From: Kevin Cheng Date: Wed, 4 Mar 2026 00:30:09 +0000 (-0800) Subject: KVM: SVM: Move STGI and CLGI intercept handling X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=69f779f79e0d1ff321a89ab56cdcab34613104c0;p=thirdparty%2Flinux.git KVM: SVM: Move STGI and CLGI intercept handling 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 [sean: keep vgif handling out of the "Intel CPU model" path] Reviewed-by: Yosry Ahmed Link: https://patch.msgid.link/20260304003010.1108257-2-seanjc@google.com Signed-off-by: Sean Christopherson --- diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 9e6864cf58d34..30d3291e4738e 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -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);