[RESEND PATCH 1/5] vtd: Ensure root entry is updated consistently

Teddy Astie <[email protected]> Wed, 29 Jul 2026 12:05:39 +0200
Newsgroups gmane.comp.emulators.xen.devel
Message-ID <1785319678.8631fc262581453bbf619ec5b2062170.19fad586037000e099@vates.tech>
Make sure the root entry is updated consistently such that the compiler
is not allowed to perform optimizations around setting present bit (and
i.e set present bit before setting up the pagetable addresss, which would
cause the IOMMU to use a pagetable at address 0 instead).

This issue can only occurs at boot time where present bit is initially cleared
or when a bus is first introduced in the machine.

Fixes: ccfe4e08455f ("Intel vt-d specific changes in arch/x86/hvm/vmx/vtd.")
Signed-off-by: Teddy Astie <[email protected]>
---
 xen/drivers/passthrough/vtd/iommu.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index 3d6f787b3c..c314ce1db8 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -281,13 +281,13 @@ void free_pgtable_maddr(u64 maddr)
 /* context entry handling */
 static u64 bus_to_context_maddr(struct vtd_iommu *iommu, u8 bus)
 {
-    struct root_entry *root, *root_entries;
+    struct root_entry root, *root_entries;
     u64 maddr;
 
     ASSERT(spin_is_locked(&iommu->lock));
     root_entries = (struct root_entry *)map_vtd_domain_page(iommu->root_maddr);
-    root = &root_entries[bus];
-    if ( !root_present(*root) )
+    root.val = ACCESS_ONCE(root_entries[bus].val);
+    if ( !root_present(root) )
     {
         maddr = alloc_pgtable_maddr(1, iommu->node);
         if ( maddr == 0 )
@@ -295,11 +295,12 @@ static u64 bus_to_context_maddr(struct vtd_iommu *iommu, u8 bus)
             unmap_vtd_domain_page(root_entries);
             return 0;
         }
-        set_root_value(*root, maddr);
-        set_root_present(*root);
-        iommu_sync_cache(root, sizeof(struct root_entry));
+        set_root_value(root, maddr);
+        set_root_present(root);
+        ACCESS_ONCE(root_entries[bus].val) = root.val;
+        iommu_sync_cache(&root_entries[bus], sizeof(struct root_entry));
     }
-    maddr = (u64) get_context_addr(*root);
+    maddr = (u64) get_context_addr(root);
     unmap_vtd_domain_page(root_entries);
     return maddr;
 }
-- 
2.54.0



-- 
Teddy Astie | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech