From: Sean Christopherson <seanjc@google.com>
To: Yosry Ahmed <yosry@kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Jim Mattson <jmattson@google.com>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 3/7] KVM: SVM: Move RAX legality check to SVM insn interception handlers
Date: Fri, 13 Mar 2026 15:44:18 -0700 [thread overview]
Message-ID: <abSTQifukogF5yEF@google.com> (raw)
In-Reply-To: <CAO9r8zNdmGK6EKnNHDNC9pZQh7+jxjHOsJin9Kaijk1hs0uX6Q@mail.gmail.com>
On Fri, Mar 13, 2026, Yosry Ahmed wrote:
> > @@ -2306,24 +2312,18 @@ static int gp_interception(struct kvm_vcpu *vcpu)
> > goto reinject;
> >
> > opcode = svm_instr_opcode(vcpu);
> > + if (opcode != NONE_SVM_INSTR)
> > + return emulate_svm_instr(vcpu, opcode);
> >
> > - if (opcode == NONE_SVM_INSTR) {
> > - if (!enable_vmware_backdoor)
> > - goto reinject;
> > -
> > - /*
> > - * VMware backdoor emulation on #GP interception only handles
> > - * IN{S}, OUT{S}, and RDPMC.
> > - */
> > - if (!is_guest_mode(vcpu))
> > - return kvm_emulate_instruction(vcpu,
> > - EMULTYPE_VMWARE_GP | EMULTYPE_NO_DECODE);
> > - } else {
> > - if (!page_address_valid(vcpu, svm->vmcb->save.rax))
> > - goto reinject;
> > + if (!enable_vmware_backdoor)
> > + goto reinject;
> >
> > - return emulate_svm_instr(vcpu, opcode);
> > - }
> > + /*
> > + * VMware backdoor emulation on #GP interception only handles
> > + * IN{S}, OUT{S}, and RDPMC.
> > + */
> > + if (!is_guest_mode(vcpu))
> > + return kvm_emulate_instruction(vcpu, EMULTYPE_VMWARE_GP | EMULTYPE_NO_DECODE);
>
> AI review pointed out that we should not drop the page_address_valid()
> from here, because if an SVM instruction is executed by L2, and KVM
> intercepts the #GP, it should re-inject the #GP into L2 if RAX is
> illegal instead of synthesizing a #VMEXIT to L1.
No, because the intercept has higher priority than the #GP due to bad RAX.
> My initial instincth is to keep the check here as well as in the intercept
> handlers, but no, L1's intercept should take precedence over #GP due to
> invalid RAX anyway. In fact, if L1 has the intercept set, then it must be set
> in vmcb02, and KVM would get a #VMEXIT on the intercept not on #GP.
Except for the erratum case.
> The actual problem is that the current code does not check if L1
> actually sets the intercept in emulate_svm_instr().
Oh dagnabbit. I had thought about this, multiple times, but wrote it off as a
non-issue because if L1 wanted to intercept VMWHATEVER, KVM would set the intercept
in vmcb02 and would get _that_ instead of a #GP. But the erratum case means that
hardware could have signaled #GP even when the instruction should have been
intercepted.
And I also forgot the KVM could be intercepting #GP for the VMware crud, which
would unintentionally grab the CPL case too. Darn kitchen sink #GPs.
> So if L1 and KVM do not set the intercept, and RAX is invalid, the current
> code could synthesize a spurious #VMEXIT to L1 instead of reinjecting #GP.
> The existing check on RAX prevents that, but it doesn't really fix the
> problem because if we get #GP due to CPL != 0, we'll still generate a
> spurious #VMEXIT to L1. What we really should be doing in gp_interception()
> is:
>
> 1. if CPL != 0, re-inject #GP.
> 2. If in guest mode and L1 intercepts the instruction, synthesize a #VMEXIT.
> 3. Otherwise emulate the instruction, which would take care of
> re-injecting the #GP if RAX is invalid with this patch.
>
> Something like this on top (over 2 patches):
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index cf5ebdc4b27bf..8942272eb80b2 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -2237,10 +2237,11 @@ static int emulate_svm_instr(struct kvm_vcpu
> *vcpu, int opcode)
> [SVM_INSTR_VMLOAD] = vmload_interception,
> [SVM_INSTR_VMSAVE] = vmsave_interception,
> };
> + int exit_code = guest_mode_exit_codes[opcode];
> struct vcpu_svm *svm = to_svm(vcpu);
>
> - if (is_guest_mode(vcpu)) {
> - nested_svm_simple_vmexit(svm, guest_mode_exit_codes[opcode]);
> + if (is_guest_mode(vcpu) &&
> vmcb12_is_intercept(&svm->nested.ctl, exit_code))
> + nested_svm_simple_vmexit(svm, exit_code);
> return 1;
> }
> return svm_instr_handlers[opcode](vcpu);
> @@ -2269,8 +2270,11 @@ static int gp_interception(struct kvm_vcpu *vcpu)
> goto reinject;
>
> opcode = svm_instr_opcode(vcpu);
> - if (opcode != NONE_SVM_INSTR)
> + if (opcode != NONE_SVM_INSTR) {
> + if (svm->vmcb->save.cpl)
> + goto reinject;
Don't you need the page_address_valid() check here? Ooooh, no, because either
emulate_svm_instr() will synthesize #VMEXIT, or svm_instr_handlers() will take
care of the #GP. It's only CPL that needs to be checked early, because it has
priority over the #VMEXIT.
> return emulate_svm_instr(vcpu, opcode);
> + }
>
> if (!enable_vmware_backdoor)
> goto reinject;
>
> ---
>
> Sean, do you prefer that I send patches separately on top of this
> series or a new version with these patches included?
Go ahead and send an entirely new series. The less threads I have to chase down
after I get back, the less likely I am to screw things up :-)
next prev parent reply other threads:[~2026-03-13 22:44 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-13 0:10 [PATCH v3 0/7] KVM: SVM: Fixes for VMCB12 checks and mapping Yosry Ahmed
2026-03-13 0:10 ` [PATCH v3 1/7] KVM: SVM: Drop RAX check for SVM instructions from the emulator Yosry Ahmed
2026-03-15 12:55 ` Paolo Bonzini
2026-03-16 13:49 ` Yosry Ahmed
2026-03-16 16:28 ` Yosry Ahmed
2026-03-17 13:15 ` Paolo Bonzini
2026-03-17 14:58 ` Jim Mattson
2026-03-18 15:55 ` Paolo Bonzini
2026-03-13 0:10 ` [PATCH v3 2/7] KVM: SVM: Check that RAX has legal GPA on #GP interception of SVM insns Yosry Ahmed
2026-03-13 0:10 ` [PATCH v3 3/7] KVM: SVM: Move RAX legality check to SVM insn interception handlers Yosry Ahmed
2026-03-13 18:17 ` Yosry Ahmed
2026-03-13 22:44 ` Sean Christopherson [this message]
2026-03-13 23:08 ` Yosry Ahmed
2026-03-16 15:25 ` Yosry Ahmed
2026-03-13 0:10 ` [PATCH v3 4/7] KVM: SVM: Treat mapping failures equally in VMLOAD/VMSAVE emulation Yosry Ahmed
2026-03-13 0:10 ` [PATCH v3 5/7] KVM: nSVM: Fail emulation of VMRUN/VMLOAD/VMSAVE if mapping vmcb12 fails Yosry Ahmed
2026-03-13 0:10 ` [PATCH v3 6/7] KVM: selftests: Rework svm_nested_invalid_vmcb12_gpa Yosry Ahmed
2026-03-13 0:10 ` [PATCH v3 7/7] KVM: selftests: Drop 'invalid' from svm_nested_invalid_vmcb12_gpa's name Yosry Ahmed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=abSTQifukogF5yEF@google.com \
--to=seanjc@google.com \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=yosry@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.