summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Cheng <chengkev@google.com>2026-03-04 03:30:09 +0300
committerSean Christopherson <seanjc@google.com>2026-03-05 03:08:57 +0300
commit69f779f79e0d1ff321a89ab56cdcab34613104c0 (patch)
treec52e89850362abaf720ffb4ada614376c28364f0
parent33d3617a52f9930d22b2af59f813c2fbdefa6dd5 (diff)
downloadlinux-69f779f79e0d1ff321a89ab56cdcab34613104c0.tar.xz
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 <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>
-rw-r--r--arch/x86/kvm/svm/svm.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 9e6864cf58d3..30d3291e4738 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);