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

[PATCH v3 1/3] x86/hvm: don't let EFLAGS.IF block NMI/#MC due to nested state


  • To: ross.lagerwall@xxxxxxxxxx
  • From: chunjie.zhu@xxxxxxxxxx
  • Date: Thu, 12 Nov 2026 19:35:23 +0800
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=jMo5vpeOVq9//sBvP0tuvNSyKs5W1YD/Ile27b2SDkA=; b=XIvx4ao+20NrfmDimrIFJ7WtROzbR2W1+jBsOIObpIZChahXTFBOebUnLh9zctSkPVIPpE8IBY2bxjfYaQBgNx2XL92FtG57UKV9Fjr0VNMOtqzTGc6qnTj6QzwTwpaDbppYVmBCTG4OQIzxTCJOwg+LXifSKwTBVMZxxN8nE/juTOBax5naoiwnwjfwGmnF8kIUHh0H0DJKUBZOe+mKOYjPxyTUDFDg/qniBGAVa9MFC8qaemMqe8/sqHfoGl8puG2+di8H7OUgRtD2ls5yI8/gx0b7wxjL8zI5gjJZr7MoMnre/z7G6jrQ/z/gzdoxEnGAvHCKx6SfT+wrxc1n+g==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=P2ObQk1lBVR40v48CrqKZqT5pdKb6ejlGmTbg1hwC+pL/3PW6oW46cRLaZ+QYzcn+tu2Nv/JoAp940V14bIGD296Bp0pZ8aMU5/12sX4BseB/OGnFIQoL5Xp6CokyCmiqOdz7wxwUrZiYY6e49wTn7O4mTnMsMAaizu7WyRvjmC73yl15um1yFAcFR/DPL6h30RomcCKaPnMPxX2NYZAXaL/oJnh8E/4/vg/CWmoIQ5ILLEcuNXEz9VdIrDdKhX9IA4o+bCOFeujAjeP5P4bc0qxFQcXsMFpd+WX6jReicbact2nV0bVo4UDLh/xJObxJHkKdJm68Uwheuyvx5YC/Q==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=citrix.com header.i="@citrix.com" header.h="From:Date:Subject:Message-Id:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: mx.microsoft.com 1; dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: andrew.cooper3@xxxxxxxxxx, chunjie.zhu@xxxxxxxxxx, jason.andryuk@xxxxxxx, jbeulich@xxxxxxxx, roger@xxxxxxxxxxxxxx, teddy.astie@xxxxxxxxxx, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • Delivery-date: Thu, 12 Nov 2026 11:35:59 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

From: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>

nhvm_interrupt_blocked() reports why an interrupt is blocked, but both
callers, nestedsvm_vcpu_interrupt() and hvm_interrupt_blocked(), treat any
reason as blocking every event source.  EFLAGS.IF (hvm_intblk_rflags_ie)
doesn't mask NMI or #MC, so NMI/#MC get held pending needlessly, e.g. when
L1 sets V_INTR_MASKING and L1's IF is clear.

Have nhvm_interrupt_blocked() take the intack and report no block for
NMI/#MC when the reason is hvm_intblk_rflags_ie.

nvmx_intr_blocked() used hvm_intblk_rflags_ie for vmexit/vmentry in
progress and a valid VM_ENTRY_INTR_INFO.  Those block every event source
and have nothing to do with RFLAGS.IF, so report hvm_intblk_arch instead.
This doesn't change behaviour as all callers only compare against
hvm_intblk_none and hvm_intblk_tpr.

Signed-off-by: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
---
v3:
 * Use nhvm_interrupt_blocked() in nvmx_intr_intercept() instead of calling
   nvmx_intr_blocked() directly, so the NMI/#MC exemption applies to VMX
   too, as suggested by Ross.
 * Rebased on staging.

 xen/arch/x86/hvm/hvm.c             |  2 +-
 xen/arch/x86/hvm/svm/nestedsvm.c   |  2 +-
 xen/arch/x86/hvm/vmx/intr.c        |  8 ++++----
 xen/arch/x86/include/asm/hvm/hvm.h | 12 ++++++++++--
 4 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ef9c7cd05777..8fd095a4f8e6 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3897,7 +3897,7 @@ enum hvm_intblk hvm_interrupt_blocked(struct vcpu *v, 
struct hvm_intack intack)
     if ( nestedhvm_enabled(v->domain) ) {
         enum hvm_intblk intr;
 
-        intr = nhvm_interrupt_blocked(v);
+        intr = nhvm_interrupt_blocked(v, intack);
         if ( intr != hvm_intblk_none )
             return intr;
     }
diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c
index d970869cfd96..40c7717c5572 100644
--- a/xen/arch/x86/hvm/svm/nestedsvm.c
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c
@@ -1417,7 +1417,7 @@ nestedsvm_vcpu_interrupt(struct vcpu *v, const struct 
hvm_intack intack)
     uint64_t exitinfo2 = 0;
     ASSERT(nestedhvm_vcpu_in_guestmode(v));
 
-    intr = nhvm_interrupt_blocked(v);
+    intr = nhvm_interrupt_blocked(v, intack);
     if ( intr != hvm_intblk_none )
         return NSVM_INTR_MASKED;
 
diff --git a/xen/arch/x86/hvm/vmx/intr.c b/xen/arch/x86/hvm/vmx/intr.c
index 6c220c4c2e49..a6099420fda5 100644
--- a/xen/arch/x86/hvm/vmx/intr.c
+++ b/xen/arch/x86/hvm/vmx/intr.c
@@ -142,18 +142,18 @@ enum hvm_intblk cf_check nvmx_intr_blocked(struct vcpu *v)
     {
         if ( nvcpu->nv_vmexit_pending ||
              nvcpu->nv_vmswitch_in_progress )
-            r = hvm_intblk_rflags_ie;
+            r = hvm_intblk_arch;
         else
         {
             unsigned long intr_info;
 
             __vmread(VM_ENTRY_INTR_INFO, &intr_info);
             if ( intr_info & INTR_INFO_VALID_MASK )
-                r = hvm_intblk_rflags_ie;
+                r = hvm_intblk_arch;
         }
     }
     else if ( nvcpu->nv_vmentry_pending )
-        r = hvm_intblk_rflags_ie;
+        r = hvm_intblk_arch;
 
     return r;
 }
@@ -167,7 +167,7 @@ static int nvmx_intr_intercept(struct vcpu *v, struct 
hvm_intack intack)
          hvm_interrupt_blocked(v, intack) == hvm_intblk_tpr )
         return 1;
 
-    if ( nvmx_intr_blocked(v) != hvm_intblk_none )
+    if ( nhvm_interrupt_blocked(v, intack) != hvm_intblk_none )
     {
         vmx_enable_intr_window(v, intack);
         return 1;
diff --git a/xen/arch/x86/include/asm/hvm/hvm.h 
b/xen/arch/x86/include/asm/hvm/hvm.h
index 9bf2064925fa..b10937e229cf 100644
--- a/xen/arch/x86/include/asm/hvm/hvm.h
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
@@ -678,9 +678,17 @@ static inline bool nhvm_vmcx_hap_enabled(struct vcpu *v)
 }
 
 /* interrupt */
-static inline enum hvm_intblk nhvm_interrupt_blocked(struct vcpu *v)
+static inline enum hvm_intblk nhvm_interrupt_blocked(
+    struct vcpu *v, const struct hvm_intack intack)
 {
-    return alternative_call(hvm_funcs.nhvm_intr_blocked, v);
+    enum hvm_intblk intr = alternative_call(hvm_funcs.nhvm_intr_blocked, v);
+
+    /* EFLAGS.IF doesn't mask NMI or #MC. */
+    if ( intr == hvm_intblk_rflags_ie &&
+         (intack.source == hvm_intsrc_nmi || intack.source == hvm_intsrc_mce) )
+        return hvm_intblk_none;
+
+    return intr;
 }
 
 static inline int nhvm_hap_walk_L1_p2m(
-- 
2.34.1




 


Rackspace

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