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)
{
}
}
+ 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
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;
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);