]> xenbits.xensource.com Git - people/tklengyel/xen.git/commitdiff
VT-d: avoid infinite recursion on domain_context_mapping_one() error path
authorJan Beulich <jbeulich@suse.com>
Thu, 7 Apr 2022 10:31:16 +0000 (12:31 +0200)
committerJan Beulich <jbeulich@suse.com>
Thu, 7 Apr 2022 10:31:16 +0000 (12:31 +0200)
Despite the comment there infinite recursion was still possible, by
flip-flopping between two domains. This is because prev_dom is derived
from the DID found in the context entry, which was already updated by
the time error recovery is invoked. Simply introduce yet another mode
flag to prevent rolling back an in-progress roll-back of a prior
mapping attempt.

Also drop the existing recursion prevention for having been dead anyway:
Earlier in the function we already bail when prev_dom == domain.

Fixes: 8f41e481b485 ("VT-d: re-assign devices directly")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
xen/drivers/passthrough/vtd/iommu.c
xen/drivers/passthrough/vtd/vtd.h

index 76ff551dfe52f65a5bf69b0750bfdc89b38ee265..069427abb292c621e0769817e6cf2cddc349ecf9 100644 (file)
@@ -1599,7 +1599,7 @@ int domain_context_mapping_one(
     if ( !seg && !rc )
         rc = me_wifi_quirk(domain, bus, devfn, domid, pgd_maddr, mode);
 
-    if ( rc )
+    if ( rc && !(mode & MAP_ERROR_RECOVERY) )
     {
         if ( !prev_dom ||
              /*
@@ -1609,13 +1609,12 @@ int domain_context_mapping_one(
               */
              (prev_dom == dom_io && !pdev) )
             ret = domain_context_unmap_one(domain, iommu, bus, devfn);
-        else if ( prev_dom != domain ) /* Avoid infinite recursion. */
+        else
             ret = domain_context_mapping_one(prev_dom, iommu, bus, devfn, pdev,
                                              DEVICE_DOMID(prev_dom, pdev),
                                              DEVICE_PGTABLE(prev_dom, pdev),
-                                             mode & MAP_WITH_RMRR) < 0;
-        else
-            ret = 1;
+                                             (mode & MAP_WITH_RMRR) |
+                                             MAP_ERROR_RECOVERY) < 0;
 
         if ( !ret && pdev && pdev->devfn == devfn )
             check_cleanup_domid_map(domain, pdev, iommu);
index e4ab242fee5cda65394b387a13ffea06376315ec..cb2df76eeddbd1f1e3682f7acc28433efdc5c643 100644 (file)
@@ -29,7 +29,8 @@
 #define MAP_WITH_RMRR         (1u << 0)
 #define MAP_OWNER_DYING       (1u << 1)
 #define MAP_SINGLE_DEVICE     (1u << 2)
-#define UNMAP_ME_PHANTOM_FUNC (1u << 3)
+#define MAP_ERROR_RECOVERY    (1u << 3)
+#define UNMAP_ME_PHANTOM_FUNC (1u << 4)
 
 /* Allow for both IOAPIC and IOSAPIC. */
 #define IO_xAPIC_route_entry IO_APIC_route_entry