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

[PATCH V1 7/8] x86/nestedhap: Retry nested page fault if the np2m changes during walk


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: chunjie.zhu@xxxxxxxxxx
  • Date: Mon, 26 Oct 2026 15:17:53 +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=Khj/KRTU4lyxeIU4dIXAw6vp1YA31vzVRgbSAA0KGDo=; b=g8uFdyddl6wEzZahZK7lcDsewCzEQqgFLW1Z99fwXKN0go69qnOFau86TFX0ef+VU7GtRbuS4Q+ngkRoYDouRskCf7fCrGAU+UaAnkB87S5WHRvGIMjRZDJpavQLAd7RzcDFXnGT64Gztwq4PwDFBZE8ynnqIAWzgw8zHLKkqo3UI0qX+yFQzLMLzSETdXnZkPfBHKZbH0gv+uPDN4Qxgvoji8DWkoEgM6lx4HAbpzqBrDyVpl5xTI8sWhXYmM9EUoO3+cmYlrHW8zy91xxWPTVBUfX4iMrLRUs7XDSUmWQQ6UBkINwVKZx61/4+bCoKWh86j/xLn66ok3XGs+warg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=rUoHRlCOb5Sr91iXFQj86sS+cWB3kRfAFdu/ptlvgqgwwA03f5AtLWuFhOmVT5TDVFtsg2Uki35CpSsPslVaaLDmmupDFly0SoBYw3HOrEmj1IiNe81K7YOf47cY214ICJjzaxnVZv6gDpgtytNplgycDin3cluQpjQlpaJ9EY1Se9d1WMye6cuM7fyarY/Gv8+XSbeY9mSHpGISgr5ptQp2b0u/UP2BQQCnVQBSoYQ1rvTIOHv+WavMY41kUZnvpWZZI874/K7p0hTqFkcTHQtFp58kSxAe7hu67o4a6ORLUn6o+dp+pfVKwW7gFUPN8wcO6c8eNYm45hiwc61K7Q==
  • 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, anthony.perard@xxxxxxxxxx, michal.orzel@xxxxxxx, jbeulich@xxxxxxxx, julien@xxxxxxx, roger@xxxxxxxxxxxxxx, sstabellini@xxxxxxxxxx, dpsmith@xxxxxxxxxxxxxxxxxxxx, Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
  • Delivery-date: Mon, 26 Oct 2026 07:19:16 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

From: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>

nestedhvm_hap_nested_page_fault() walks the L1 and L0 p2m tables without
holding the nested p2m lock, and only afterwards looks up the np2m with
p2m_get_nestedp2m_locked() to install the result.  If L1 changes its
EPT/NPT base or the np2m is flushed or reassigned during the walk
(np2m_base / np2m_generation change), the translation computed from
the old tables may be installed into a np2m that now represents a
different L2 address space, leaving a stale or wrong mapping.

Snapshot np2m_base and np2m_generation before the walk, and re-check
them after each walk step (L1 and L0) via the new nestedhap_np2m_changed()
helper.  Re-check them again, together with the np2m identity, once the
np2m lock is retaken for nestedhap_fix_p2m(). On any mismatch, drop
the lock and retry the whole fault from the start.

Signed-off-by: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
---
 xen/arch/x86/mm/hap/nested_hap.c | 40 +++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c
index 72706cebaedf..1f09c706dda5 100644
--- a/xen/arch/x86/mm/hap/nested_hap.c
+++ b/xen/arch/x86/mm/hap/nested_hap.c
@@ -101,6 +101,19 @@ nestedhap_fix_p2m(struct vcpu *v, struct p2m_domain *p2m,
     }
 }
 
+static bool nestedhap_np2m_changed(struct p2m_domain *p2m,
+                                   uint64_t base, uint64_t generation)
+{
+    bool changed;
+
+    p2m_lock(p2m);
+    changed = p2m->np2m_base != base ||
+              p2m->np2m_generation != generation;
+    p2m_unlock(p2m);
+
+    return changed;
+}
+
 /* This function uses L1_gpa to walk the P2M table in L0 hypervisor. If the
  * walk is successful, the translated value is returned in L0_gpa. The return 
  * value tells the upper level what to do.
@@ -176,16 +189,26 @@ int nestedhvm_hap_nested_page_fault(
     p2m_type_t p2mt_10;
     p2m_access_t p2ma_10 = p2m_access_rwx;
     uint8_t p2ma_21 = p2m_access_rwx;
+    uint64_t np2m_base, np2m_generation;
 
     if ( *L2_gpa >> v->domain->arch.cpuid->extd.maxphysaddr )
         return NESTEDHVM_PAGEFAULT_INJECT;
 
     p2m = p2m_get_hostp2m(d); /* L0 p2m */
 
+ retry:
+    nested_p2m = p2m_get_nestedp2m_locked(v);
+    np2m_base = nested_p2m->np2m_base;
+    np2m_generation = nested_p2m->np2m_generation;
+    p2m_unlock(nested_p2m);
+
     /* walk the L1 P2M table */
     rv = nhvm_hap_walk_L1_p2m(v, *L2_gpa, &L1_gpa, &page_order_21, &p2ma_21,
                               npfec);
 
+    if ( nestedhap_np2m_changed(nested_p2m, np2m_base, np2m_generation) )
+        goto retry;
+
     /* let caller to handle these two cases */
     switch (rv) {
     case NESTEDHVM_PAGEFAULT_INJECT:
@@ -203,6 +226,9 @@ int nestedhvm_hap_nested_page_fault(
     rv = nestedhap_walk_L0_p2m(p2m, L1_gpa, &L0_gpa, &p2mt_10, &p2ma_10,
                                &page_order_10, npfec);
 
+    if ( nestedhap_np2m_changed(nested_p2m, np2m_base, np2m_generation) )
+        goto retry;
+
     /* let upper level caller to handle these two cases */
     switch (rv) {
     case NESTEDHVM_PAGEFAULT_INJECT:
@@ -249,7 +275,19 @@ int nestedhvm_hap_nested_page_fault(
     p2ma_10 &= (p2m_access_t)p2ma_21;
 
     /* fix p2m_get_pagetable(nested_p2m) */
-    nested_p2m = p2m_get_nestedp2m_locked(v);
+    {
+        struct p2m_domain *current_p2m = p2m_get_nestedp2m_locked(v);
+
+        if ( current_p2m != nested_p2m ||
+             current_p2m->np2m_base != np2m_base ||
+             current_p2m->np2m_generation != np2m_generation )
+        {
+            p2m_unlock(current_p2m);
+            goto retry;
+        }
+
+        nested_p2m = current_p2m;
+    }
     nestedhap_fix_p2m(v, nested_p2m, *L2_gpa, L0_gpa, page_order_20,
         p2mt_10, p2ma_10);
     p2m_unlock(nested_p2m);
-- 
2.34.1




 


Rackspace

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