Change History: v3 (rebased on eb555cb5b794f): 03 - added clear/set_vnmi_mask API for SMM case 04 - added vnmi_pending check so to detect the pending VNMI scenario 05 - removed WARN_ON 06 - handle one of nested case where L1 using vnmi and L2 doesn't 07 - Emulate the VMEXIT(#INVALID) case for nested case 08 - No change. v2: https://lore.kernel.org/lkml/20220709134230.2397-7-santosh.shukla@xxxxxxx/T/#m4bf8a131748688fed00ab0fefdcac209a169e202 01, 02 - added maxim reviwed-by. 03 - Added get_vnmi_vmcb API to return vmcb for l1 and l2. 04 - Moved vnmi check after is_guest_mode() in func svm_nmi_blocked(). 05 - Added WARN_ON check for vnmi pending. 06 - Save the V_NMI_PENDING/MASK state in vmcb12 on vmexit. 07 - No change. v1: https://lore.kernel.org/all/20220602142620.3196-1-santosh.shukla@xxxxxxx/ Description: Currently, NMI is delivered to the guest using the Event Injection mechanism [1]. The Event Injection mechanism does not block the delivery of subsequent NMIs. So the Hypervisor needs to track the NMI delivery and its completion(by intercepting IRET) before sending a new NMI. Virtual NMI (VNMI) allows the hypervisor to inject the NMI into the guest w/o using Event Injection mechanism meaning not required to track the guest NMI and intercepting the IRET. To achieve that, VNMI feature provides virtualized NMI and NMI_MASK capability bits in VMCB intr_control - V_NMI(11) - Indicates whether a virtual NMI is pending in the guest. V_NMI_MASK(12) - Indicates whether virtual NMI is masked in the guest. V_NMI_ENABLE(26) - Enables the NMI virtualization feature for the guest. When Hypervisor wants to inject NMI, it will set V_NMI bit, Processor will clear the V_NMI bit and Set the V_NMI_MASK which means the Guest is handling NMI, After the guest handled the NMI, The processor will clear the V_NMI_MASK on the successful completion of IRET instruction Or if VMEXIT occurs while delivering the virtual NMI. If NMI virtualization enabled and NMI_INTERCEPT bit is unset then HW will exit with #INVALID exit reason. To enable the VNMI capability, Hypervisor need to program V_NMI_ENABLE bit 1. The presence of this feature is indicated via the CPUID function 0x8000000A_EDX[25]. Testing - * Used qemu's `inject_nmi` for testing. * tested with and w/o AVIC case. * tested with kvm-unit-test * tested with vGIF enable and disable. * tested nested env: - L1+L2 using vnmi - L1 using vnmi and L2 not Thanks, Santosh [1] https://www.amd.com/system/files/TechDocs/40332.pdf - APM Vol2, ch-15.20 - "Event Injection". Santosh Shukla (8): x86/cpu: Add CPUID feature bit for VNMI KVM: SVM: Add VNMI bit definition KVM: SVM: Add VNMI support in get/set_nmi_mask KVM: SVM: Report NMI not allowed when Guest busy handling VNMI KVM: SVM: Add VNMI support in inject_nmi KVM: nSVM: implement nested VNMI KVM: nSVM: emulate VMEXIT_INVALID case for nested VNMI KVM: SVM: Enable VNMI feature arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/svm.h | 7 +++ arch/x86/kvm/svm/nested.c | 32 ++++++++++++++ arch/x86/kvm/svm/svm.c | 44 ++++++++++++++++++- arch/x86/kvm/svm/svm.h | 68 ++++++++++++++++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) -- 2.25.1