[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] x86/svm: Adjust vNMI handling to update the cleanbit



Despite prior information to the contrary, APM Vol2 revision 3.46 October 2026
has been adjusted to state that the vNMI fields in vINTR are covered by the
TPR cleanbit.

Adjust svm_inject_nmi() and svm_set_interrupt_shadow() to use vmcb_set_vintr()
rather than writing into the VMCB directly.

In svm_inject_nmi(), fix an inefficiency from the introduction of vNMI.  Move
the reading of vmcb_get_general1_intercepts() to the point at which it is
used; tt does not need reading on the case that vNMIs are enabled.

Fixes: 86a203ab8d38 ("x86/svm: Support vNMI on capable hardware")
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <jbeulich@xxxxxxxx>
CC: Roger Pau Monné <roger@xxxxxxxxxxxxxx>
CC: Teddy Astie <teddy.astie@xxxxxxxxxx>
CC: Jason Andryuk <jason.andryuk@xxxxxxx>
---
 xen/arch/x86/hvm/svm/intr.c | 9 ++++++---
 xen/arch/x86/hvm/svm/svm.c  | 8 ++++++--
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index 4b0debfa9a2e..2224f1834741 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -30,12 +30,14 @@
 static void svm_inject_nmi(struct vcpu *v)
 {
     struct vmcb_struct *vmcb = v->arch.hvm.svm.vmcb;
-    u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);
+    vintr_t vintr = vmcb_get_vintr(vmcb);
+    uint32_t general1_intercepts;
     intinfo_t event;
 
-    if ( vmcb->_vintr.fields.vnmi_enable )
+    if ( vintr.fields.vnmi_enable )
     {
-        vmcb->_vintr.fields.vnmi_pending = true;
+        vintr.fields.vnmi_pending = true;
+        vmcb_set_vintr(vmcb, vintr);
         return;
     }
 
@@ -51,6 +53,7 @@ static void svm_inject_nmi(struct vcpu *v)
      * SVM does not virtualise the NMI mask, so we emulate it by intercepting
      * the next IRET and blocking NMI injection until the intercept triggers.
      */
+    general1_intercepts = vmcb_get_general1_intercepts(vmcb);
     vmcb_set_general1_intercepts(
         vmcb, general1_intercepts | GENERAL1_INTERCEPT_IRET);
 }
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 1628c5e0ae05..57779806bf6a 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -511,12 +511,16 @@ static void cf_check svm_set_interrupt_shadow(
 {
     struct vmcb_struct *vmcb = v->arch.hvm.svm.vmcb;
     bool block_nmi = intr_shadow & HVM_INTR_SHADOW_NMI;
+    vintr_t vintr = vmcb_get_vintr(vmcb);
 
     vmcb->int_stat.intr_shadow =
         !!(intr_shadow & (HVM_INTR_SHADOW_MOV_SS|HVM_INTR_SHADOW_STI));
 
-    if ( vmcb->_vintr.fields.vnmi_enable )
-        vmcb->_vintr.fields.vnmi_blocking = block_nmi;
+    if ( vintr.fields.vnmi_enable )
+    {
+        vintr.fields.vnmi_blocking = block_nmi;
+        vmcb_set_vintr(vmcb, vintr);
+    }
     else
     {
         uint32_t gen1 = vmcb_get_general1_intercepts(vmcb);
-- 
2.39.5




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.