* [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling
2026-01-12 17:45 [PATCH V2 0/5] Align SVM with APM defined behaviors Kevin Cheng
@ 2026-01-12 17:45 ` Kevin Cheng
2026-01-12 20:37 ` Yosry Ahmed
2026-01-12 17:45 ` [PATCH V2 2/5] KVM: SVM: Inject #UD for STGI if EFER.SVME=0 and SVM Lock and DEV are not available Kevin Cheng
` (3 subsequent siblings)
4 siblings, 1 reply; 18+ messages in thread
From: Kevin Cheng @ 2026-01-12 17:45 UTC (permalink / raw)
To: seanjc, pbonzini; +Cc: kvm, linux-kernel, yosry.ahmed, Kevin Cheng
Similar to VMLOAD/VMSAVE intercept handling, move the STGI/CLGI
intercept handling to svm_recalc_instruction_intercepts().
---
arch/x86/kvm/svm/svm.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 24d59ccfa40d9..6373a25d85479 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1010,6 +1010,11 @@ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
svm_clr_intercept(svm, INTERCEPT_VMSAVE);
svm->vmcb->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
}
+
+ if (vgif) {
+ svm_clr_intercept(svm, INTERCEPT_STGI);
+ svm_clr_intercept(svm, INTERCEPT_CLGI);
+ }
}
}
@@ -1147,11 +1152,8 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool init_event)
if (vnmi)
svm->vmcb->control.int_ctl |= V_NMI_ENABLE_MASK;
- if (vgif) {
- svm_clr_intercept(svm, INTERCEPT_STGI);
- svm_clr_intercept(svm, INTERCEPT_CLGI);
+ if (vgif)
svm->vmcb->control.int_ctl |= V_GIF_ENABLE_MASK;
- }
if (vcpu->kvm->arch.bus_lock_detection_enabled)
svm_set_intercept(svm, INTERCEPT_BUSLOCK);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling
2026-01-12 17:45 ` [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling Kevin Cheng
@ 2026-01-12 20:37 ` Yosry Ahmed
2026-01-15 1:39 ` Sean Christopherson
0 siblings, 1 reply; 18+ messages in thread
From: Yosry Ahmed @ 2026-01-12 20:37 UTC (permalink / raw)
To: Kevin Cheng; +Cc: seanjc, pbonzini, kvm, linux-kernel
On Mon, Jan 12, 2026 at 05:45:31PM +0000, Kevin Cheng wrote:
> Similar to VMLOAD/VMSAVE intercept handling, move the STGI/CLGI
> intercept handling to svm_recalc_instruction_intercepts().
> ---
> arch/x86/kvm/svm/svm.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 24d59ccfa40d9..6373a25d85479 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -1010,6 +1010,11 @@ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
> svm_clr_intercept(svm, INTERCEPT_VMSAVE);
> svm->vmcb->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
> }
> +
> + if (vgif) {
> + svm_clr_intercept(svm, INTERCEPT_STGI);
Could this cause a problem with NMI window tracking?
svm_enable_nmi_window() sets INTERCEPT_STGI to detect when NMIs are
enabled, and it's later cleared by svm_set_gif(). If we recalc
intercepts in between we will clear the intercept here and miss NMI
enablement.
We could move the logic to set/clear INTERCEPT_STGI for NMI window
tracking here as well, but then we'll need to recalc intercepts in
svm_enable_nmi_window() and svm_set_gif(), which could be expensive.
The alternative is perhaps setting a flag when INTERCEPT_STGI is set in
svm_enable_nmi_window() and avoid clearing the intercept here if the
flag is set.
Not sure what's the best way forward here.
> + svm_clr_intercept(svm, INTERCEPT_CLGI);
> + }
> }
> }
>
> @@ -1147,11 +1152,8 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool init_event)
> if (vnmi)
> svm->vmcb->control.int_ctl |= V_NMI_ENABLE_MASK;
>
> - if (vgif) {
> - svm_clr_intercept(svm, INTERCEPT_STGI);
> - svm_clr_intercept(svm, INTERCEPT_CLGI);
> + if (vgif)
> svm->vmcb->control.int_ctl |= V_GIF_ENABLE_MASK;
> - }
>
> if (vcpu->kvm->arch.bus_lock_detection_enabled)
> svm_set_intercept(svm, INTERCEPT_BUSLOCK);
> --
> 2.52.0.457.g6b5491de43-goog
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling
2026-01-12 20:37 ` Yosry Ahmed
@ 2026-01-15 1:39 ` Sean Christopherson
2026-01-15 16:41 ` Yosry Ahmed
0 siblings, 1 reply; 18+ messages in thread
From: Sean Christopherson @ 2026-01-15 1:39 UTC (permalink / raw)
To: Yosry Ahmed; +Cc: Kevin Cheng, pbonzini, kvm, linux-kernel
On Mon, Jan 12, 2026, Yosry Ahmed wrote:
> On Mon, Jan 12, 2026 at 05:45:31PM +0000, Kevin Cheng wrote:
> > Similar to VMLOAD/VMSAVE intercept handling, move the STGI/CLGI
> > intercept handling to svm_recalc_instruction_intercepts().
> > ---
> > arch/x86/kvm/svm/svm.c | 10 ++++++----
> > 1 file changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> > index 24d59ccfa40d9..6373a25d85479 100644
> > --- a/arch/x86/kvm/svm/svm.c
> > +++ b/arch/x86/kvm/svm/svm.c
> > @@ -1010,6 +1010,11 @@ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
> > svm_clr_intercept(svm, INTERCEPT_VMSAVE);
> > svm->vmcb->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
> > }
> > +
> > + if (vgif) {
> > + svm_clr_intercept(svm, INTERCEPT_STGI);
>
> Could this cause a problem with NMI window tracking?
Yes.
> svm_enable_nmi_window() sets INTERCEPT_STGI to detect when NMIs are
> enabled, and it's later cleared by svm_set_gif(). If we recalc
> intercepts in between we will clear the intercept here and miss NMI
> enablement.
>
> We could move the logic to set/clear INTERCEPT_STGI for NMI window
> tracking here as well, but then we'll need to recalc intercepts in
> svm_enable_nmi_window() and svm_set_gif(), which could be expensive.
>
> The alternative is perhaps setting a flag when INTERCEPT_STGI is set in
> svm_enable_nmi_window() and avoid clearing the intercept here if the
> flag is set.
>
> Not sure what's the best way forward here.
First things first, the changelog needs to state _why_ the code is being moved.
"To be like VMLOAD/VMSAVE" doesn't suffice, because my initial answer was going
to be "well just don't move the code" (I already forgot the context of v1).
But moving the code is needed to fix the missing #UD in "Recalc instructions
intercepts when EFER.SVME is toggled".
As for how to fix this, a few ideas:
1. Set KVM_REQ_EVENT to force KVM to re-evulate all events. kvm_check_and_inject_events()
will see the pending NMI and/or SMI, that the NMI/SMI is not allowed, and
re-call enable_{nmi,smi}_window().
2. Manually check for pending+blocked NMI/SMIs.
3. Combine parts of #1 and #2. Set KVM_REQ_EVENT, but only if there's a pending
NMI or SMI.
4. Add flags to vcpu_svm to explicitly track if a vCPU has an NMI/SMI window,
similar to what we're planning on doing for IRQs[*], and use that to more
confidently do the right thing when recomputing intercepts.
I don't love any of those ideas. Ah, at least not until I poke around KVM. In
svm_set_gif() there's already this:
if (svm->vcpu.arch.smi_pending ||
svm->vcpu.arch.nmi_pending ||
kvm_cpu_has_injectable_intr(&svm->vcpu) ||
kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
So I think it makes sense to bundle that into a helper, e.g. (no idea what to
call it)
static bool svm_think_of_a_good_name(struct kvm_vcpu *vcpu)
{
if (svm->vcpu.arch.smi_pending ||
svm->vcpu.arch.nmi_pending ||
kvm_cpu_has_injectable_intr(&svm->vcpu) ||
kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
}
And then call that from svm_recalc_instruction_intercepts(). That implements #3
in a fairly maintainable way (we'll hopefully notice sooner than later if we break
svm_set_gif()).
https://lore.kernel.org/all/26732815475bf1c5ba672bc3b1785265f1a994e6.1752819570.git.naveen@kernel.org
> > + svm_clr_intercept(svm, INTERCEPT_CLGI);
> > + }
> > }
> > }
> >
> > @@ -1147,11 +1152,8 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool init_event)
> > if (vnmi)
> > svm->vmcb->control.int_ctl |= V_NMI_ENABLE_MASK;
> >
> > - if (vgif) {
> > - svm_clr_intercept(svm, INTERCEPT_STGI);
> > - svm_clr_intercept(svm, INTERCEPT_CLGI);
> > + if (vgif)
> > svm->vmcb->control.int_ctl |= V_GIF_ENABLE_MASK;
> > - }
> >
> > if (vcpu->kvm->arch.bus_lock_detection_enabled)
> > svm_set_intercept(svm, INTERCEPT_BUSLOCK);
> > --
> > 2.52.0.457.g6b5491de43-goog
> >
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling
2026-01-15 1:39 ` Sean Christopherson
@ 2026-01-15 16:41 ` Yosry Ahmed
2026-01-15 17:00 ` Sean Christopherson
0 siblings, 1 reply; 18+ messages in thread
From: Yosry Ahmed @ 2026-01-15 16:41 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Kevin Cheng, pbonzini, kvm, linux-kernel
On Wed, Jan 14, 2026 at 05:39:13PM -0800, Sean Christopherson wrote:
> On Mon, Jan 12, 2026, Yosry Ahmed wrote:
> > On Mon, Jan 12, 2026 at 05:45:31PM +0000, Kevin Cheng wrote:
> > > Similar to VMLOAD/VMSAVE intercept handling, move the STGI/CLGI
> > > intercept handling to svm_recalc_instruction_intercepts().
> > > ---
> > > arch/x86/kvm/svm/svm.c | 10 ++++++----
> > > 1 file changed, 6 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> > > index 24d59ccfa40d9..6373a25d85479 100644
> > > --- a/arch/x86/kvm/svm/svm.c
> > > +++ b/arch/x86/kvm/svm/svm.c
> > > @@ -1010,6 +1010,11 @@ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
> > > svm_clr_intercept(svm, INTERCEPT_VMSAVE);
> > > svm->vmcb->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
> > > }
> > > +
> > > + if (vgif) {
> > > + svm_clr_intercept(svm, INTERCEPT_STGI);
> >
> > Could this cause a problem with NMI window tracking?
>
> Yes.
>
> > svm_enable_nmi_window() sets INTERCEPT_STGI to detect when NMIs are
> > enabled, and it's later cleared by svm_set_gif(). If we recalc
> > intercepts in between we will clear the intercept here and miss NMI
> > enablement.
> >
> > We could move the logic to set/clear INTERCEPT_STGI for NMI window
> > tracking here as well, but then we'll need to recalc intercepts in
> > svm_enable_nmi_window() and svm_set_gif(), which could be expensive.
> >
> > The alternative is perhaps setting a flag when INTERCEPT_STGI is set in
> > svm_enable_nmi_window() and avoid clearing the intercept here if the
> > flag is set.
> >
> > Not sure what's the best way forward here.
>
> First things first, the changelog needs to state _why_ the code is being moved.
> "To be like VMLOAD/VMSAVE" doesn't suffice, because my initial answer was going
> to be "well just don't move the code" (I already forgot the context of v1).
>
> But moving the code is needed to fix the missing #UD in "Recalc instructions
> intercepts when EFER.SVME is toggled".
>
> As for how to fix this, a few ideas:
>
> 1. Set KVM_REQ_EVENT to force KVM to re-evulate all events. kvm_check_and_inject_events()
> will see the pending NMI and/or SMI, that the NMI/SMI is not allowed, and
> re-call enable_{nmi,smi}_window().
>
> 2. Manually check for pending+blocked NMI/SMIs.
>
> 3. Combine parts of #1 and #2. Set KVM_REQ_EVENT, but only if there's a pending
> NMI or SMI.
>
> 4. Add flags to vcpu_svm to explicitly track if a vCPU has an NMI/SMI window,
> similar to what we're planning on doing for IRQs[*], and use that to more
> confidently do the right thing when recomputing intercepts.
>
> I don't love any of those ideas. Ah, at least not until I poke around KVM. In
> svm_set_gif() there's already this:
>
> if (svm->vcpu.arch.smi_pending ||
> svm->vcpu.arch.nmi_pending ||
> kvm_cpu_has_injectable_intr(&svm->vcpu) ||
> kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
> kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
>
> So I think it makes sense to bundle that into a helper, e.g. (no idea what to
> call it)
>
> static bool svm_think_of_a_good_name(struct kvm_vcpu *vcpu)
> {
> if (svm->vcpu.arch.smi_pending ||
> svm->vcpu.arch.nmi_pending ||
> kvm_cpu_has_injectable_intr(&svm->vcpu) ||
> kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
> kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
> }
Maybe svm_check_gif_events() or svm_check_gif_interrupts()?
Or maybe it's clearer if we just put the checks in a helper like
svm_waiting_for_gif() or svm_pending_gif_interrupt().
Then in svm_recalc_instruction_intercepts() we do:
/*
* If there is a pending interrupt controlled by GIF, set
* KVM_REQ_EVENT to re-evaluate if the intercept needs to be set
* again to track when GIF is re-enabled (e.g. for NMI
* injection).
*/
svm_clr_intercept(svm, INTERCEPT_STGI);
if (svm_pending_gif_interrupt())
kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
and in svm_set_gif() it reads well semantically:
enable_gif(svm);
if (svm_pending_gif_interrupt())
kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
>
> And then call that from svm_recalc_instruction_intercepts(). That implements #3
> in a fairly maintainable way (we'll hopefully notice sooner than later if we break
> svm_set_gif()).
>
> https://lore.kernel.org/all/26732815475bf1c5ba672bc3b1785265f1a994e6.1752819570.git.naveen@kernel.org
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling
2026-01-15 16:41 ` Yosry Ahmed
@ 2026-01-15 17:00 ` Sean Christopherson
2026-01-15 17:05 ` Yosry Ahmed
0 siblings, 1 reply; 18+ messages in thread
From: Sean Christopherson @ 2026-01-15 17:00 UTC (permalink / raw)
To: Yosry Ahmed; +Cc: Kevin Cheng, pbonzini, kvm, linux-kernel
On Thu, Jan 15, 2026, Yosry Ahmed wrote:
> On Wed, Jan 14, 2026 at 05:39:13PM -0800, Sean Christopherson wrote:
> > On Mon, Jan 12, 2026, Yosry Ahmed wrote:
> > As for how to fix this, a few ideas:
> >
> > 1. Set KVM_REQ_EVENT to force KVM to re-evulate all events. kvm_check_and_inject_events()
> > will see the pending NMI and/or SMI, that the NMI/SMI is not allowed, and
> > re-call enable_{nmi,smi}_window().
> >
> > 2. Manually check for pending+blocked NMI/SMIs.
> >
> > 3. Combine parts of #1 and #2. Set KVM_REQ_EVENT, but only if there's a pending
> > NMI or SMI.
> >
> > 4. Add flags to vcpu_svm to explicitly track if a vCPU has an NMI/SMI window,
> > similar to what we're planning on doing for IRQs[*], and use that to more
> > confidently do the right thing when recomputing intercepts.
> >
> > I don't love any of those ideas. Ah, at least not until I poke around KVM. In
> > svm_set_gif() there's already this:
> >
> > if (svm->vcpu.arch.smi_pending ||
> > svm->vcpu.arch.nmi_pending ||
> > kvm_cpu_has_injectable_intr(&svm->vcpu) ||
> > kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
> > kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
> >
> > So I think it makes sense to bundle that into a helper, e.g. (no idea what to
> > call it)
> >
> > static bool svm_think_of_a_good_name(struct kvm_vcpu *vcpu)
> > {
> > if (svm->vcpu.arch.smi_pending ||
> > svm->vcpu.arch.nmi_pending ||
> > kvm_cpu_has_injectable_intr(&svm->vcpu) ||
> > kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
> > kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
> > }
>
> Maybe svm_check_gif_events() or svm_check_gif_interrupts()?
>
> Or maybe it's clearer if we just put the checks in a helper like
> svm_waiting_for_gif() or svm_pending_gif_interrupt().
This was my first idea as well, though I would name it svm_has_pending_gif_event()
to better align with kvm_vcpu_has_events().
I suggested a single helper because I don't love that how to react to the pending
event is duplicated. But I definitely don't object to open coding the request if
the consensus is that it's more readable overall.
> Then in svm_recalc_instruction_intercepts() we do:
>
> /*
> * If there is a pending interrupt controlled by GIF, set
> * KVM_REQ_EVENT to re-evaluate if the intercept needs to be set
> * again to track when GIF is re-enabled (e.g. for NMI
> * injection).
> */
> svm_clr_intercept(svm, INTERCEPT_STGI);
> if (svm_pending_gif_interrupt())
> kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
>
> and in svm_set_gif() it reads well semantically:
>
> enable_gif(svm);
> if (svm_pending_gif_interrupt())
> kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling
2026-01-15 17:00 ` Sean Christopherson
@ 2026-01-15 17:05 ` Yosry Ahmed
2026-01-15 17:29 ` Sean Christopherson
0 siblings, 1 reply; 18+ messages in thread
From: Yosry Ahmed @ 2026-01-15 17:05 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Kevin Cheng, pbonzini, kvm, linux-kernel
On Thu, Jan 15, 2026 at 09:00:07AM -0800, Sean Christopherson wrote:
> On Thu, Jan 15, 2026, Yosry Ahmed wrote:
> > On Wed, Jan 14, 2026 at 05:39:13PM -0800, Sean Christopherson wrote:
> > > On Mon, Jan 12, 2026, Yosry Ahmed wrote:
> > > As for how to fix this, a few ideas:
> > >
> > > 1. Set KVM_REQ_EVENT to force KVM to re-evulate all events. kvm_check_and_inject_events()
> > > will see the pending NMI and/or SMI, that the NMI/SMI is not allowed, and
> > > re-call enable_{nmi,smi}_window().
> > >
> > > 2. Manually check for pending+blocked NMI/SMIs.
> > >
> > > 3. Combine parts of #1 and #2. Set KVM_REQ_EVENT, but only if there's a pending
> > > NMI or SMI.
> > >
> > > 4. Add flags to vcpu_svm to explicitly track if a vCPU has an NMI/SMI window,
> > > similar to what we're planning on doing for IRQs[*], and use that to more
> > > confidently do the right thing when recomputing intercepts.
> > >
> > > I don't love any of those ideas. Ah, at least not until I poke around KVM. In
> > > svm_set_gif() there's already this:
> > >
> > > if (svm->vcpu.arch.smi_pending ||
> > > svm->vcpu.arch.nmi_pending ||
> > > kvm_cpu_has_injectable_intr(&svm->vcpu) ||
> > > kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
> > > kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
> > >
> > > So I think it makes sense to bundle that into a helper, e.g. (no idea what to
> > > call it)
> > >
> > > static bool svm_think_of_a_good_name(struct kvm_vcpu *vcpu)
> > > {
> > > if (svm->vcpu.arch.smi_pending ||
> > > svm->vcpu.arch.nmi_pending ||
> > > kvm_cpu_has_injectable_intr(&svm->vcpu) ||
> > > kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
> > > kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
> > > }
> >
> > Maybe svm_check_gif_events() or svm_check_gif_interrupts()?
> >
> > Or maybe it's clearer if we just put the checks in a helper like
> > svm_waiting_for_gif() or svm_pending_gif_interrupt().
>
> This was my first idea as well, though I would name it svm_has_pending_gif_event()
> to better align with kvm_vcpu_has_events().
svm_has_pending_gif_event() sounds good.
>
> I suggested a single helper because I don't love that how to react to the pending
> event is duplicated. But I definitely don't object to open coding the request if
> the consensus is that it's more readable overall.
A single helper is nice, but I can't think of a name that would read
well. My first instinct is svm_check_pending_gif_event(), but we are not
really checking the event as much as requesting for it to be checked.
We can do svm_request_gif_event(), perhaps? Not sure if that's better or
worse than svm_has_pending_gif_event().
>
> > Then in svm_recalc_instruction_intercepts() we do:
> >
> > /*
> > * If there is a pending interrupt controlled by GIF, set
> > * KVM_REQ_EVENT to re-evaluate if the intercept needs to be set
> > * again to track when GIF is re-enabled (e.g. for NMI
> > * injection).
> > */
> > svm_clr_intercept(svm, INTERCEPT_STGI);
> > if (svm_pending_gif_interrupt())
> > kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
> >
> > and in svm_set_gif() it reads well semantically:
> >
> > enable_gif(svm);
> > if (svm_pending_gif_interrupt())
> > kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling
2026-01-15 17:05 ` Yosry Ahmed
@ 2026-01-15 17:29 ` Sean Christopherson
2026-01-22 4:59 ` Kevin Cheng
0 siblings, 1 reply; 18+ messages in thread
From: Sean Christopherson @ 2026-01-15 17:29 UTC (permalink / raw)
To: Yosry Ahmed; +Cc: Kevin Cheng, pbonzini, kvm, linux-kernel
On Thu, Jan 15, 2026, Yosry Ahmed wrote:
> On Thu, Jan 15, 2026 at 09:00:07AM -0800, Sean Christopherson wrote:
> > On Thu, Jan 15, 2026, Yosry Ahmed wrote:
> > > Or maybe it's clearer if we just put the checks in a helper like
> > > svm_waiting_for_gif() or svm_pending_gif_interrupt().
> >
> > This was my first idea as well, though I would name it svm_has_pending_gif_event()
> > to better align with kvm_vcpu_has_events().
>
> svm_has_pending_gif_event() sounds good.
>
> >
> > I suggested a single helper because I don't love that how to react to the pending
> > event is duplicated. But I definitely don't object to open coding the request if
> > the consensus is that it's more readable overall.
>
> A single helper is nice, but I can't think of a name that would read
> well. My first instinct is svm_check_pending_gif_event(), but we are not
> really checking the event as much as requesting for it to be checked.
Ya, that's the same problem I'm having. I can't even come up with an absurdly
verbose name to describe the behavior.
> We can do svm_request_gif_event(), perhaps? Not sure if that's better or
> worse than svm_has_pending_gif_event().
Definitely worse in my opinion. My entire motivation for a single helper would
be to avoid bleeding implementation details (use of KVM_REQ_EVENT) to trigger
the potential re-evaluation STGI/CLGI intercepts. And then there's the fact that
in most cases, there probably isn't a pending event, i.e. not request will be
made.
Let's just go with svm_has_pending_gif_event().
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling
2026-01-15 17:29 ` Sean Christopherson
@ 2026-01-22 4:59 ` Kevin Cheng
0 siblings, 0 replies; 18+ messages in thread
From: Kevin Cheng @ 2026-01-22 4:59 UTC (permalink / raw)
To: Sean Christopherson; +Cc: Yosry Ahmed, pbonzini, kvm, linux-kernel
On Thu, Jan 15, 2026 at 12:29 PM Sean Christopherson <seanjc@google.com> wrote:
>
> On Thu, Jan 15, 2026, Yosry Ahmed wrote:
> > On Thu, Jan 15, 2026 at 09:00:07AM -0800, Sean Christopherson wrote:
> > > On Thu, Jan 15, 2026, Yosry Ahmed wrote:
> > > > Or maybe it's clearer if we just put the checks in a helper like
> > > > svm_waiting_for_gif() or svm_pending_gif_interrupt().
> > >
> > > This was my first idea as well, though I would name it svm_has_pending_gif_event()
> > > to better align with kvm_vcpu_has_events().
> >
> > svm_has_pending_gif_event() sounds good.
> >
> > >
> > > I suggested a single helper because I don't love that how to react to the pending
> > > event is duplicated. But I definitely don't object to open coding the request if
> > > the consensus is that it's more readable overall.
> >
> > A single helper is nice, but I can't think of a name that would read
> > well. My first instinct is svm_check_pending_gif_event(), but we are not
> > really checking the event as much as requesting for it to be checked.
>
> Ya, that's the same problem I'm having. I can't even come up with an absurdly
> verbose name to describe the behavior.
>
> > We can do svm_request_gif_event(), perhaps? Not sure if that's better or
> > worse than svm_has_pending_gif_event().
>
> Definitely worse in my opinion. My entire motivation for a single helper would
> be to avoid bleeding implementation details (use of KVM_REQ_EVENT) to trigger
> the potential re-evaluation STGI/CLGI intercepts. And then there's the fact that
> in most cases, there probably isn't a pending event, i.e. not request will be
> made.
>
> Let's just go with svm_has_pending_gif_event().
Sounds good. Thanks for the suggestions Yosry and Sean :) And thanks
for catching this!
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH V2 2/5] KVM: SVM: Inject #UD for STGI if EFER.SVME=0 and SVM Lock and DEV are not available
2026-01-12 17:45 [PATCH V2 0/5] Align SVM with APM defined behaviors Kevin Cheng
2026-01-12 17:45 ` [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling Kevin Cheng
@ 2026-01-12 17:45 ` Kevin Cheng
2026-01-12 20:50 ` Yosry Ahmed
2026-01-12 17:45 ` [PATCH V2 3/5] KVM: SVM: Inject #UD for INVLPGA if EFER.SVME=0 Kevin Cheng
` (2 subsequent siblings)
4 siblings, 1 reply; 18+ messages in thread
From: Kevin Cheng @ 2026-01-12 17:45 UTC (permalink / raw)
To: seanjc, pbonzini; +Cc: kvm, linux-kernel, yosry.ahmed, Kevin Cheng
The AMD APM states that STGI causes a #UD if SVM is not enabled and
neither SVM Lock nor the device exclusion vector (DEV) are supported.
Fix the STGI exit handler by injecting #UD when these conditions are
met.
Signed-off-by: Kevin Cheng <chengkev@google.com>
---
arch/x86/kvm/svm/svm.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 6373a25d85479..557c84a060fc6 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2271,8 +2271,18 @@ static int stgi_interception(struct kvm_vcpu *vcpu)
{
int ret;
- if (nested_svm_check_permissions(vcpu))
+ if ((!(vcpu->arch.efer & EFER_SVME) &&
+ !guest_cpu_cap_has(vcpu, X86_FEATURE_SVML) &&
+ !guest_cpu_cap_has(vcpu, X86_FEATURE_SKINIT)) ||
+ !is_paging(vcpu)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ if (to_svm(vcpu)->vmcb->save.cpl) {
+ kvm_inject_gp(vcpu, 0);
return 1;
+ }
ret = kvm_skip_emulated_instruction(vcpu);
svm_set_gif(to_svm(vcpu), true);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V2 2/5] KVM: SVM: Inject #UD for STGI if EFER.SVME=0 and SVM Lock and DEV are not available
2026-01-12 17:45 ` [PATCH V2 2/5] KVM: SVM: Inject #UD for STGI if EFER.SVME=0 and SVM Lock and DEV are not available Kevin Cheng
@ 2026-01-12 20:50 ` Yosry Ahmed
2026-01-22 5:02 ` Kevin Cheng
0 siblings, 1 reply; 18+ messages in thread
From: Yosry Ahmed @ 2026-01-12 20:50 UTC (permalink / raw)
To: Kevin Cheng; +Cc: seanjc, pbonzini, kvm, linux-kernel
On Mon, Jan 12, 2026 at 05:45:32PM +0000, Kevin Cheng wrote:
> The AMD APM states that STGI causes a #UD if SVM is not enabled and
> neither SVM Lock nor the device exclusion vector (DEV) are supported.
Might be useful to also mention the following part "Support for DEV is
part of the SKINIT architecture".
> Fix the STGI exit handler by injecting #UD when these conditions are
> met.
>
> Signed-off-by: Kevin Cheng <chengkev@google.com>
> ---
> arch/x86/kvm/svm/svm.c | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 6373a25d85479..557c84a060fc6 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -2271,8 +2271,18 @@ static int stgi_interception(struct kvm_vcpu *vcpu)
> {
> int ret;
>
> - if (nested_svm_check_permissions(vcpu))
> + if ((!(vcpu->arch.efer & EFER_SVME) &&
> + !guest_cpu_cap_has(vcpu, X86_FEATURE_SVML) &&
> + !guest_cpu_cap_has(vcpu, X86_FEATURE_SKINIT)) ||
> + !is_paging(vcpu)) {
> + kvm_queue_exception(vcpu, UD_VECTOR);
> + return 1;
> + }
> +
> + if (to_svm(vcpu)->vmcb->save.cpl) {
> + kvm_inject_gp(vcpu, 0);
> return 1;
> + }
Not a big fan of open-coding nested_svm_check_permissions() here. The
checks could get out of sync.
How about refactoring nested_svm_check_permissions() like so:
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index f295a41ec659..7f53c54b9d39 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -1520,9 +1520,10 @@ int nested_svm_exit_handled(struct vcpu_svm *svm)
return vmexit;
}
-int nested_svm_check_permissions(struct kvm_vcpu *vcpu)
+static int __nested_svm_check_permissions(struct kvm_vcpu *vcpu,
+ bool insn_allowed)
{
- if (!(vcpu->arch.efer & EFER_SVME) || !is_paging(vcpu)) {
+ if (!insn_allowed || !is_paging(vcpu)) {
kvm_queue_exception(vcpu, UD_VECTOR);
return 1;
}
@@ -1535,6 +1536,11 @@ int nested_svm_check_permissions(struct kvm_vcpu *vcpu)
return 0;
}
+int nested_svm_check_permissions(struct kvm_vcpu *vcpu)
+{
+ return __nested_svm_check_permissions(vcpu, vcpu->arch.efer & EFER_SVME);
+}
+
static bool nested_svm_is_exception_vmexit(struct kvm_vcpu *vcpu, u8 vector,
u32 error_code)
{
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 7041498a8091..6340c4ce323c 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2333,9 +2333,19 @@ void svm_set_gif(struct vcpu_svm *svm, bool value)
static int stgi_interception(struct kvm_vcpu *vcpu)
{
+ bool insn_allowed;
int ret;
- if (nested_svm_check_permissions(vcpu))
+ /*
+ * According to the APM, STGI is allowed even with SVM disabled if SVM
+ * Lock or device exclusion vector (DEV) are supported. DEV is part of
+ * the SKINIT architecture.
+ */
+ insn_allowed = (vcpu->arch.efer & EFER_SVME) ||
+ guest_cpu_cap_has(vcpu, X86_FEATURE_SVML) ||
+ guest_cpu_cap_has(vcpu, X86_FEATURE_SKINIT);
+
+ if (__nested_svm_check_permissions(vcpu, insn_allowed))
return 1;
ret = kvm_skip_emulated_instruction(vcpu);
---
We may also want to rename nested_svm_check_permissions() to
nested_svm_insn_check_permissions() or something. Sean, WDYT?
>
> ret = kvm_skip_emulated_instruction(vcpu);
> svm_set_gif(to_svm(vcpu), true);
> --
> 2.52.0.457.g6b5491de43-goog
>
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V2 2/5] KVM: SVM: Inject #UD for STGI if EFER.SVME=0 and SVM Lock and DEV are not available
2026-01-12 20:50 ` Yosry Ahmed
@ 2026-01-22 5:02 ` Kevin Cheng
0 siblings, 0 replies; 18+ messages in thread
From: Kevin Cheng @ 2026-01-22 5:02 UTC (permalink / raw)
To: Yosry Ahmed; +Cc: seanjc, pbonzini, kvm, linux-kernel
On Mon, Jan 12, 2026 at 3:50 PM Yosry Ahmed <yosry.ahmed@linux.dev> wrote:
>
> On Mon, Jan 12, 2026 at 05:45:32PM +0000, Kevin Cheng wrote:
> > The AMD APM states that STGI causes a #UD if SVM is not enabled and
> > neither SVM Lock nor the device exclusion vector (DEV) are supported.
>
> Might be useful to also mention the following part "Support for DEV is
> part of the SKINIT architecture".
>
> > Fix the STGI exit handler by injecting #UD when these conditions are
> > met.
> >
> > Signed-off-by: Kevin Cheng <chengkev@google.com>
> > ---
> > arch/x86/kvm/svm/svm.c | 12 +++++++++++-
> > 1 file changed, 11 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> > index 6373a25d85479..557c84a060fc6 100644
> > --- a/arch/x86/kvm/svm/svm.c
> > +++ b/arch/x86/kvm/svm/svm.c
> > @@ -2271,8 +2271,18 @@ static int stgi_interception(struct kvm_vcpu *vcpu)
> > {
> > int ret;
> >
> > - if (nested_svm_check_permissions(vcpu))
> > + if ((!(vcpu->arch.efer & EFER_SVME) &&
> > + !guest_cpu_cap_has(vcpu, X86_FEATURE_SVML) &&
> > + !guest_cpu_cap_has(vcpu, X86_FEATURE_SKINIT)) ||
> > + !is_paging(vcpu)) {
> > + kvm_queue_exception(vcpu, UD_VECTOR);
> > + return 1;
> > + }
> > +
> > + if (to_svm(vcpu)->vmcb->save.cpl) {
> > + kvm_inject_gp(vcpu, 0);
> > return 1;
> > + }
>
> Not a big fan of open-coding nested_svm_check_permissions() here. The
> checks could get out of sync.
>
> How about refactoring nested_svm_check_permissions() like so:
>
> diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
> index f295a41ec659..7f53c54b9d39 100644
> --- a/arch/x86/kvm/svm/nested.c
> +++ b/arch/x86/kvm/svm/nested.c
> @@ -1520,9 +1520,10 @@ int nested_svm_exit_handled(struct vcpu_svm *svm)
> return vmexit;
> }
>
> -int nested_svm_check_permissions(struct kvm_vcpu *vcpu)
> +static int __nested_svm_check_permissions(struct kvm_vcpu *vcpu,
> + bool insn_allowed)
> {
> - if (!(vcpu->arch.efer & EFER_SVME) || !is_paging(vcpu)) {
> + if (!insn_allowed || !is_paging(vcpu)) {
> kvm_queue_exception(vcpu, UD_VECTOR);
> return 1;
> }
> @@ -1535,6 +1536,11 @@ int nested_svm_check_permissions(struct kvm_vcpu *vcpu)
> return 0;
> }
>
> +int nested_svm_check_permissions(struct kvm_vcpu *vcpu)
> +{
> + return __nested_svm_check_permissions(vcpu, vcpu->arch.efer & EFER_SVME);
> +}
> +
> static bool nested_svm_is_exception_vmexit(struct kvm_vcpu *vcpu, u8 vector,
> u32 error_code)
> {
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 7041498a8091..6340c4ce323c 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -2333,9 +2333,19 @@ void svm_set_gif(struct vcpu_svm *svm, bool value)
>
> static int stgi_interception(struct kvm_vcpu *vcpu)
> {
> + bool insn_allowed;
> int ret;
>
> - if (nested_svm_check_permissions(vcpu))
> + /*
> + * According to the APM, STGI is allowed even with SVM disabled if SVM
> + * Lock or device exclusion vector (DEV) are supported. DEV is part of
> + * the SKINIT architecture.
> + */
> + insn_allowed = (vcpu->arch.efer & EFER_SVME) ||
> + guest_cpu_cap_has(vcpu, X86_FEATURE_SVML) ||
> + guest_cpu_cap_has(vcpu, X86_FEATURE_SKINIT);
> +
> + if (__nested_svm_check_permissions(vcpu, insn_allowed))
> return 1;
>
> ret = kvm_skip_emulated_instruction(vcpu);
>
> ---
>
> We may also want to rename nested_svm_check_permissions() to
> nested_svm_insn_check_permissions() or something. Sean, WDYT?
I just sent out v3 without the rename for now. Sean, if you prefer
nested_svm_insn_check_permissions over nested_svm_check_permissions
let me know and I can change along with any final revisions.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH V2 3/5] KVM: SVM: Inject #UD for INVLPGA if EFER.SVME=0
2026-01-12 17:45 [PATCH V2 0/5] Align SVM with APM defined behaviors Kevin Cheng
2026-01-12 17:45 ` [PATCH V2 1/5] KVM: SVM: Move STGI and CLGI intercept handling Kevin Cheng
2026-01-12 17:45 ` [PATCH V2 2/5] KVM: SVM: Inject #UD for STGI if EFER.SVME=0 and SVM Lock and DEV are not available Kevin Cheng
@ 2026-01-12 17:45 ` Kevin Cheng
2026-01-12 20:51 ` Yosry Ahmed
2026-01-12 17:45 ` [PATCH V2 4/5] KVM: SVM: Recalc instructions intercepts when EFER.SVME is toggled Kevin Cheng
2026-01-12 17:45 ` [PATCH V2 5/5] KVM: SVM: Raise #UD if VMMCALL instruction is not intercepted Kevin Cheng
4 siblings, 1 reply; 18+ messages in thread
From: Kevin Cheng @ 2026-01-12 17:45 UTC (permalink / raw)
To: seanjc, pbonzini; +Cc: kvm, linux-kernel, yosry.ahmed, Kevin Cheng
INVLPGA should cause a #UD when EFER.SVME is not set. Add a check to
properly inject #UD when EFER.SVME=0.
Signed-off-by: Kevin Cheng <chengkev@google.com>
---
arch/x86/kvm/svm/svm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 557c84a060fc6..92a2faff1ccc8 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2306,6 +2306,9 @@ static int invlpga_interception(struct kvm_vcpu *vcpu)
gva_t gva = kvm_rax_read(vcpu);
u32 asid = kvm_rcx_read(vcpu);
+ if (nested_svm_check_permissions(vcpu))
+ return 1;
+
/* FIXME: Handle an address size prefix. */
if (!is_long_mode(vcpu))
gva = (u32)gva;
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH V2 3/5] KVM: SVM: Inject #UD for INVLPGA if EFER.SVME=0
2026-01-12 17:45 ` [PATCH V2 3/5] KVM: SVM: Inject #UD for INVLPGA if EFER.SVME=0 Kevin Cheng
@ 2026-01-12 20:51 ` Yosry Ahmed
0 siblings, 0 replies; 18+ messages in thread
From: Yosry Ahmed @ 2026-01-12 20:51 UTC (permalink / raw)
To: Kevin Cheng; +Cc: seanjc, pbonzini, kvm, linux-kernel
On Mon, Jan 12, 2026 at 05:45:33PM +0000, Kevin Cheng wrote:
> INVLPGA should cause a #UD when EFER.SVME is not set. Add a check to
> properly inject #UD when EFER.SVME=0.
>
> Signed-off-by: Kevin Cheng <chengkev@google.com>
Reviewed-by: Yosry Ahmed <yosry.ahmed@linux.dev>
> ---
> arch/x86/kvm/svm/svm.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 557c84a060fc6..92a2faff1ccc8 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -2306,6 +2306,9 @@ static int invlpga_interception(struct kvm_vcpu *vcpu)
> gva_t gva = kvm_rax_read(vcpu);
> u32 asid = kvm_rcx_read(vcpu);
>
> + if (nested_svm_check_permissions(vcpu))
> + return 1;
> +
> /* FIXME: Handle an address size prefix. */
> if (!is_long_mode(vcpu))
> gva = (u32)gva;
> --
> 2.52.0.457.g6b5491de43-goog
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH V2 4/5] KVM: SVM: Recalc instructions intercepts when EFER.SVME is toggled
2026-01-12 17:45 [PATCH V2 0/5] Align SVM with APM defined behaviors Kevin Cheng
` (2 preceding siblings ...)
2026-01-12 17:45 ` [PATCH V2 3/5] KVM: SVM: Inject #UD for INVLPGA if EFER.SVME=0 Kevin Cheng
@ 2026-01-12 17:45 ` Kevin Cheng
2026-01-12 17:45 ` [PATCH V2 5/5] KVM: SVM: Raise #UD if VMMCALL instruction is not intercepted Kevin Cheng
4 siblings, 0 replies; 18+ messages in thread
From: Kevin Cheng @ 2026-01-12 17:45 UTC (permalink / raw)
To: seanjc, pbonzini; +Cc: kvm, linux-kernel, yosry.ahmed, Kevin Cheng
The AMD APM states that VMRUN, VMLOAD, VMSAVE, CLGI, VMMCALL, and
INVLPGA instructions should generate a #UD when EFER.SVME is cleared.
Currently, when VMLOAD, VMSAVE, or CLGI are executed in L1 with
EFER.SVME cleared, no #UD is generated in certain cases. This is because
the intercepts for these instructions are cleared based on whether or
not vls or vgif is enabled. The #UD fails to be generated when the
intercepts are absent.
Fix the missing #UD generation by ensuring that all relevant
instructions have intercepts set when SVME.EFER is disabled.
VMMCALL is special because KVM's ABI is that VMCALL/VMMCALL are always
supported for L1 and never fault.
Signed-off-by: Kevin Cheng <chengkev@google.com>
---
arch/x86/kvm/svm/svm.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 92a2faff1ccc8..92a66b62cfabd 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -243,6 +243,8 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
if (svm_gp_erratum_intercept && !sev_guest(vcpu->kvm))
set_exception_intercept(svm, GP_VECTOR);
}
+
+ kvm_make_request(KVM_REQ_RECALC_INTERCEPTS, vcpu);
}
svm->vmcb->save.efer = efer | EFER_SVME;
@@ -976,6 +978,7 @@ void svm_write_tsc_multiplier(struct kvm_vcpu *vcpu)
static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
+ u64 efer = vcpu->arch.efer;
/*
* Intercept INVPCID if shadow paging is enabled to sync/free shadow
@@ -996,7 +999,13 @@ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
svm_set_intercept(svm, INTERCEPT_RDTSCP);
}
- if (guest_cpuid_is_intel_compatible(vcpu)) {
+ /*
+ * Intercept instructions that #UD if EFER.SVME=0, as SVME must be set even
+ * when running the guest, i.e. hardware will only ever see EFER.SVME=1.
+ */
+ if (guest_cpuid_is_intel_compatible(vcpu) || !(efer & EFER_SVME)) {
+ svm_set_intercept(svm, INTERCEPT_CLGI);
+ svm_set_intercept(svm, INTERCEPT_STGI);
svm_set_intercept(svm, INTERCEPT_VMLOAD);
svm_set_intercept(svm, INTERCEPT_VMSAVE);
svm->vmcb->control.virt_ext &= ~VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH V2 5/5] KVM: SVM: Raise #UD if VMMCALL instruction is not intercepted
2026-01-12 17:45 [PATCH V2 0/5] Align SVM with APM defined behaviors Kevin Cheng
` (3 preceding siblings ...)
2026-01-12 17:45 ` [PATCH V2 4/5] KVM: SVM: Recalc instructions intercepts when EFER.SVME is toggled Kevin Cheng
@ 2026-01-12 17:45 ` Kevin Cheng
2026-01-12 20:54 ` Yosry Ahmed
2026-01-14 5:20 ` Manali Shukla
4 siblings, 2 replies; 18+ messages in thread
From: Kevin Cheng @ 2026-01-12 17:45 UTC (permalink / raw)
To: seanjc, pbonzini; +Cc: kvm, linux-kernel, yosry.ahmed, Kevin Cheng
The AMD APM states that if VMMCALL instruction is not intercepted, the
instruction raises a #UD exception.
Create a vmmcall exit handler that generates a #UD if a VMMCALL exit
from L2 is being handled by L0, which means that L1 did not intercept
the VMMCALL instruction.
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Kevin Cheng <chengkev@google.com>
---
arch/x86/kvm/svm/svm.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 92a66b62cfabd..805267a5106ac 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3180,6 +3180,20 @@ static int bus_lock_exit(struct kvm_vcpu *vcpu)
return 0;
}
+static int vmmcall_interception(struct kvm_vcpu *vcpu)
+{
+ /*
+ * VMMCALL #UDs if it's not intercepted, and KVM reaches this point if
+ * and only if the VMMCALL intercept is not set in vmcb12.
+ */
+ if (is_guest_mode(vcpu)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+ return kvm_emulate_hypercall(vcpu);
+}
+
static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
[SVM_EXIT_READ_CR0] = cr_interception,
[SVM_EXIT_READ_CR3] = cr_interception,
@@ -3230,7 +3244,7 @@ static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
[SVM_EXIT_TASK_SWITCH] = task_switch_interception,
[SVM_EXIT_SHUTDOWN] = shutdown_interception,
[SVM_EXIT_VMRUN] = vmrun_interception,
- [SVM_EXIT_VMMCALL] = kvm_emulate_hypercall,
+ [SVM_EXIT_VMMCALL] = vmmcall_interception,
[SVM_EXIT_VMLOAD] = vmload_interception,
[SVM_EXIT_VMSAVE] = vmsave_interception,
[SVM_EXIT_STGI] = stgi_interception,
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH V2 5/5] KVM: SVM: Raise #UD if VMMCALL instruction is not intercepted
2026-01-12 17:45 ` [PATCH V2 5/5] KVM: SVM: Raise #UD if VMMCALL instruction is not intercepted Kevin Cheng
@ 2026-01-12 20:54 ` Yosry Ahmed
2026-01-14 5:20 ` Manali Shukla
1 sibling, 0 replies; 18+ messages in thread
From: Yosry Ahmed @ 2026-01-12 20:54 UTC (permalink / raw)
To: Kevin Cheng; +Cc: seanjc, pbonzini, kvm, linux-kernel
On Mon, Jan 12, 2026 at 05:45:35PM +0000, Kevin Cheng wrote:
> The AMD APM states that if VMMCALL instruction is not intercepted, the
> instruction raises a #UD exception.
>
> Create a vmmcall exit handler that generates a #UD if a VMMCALL exit
> from L2 is being handled by L0, which means that L1 did not intercept
> the VMMCALL instruction.
>
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Kevin Cheng <chengkev@google.com>
Reviewed-by: Yosry Ahmed <yosry.ahmed@linux.dev>
> ---
> arch/x86/kvm/svm/svm.c | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 92a66b62cfabd..805267a5106ac 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -3180,6 +3180,20 @@ static int bus_lock_exit(struct kvm_vcpu *vcpu)
> return 0;
> }
>
> +static int vmmcall_interception(struct kvm_vcpu *vcpu)
> +{
> + /*
> + * VMMCALL #UDs if it's not intercepted, and KVM reaches this point if
> + * and only if the VMMCALL intercept is not set in vmcb12.
> + */
> + if (is_guest_mode(vcpu)) {
> + kvm_queue_exception(vcpu, UD_VECTOR);
> + return 1;
> + }
> +
> + return kvm_emulate_hypercall(vcpu);
> +}
> +
> static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
> [SVM_EXIT_READ_CR0] = cr_interception,
> [SVM_EXIT_READ_CR3] = cr_interception,
> @@ -3230,7 +3244,7 @@ static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
> [SVM_EXIT_TASK_SWITCH] = task_switch_interception,
> [SVM_EXIT_SHUTDOWN] = shutdown_interception,
> [SVM_EXIT_VMRUN] = vmrun_interception,
> - [SVM_EXIT_VMMCALL] = kvm_emulate_hypercall,
> + [SVM_EXIT_VMMCALL] = vmmcall_interception,
> [SVM_EXIT_VMLOAD] = vmload_interception,
> [SVM_EXIT_VMSAVE] = vmsave_interception,
> [SVM_EXIT_STGI] = stgi_interception,
> --
> 2.52.0.457.g6b5491de43-goog
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH V2 5/5] KVM: SVM: Raise #UD if VMMCALL instruction is not intercepted
2026-01-12 17:45 ` [PATCH V2 5/5] KVM: SVM: Raise #UD if VMMCALL instruction is not intercepted Kevin Cheng
2026-01-12 20:54 ` Yosry Ahmed
@ 2026-01-14 5:20 ` Manali Shukla
1 sibling, 0 replies; 18+ messages in thread
From: Manali Shukla @ 2026-01-14 5:20 UTC (permalink / raw)
To: Kevin Cheng, seanjc, pbonzini; +Cc: kvm, linux-kernel, yosry.ahmed
On 1/12/2026 11:15 PM, Kevin Cheng wrote:
> The AMD APM states that if VMMCALL instruction is not intercepted, the
> instruction raises a #UD exception.
>
> Create a vmmcall exit handler that generates a #UD if a VMMCALL exit
> from L2 is being handled by L0, which means that L1 did not intercept
> the VMMCALL instruction.
>
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Kevin Cheng <chengkev@google.com>
> ---
> arch/x86/kvm/svm/svm.c | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 92a66b62cfabd..805267a5106ac 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -3180,6 +3180,20 @@ static int bus_lock_exit(struct kvm_vcpu *vcpu)
> return 0;
> }
>
> +static int vmmcall_interception(struct kvm_vcpu *vcpu)
> +{
> + /*
> + * VMMCALL #UDs if it's not intercepted, and KVM reaches this point if
> + * and only if the VMMCALL intercept is not set in vmcb12.
> + */
> + if (is_guest_mode(vcpu)) {
> + kvm_queue_exception(vcpu, UD_VECTOR);
> + return 1;
> + }
> +
> + return kvm_emulate_hypercall(vcpu);
> +}
> +
> static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
> [SVM_EXIT_READ_CR0] = cr_interception,
> [SVM_EXIT_READ_CR3] = cr_interception,
> @@ -3230,7 +3244,7 @@ static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
> [SVM_EXIT_TASK_SWITCH] = task_switch_interception,
> [SVM_EXIT_SHUTDOWN] = shutdown_interception,
> [SVM_EXIT_VMRUN] = vmrun_interception,
> - [SVM_EXIT_VMMCALL] = kvm_emulate_hypercall,
> + [SVM_EXIT_VMMCALL] = vmmcall_interception,
> [SVM_EXIT_VMLOAD] = vmload_interception,
> [SVM_EXIT_VMSAVE] = vmsave_interception,
> [SVM_EXIT_STGI] = stgi_interception,
Reviewed-by: Manali Shukla <manali.shukla@amd.com>
Tested-by: Manali Shukla <manali.shukla@amd.com>
^ permalink raw reply [flat|nested] 18+ messages in thread