]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: SVM: Move STGI and CLGI intercept handling
authorKevin Cheng <chengkev@google.com>
Wed, 4 Mar 2026 00:30:09 +0000 (16:30 -0800)
committerSean Christopherson <seanjc@google.com>
Thu, 5 Mar 2026 00:08:57 +0000 (16:08 -0800)
Move STGI/CLGI intercept handling to svm_recalc_instruction_intercepts()
in preparation for making the function EFER.SVME-aware.  This will allow
configuring STGI/CLGI intercepts along with other intercepts for other SVM
instructions when EFER.SVME is toggled (KVM needs to intercept SVM
instructions when EFER.SVME=0 to inject #UD).

When clearing the STGI intercept in particular, request KVM_REQ_EVENT if
there is at least one a pending GIF-controlled event. This avoids breaking
NMI/SMI window tracking, as enable_{nmi,smi}_window() sets INTERCEPT_STGI
to detect when NMIs become unblocked. KVM_REQ_EVENT forces
kvm_check_and_inject_events() to re-evaluate pending events and re-enable
the intercept if needed.

Extract the pending GIF event check into a helper function
svm_has_pending_gif_event() to deduplicate the logic between
svm_recalc_instruction_intercepts() and svm_set_gif().

Signed-off-by: Kevin Cheng <chengkev@google.com>
[sean: keep vgif handling out of the "Intel CPU model" path]
Reviewed-by: Yosry Ahmed <yosry@kernel.org>
Link: https://patch.msgid.link/20260304003010.1108257-2-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/svm/svm.c

index 9e6864cf58d34e453084ef9e2c45801d97ff742f..30d3291e4738e9138ef5832593268fe251657e3b 100644 (file)
@@ -999,6 +999,14 @@ void svm_write_tsc_multiplier(struct kvm_vcpu *vcpu)
        preempt_enable();
 }
 
+static bool svm_has_pending_gif_event(struct vcpu_svm *svm)
+{
+       return 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);
+}
+
 /* Evaluate instruction intercepts that depend on guest CPUID features. */
 static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
 {
@@ -1042,6 +1050,20 @@ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu)
                }
        }
 
+       if (vgif) {
+               svm_clr_intercept(svm, INTERCEPT_STGI);
+               svm_clr_intercept(svm, INTERCEPT_CLGI);
+
+               /*
+                * Process pending events when clearing STGI/CLGI intercepts if
+                * there's at least one pending event that is masked by GIF, so
+                * that KVM re-evaluates if the intercept needs to be set again
+                * to track when GIF is re-enabled (e.g. for NMI injection).
+                */
+               if (svm_has_pending_gif_event(svm))
+                       kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
+       }
+
        if (kvm_need_rdpmc_intercept(vcpu))
                svm_set_intercept(svm, INTERCEPT_RDPMC);
        else
@@ -1185,11 +1207,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 (vls)
                svm->vmcb->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
@@ -2306,10 +2325,7 @@ void svm_set_gif(struct vcpu_svm *svm, bool value)
                        svm_clear_vintr(svm);
 
                enable_gif(svm);
-               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))
+               if (svm_has_pending_gif_event(svm))
                        kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
        } else {
                disable_gif(svm);