]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
AMD/IOMMU: suppress PTE merging after initial table creation
authorJan Beulich <jbeulich@suse.com>
Tue, 20 Nov 2018 13:55:14 +0000 (14:55 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 20 Nov 2018 13:55:14 +0000 (14:55 +0100)
The logic is not fit for this purpose, so simply disable its use until
it can be fixed / replaced. Note that this re-enables merging for the
table creation case, which was disabled as a (perhaps unintended) side
effect of the earlier "amd/iommu: fix flush checks". It relies on no
page getting mapped more than once (with different properties) in this
process, as that would still be beyond what the merging logic can cope
with. But arch_iommu_populate_page_table() guarantees this afaict.

This is part of XSA-275.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
xen/drivers/passthrough/amd/iommu_map.c
xen/include/asm-x86/iommu.h

index 0c9d2c9c0032d4890af3794dd457955aee5bd8f5..c1daba8422dd8354d1dc99fa16e359737fd7474c 100644 (file)
@@ -699,11 +699,24 @@ int amd_iommu_map_page(struct domain *d, dfn_t dfn, mfn_t mfn,
                                        !!(flags & IOMMUF_writable),
                                        !!(flags & IOMMUF_readable));
 
-    /* Do not increase pde count if io mapping has not been changed */
-    if ( !need_flush )
-        goto out;
+    if ( need_flush )
+    {
+        amd_iommu_flush_pages(d, dfn_x(dfn), 0);
+        /* No further merging, as the logic doesn't cope. */
+        hd->arch.no_merge = true;
+    }
 
-    amd_iommu_flush_pages(d, dfn_x(dfn), 0);
+    /*
+     * Suppress merging of non-R/W mappings or after initial table creation,
+     * as the merge logic does not cope with this.
+     */
+    if ( hd->arch.no_merge || flags != (IOMMUF_writable | IOMMUF_readable) )
+        goto out;
+    if ( d->creation_finished )
+    {
+        hd->arch.no_merge = true;
+        goto out;
+    }
 
     for ( merge_level = 2; merge_level <= hd->arch.paging_mode;
           merge_level++ )
@@ -780,6 +793,10 @@ int amd_iommu_unmap_page(struct domain *d, dfn_t dfn)
 
     /* mark PTE as 'page not present' */
     clear_iommu_pte_present(pt_mfn[1], dfn_x(dfn));
+
+    /* No further merging in amd_iommu_map_page(), as the logic doesn't cope. */
+    hd->arch.no_merge = true;
+
     spin_unlock(&hd->arch.mapping_lock);
 
     amd_iommu_flush_pages(d, dfn_x(dfn), 0);
index 8dc392473d0980da7383a644016451c63ba793ef..055466b5bfb8ff2073432d8c9138ea358bcc1bf1 100644 (file)
@@ -52,6 +52,7 @@ struct arch_iommu
 
     /* amd iommu support */
     int paging_mode;
+    bool no_merge;
     struct page_info *root_table;
     struct guest_iommu *g_iommu;
 };