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

[xen stable-4.12] AMD/IOMMU: ensure suitable ordering of DTE modifications



commit 14b0a080c19949a6af6e9c5af295427e98a2974b
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Oct 20 15:03:24 2020 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Oct 20 15:03:24 2020 +0200

    AMD/IOMMU: ensure suitable ordering of DTE modifications
    
    DMA and interrupt translation should be enabled only after other
    applicable DTE fields have been written. Similarly when disabling
    translation or when moving a device between domains, translation should
    first be disabled, before other entry fields get modified. Note however
    that the "moving" aspect doesn't apply to the interrupt remapping side,
    as domain specifics are maintained in the IRTEs here, not the DTE. We
    also never disable interrupt remapping once it got enabled for a device
    (the respective argument passed is always the immutable iommu_intremap).
    
    This is part of XSA-347.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Paul Durrant <paul@xxxxxxx>
    master commit: 0514a3a25fb9ebff5d75cc8f00a9229385300858
    master date: 2020-10-20 14:23:12 +0200
---
 xen/drivers/passthrough/amd/iommu_map.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/xen/drivers/passthrough/amd/iommu_map.c 
b/xen/drivers/passthrough/amd/iommu_map.c
index 98993aa0ce..da7ca7a41e 100644
--- a/xen/drivers/passthrough/amd/iommu_map.c
+++ b/xen/drivers/passthrough/amd/iommu_map.c
@@ -162,7 +162,22 @@ void amd_iommu_set_root_page_table(uint32_t *dte, uint64_t 
root_ptr,
                                    uint16_t domain_id, uint8_t paging_mode,
                                    uint8_t valid)
 {
-    uint32_t addr_hi, addr_lo, entry;
+    uint32_t addr_hi, addr_lo, entry, dte0 = dte[0];
+
+    if ( valid ||
+         get_field_from_reg_u32(dte0, IOMMU_DEV_TABLE_VALID_MASK,
+                                IOMMU_DEV_TABLE_VALID_SHIFT) )
+    {
+        set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, dte0,
+                             IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK,
+                             IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT, &dte0);
+        set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, dte0,
+                             IOMMU_DEV_TABLE_VALID_MASK,
+                             IOMMU_DEV_TABLE_VALID_SHIFT, &dte0);
+        dte[0] = dte0;
+        smp_wmb();
+    }
+
     set_field_in_reg_u32(domain_id, 0,
                          IOMMU_DEV_TABLE_DOMAIN_ID_MASK,
                          IOMMU_DEV_TABLE_DOMAIN_ID_SHIFT, &entry);
@@ -181,8 +196,9 @@ void amd_iommu_set_root_page_table(uint32_t *dte, uint64_t 
root_ptr,
                          IOMMU_DEV_TABLE_IO_READ_PERMISSION_MASK,
                          IOMMU_DEV_TABLE_IO_READ_PERMISSION_SHIFT, &entry);
     dte[1] = entry;
+    smp_wmb();
 
-    set_field_in_reg_u32(addr_lo >> PAGE_SHIFT, 0,
+    set_field_in_reg_u32(addr_lo >> PAGE_SHIFT, dte0,
                          IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
                          IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT, &entry);
     set_field_in_reg_u32(paging_mode, entry,
@@ -195,7 +211,7 @@ void amd_iommu_set_root_page_table(uint32_t *dte, uint64_t 
root_ptr,
                          IOMMU_CONTROL_DISABLED, entry,
                          IOMMU_DEV_TABLE_VALID_MASK,
                          IOMMU_DEV_TABLE_VALID_SHIFT, &entry);
-    dte[0] = entry;
+    write_atomic(&dte[0], entry);
 }
 
 void iommu_dte_set_iotlb(uint32_t *dte, uint8_t i)
@@ -226,6 +242,7 @@ void __init amd_iommu_set_intremap_table(
                          IOMMU_DEV_TABLE_INT_CONTROL_MASK,
                          IOMMU_DEV_TABLE_INT_CONTROL_SHIFT, &entry);
     dte[5] = entry;
+    smp_wmb();
 
     set_field_in_reg_u32(addr_lo >> 6, 0,
                          IOMMU_DEV_TABLE_INT_TABLE_PTR_LOW_MASK,
@@ -243,7 +260,7 @@ void __init amd_iommu_set_intremap_table(
                          IOMMU_CONTROL_DISABLED, entry,
                          IOMMU_DEV_TABLE_INT_VALID_MASK,
                          IOMMU_DEV_TABLE_INT_VALID_SHIFT, &entry);
-    dte[4] = entry;
+    write_atomic(&dte[4], entry);
 }
 
 void __init iommu_dte_add_device_entry(uint32_t *dte,
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.12



 


Rackspace

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