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

[RFC PATCH v7 14/14] iommu: Introduce no-dma feature



This feature exposed through `dom0-iommu=no-dma` prevents the devices
of default context to have access to domain's memory.
This basically enforces DMA protection by default. The domain will
need to prepare a specific IOMMU context to do DMA.

This feature needs the guest to provide a PV-IOMMU driver.

Signed-off-by Teddy Astie <teddy.astie@xxxxxxxxxx>
---
 docs/misc/xen-command-line.pandoc   | 16 +++++++++++++++-
 xen/arch/x86/x86_64/mm.c            |  3 ++-
 xen/common/pv-iommu.c               |  3 +++
 xen/drivers/passthrough/iommu.c     | 13 +++++++++++++
 xen/drivers/passthrough/x86/iommu.c |  4 ++++
 xen/include/xen/iommu.h             |  3 +++
 6 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/docs/misc/xen-command-line.pandoc 
b/docs/misc/xen-command-line.pandoc
index 34004ce282..b528f626a7 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -941,7 +941,7 @@ is necessary to fix an issue, please report a bug.
 
 ### dom0-iommu
     = List of [ passthrough=<bool>, strict=<bool>, map-inclusive=<bool>,
-                map-reserved=<bool>, none ]
+                map-reserved=<bool>, dma=<bool>, none ]
 
 Controls for the dom0 IOMMU setup.
 
@@ -992,6 +992,20 @@ Controls for the dom0 IOMMU setup.
     subset of the correction by only mapping reserved memory regions rather
     than all non-RAM regions.
 
+*   The `dma` option determines if the IOMMU is configured to identity map
+    the "default IOMMU context". If set to false, all devices of the Dom0 get
+    their DMA blocked until the IOMMU is properly configured by the guest 
(aside
+    special reserved regions).
+
+    Disabling this can slightly improve performance by removing the need to 
synchronize
+    p2m modifications with the IOMMU subsystem, moreover, disabling it 
provides DMA
+    protection that some operating systems can expect in order to securely 
handle some
+    devices (e.g Thunderbolt).
+
+    Disabling this requires guest support for PV-IOMMU for devices to behave 
properly.
+
+    This option is enabled by default.
+
 *   The `none` option is intended for development purposes only, and skips
     certain safety checks pertaining to the correct IOMMU configuration for
     dom0 to boot.
diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
index d4e6a9c0a2..00ff5d0b71 100644
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -1315,7 +1315,8 @@ int memory_add(unsigned long spfn, unsigned long epfn, 
unsigned int pxm)
      */
     if ( is_iommu_enabled(hardware_domain) &&
          !iommu_use_hap_pt(hardware_domain) &&
-         !need_iommu_pt_sync(hardware_domain) )
+         !need_iommu_pt_sync(hardware_domain) &&
+         !iommu_hwdom_no_dma )
     {
         for ( i = spfn; i < epfn; i++ )
             if ( iommu_legacy_map(hardware_domain, _dfn(i), _mfn(i),
diff --git a/xen/common/pv-iommu.c b/xen/common/pv-iommu.c
index 4cdb30a031..a1d0552a66 100644
--- a/xen/common/pv-iommu.c
+++ b/xen/common/pv-iommu.c
@@ -107,6 +107,9 @@ static long capabilities_op(struct pv_iommu_capabilities 
*cap, struct domain *d)
     cap->max_pasid = 0; /* TODO */
     cap->cap_flags = 0;
 
+    if ( !dom_iommu(d)->no_dma )
+        cap->cap_flags |= IOMMUCAP_default_identity;
+
     cap->pgsize_mask = PAGE_SIZE_4K;
 
     return 0;
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index 5c6b272697..81d4cb87cf 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -55,6 +55,7 @@ static bool __hwdom_initdata iommu_hwdom_none;
 bool __hwdom_initdata iommu_hwdom_strict;
 bool __read_mostly iommu_hwdom_passthrough;
 bool __hwdom_initdata iommu_hwdom_inclusive;
+bool __read_mostly iommu_hwdom_no_dma = false;
 int8_t __hwdom_initdata iommu_hwdom_reserved = -1;
 
 #ifndef iommu_hap_pt_share
@@ -172,6 +173,8 @@ static int __init cf_check parse_dom0_iommu_param(const 
char *s)
             iommu_hwdom_reserved = val;
         else if ( !cmdline_strcmp(s, "none") )
             iommu_hwdom_none = true;
+        else if ( (val = parse_boolean("dma", s, ss)) >= 0 )
+            iommu_hwdom_no_dma = !val;
         else
             rc = -EINVAL;
 
@@ -292,7 +295,10 @@ int iommu_domain_init(struct domain *d, unsigned int opts)
     int ret = 0;
 
     if ( is_hardware_domain(d) )
+    {
         check_hwdom_reqs(d); /* may modify iommu_hwdom_strict */
+        hd->no_dma = iommu_hwdom_no_dma;
+    }
 
     if ( !is_iommu_enabled(d) )
         return 0;
@@ -329,6 +335,13 @@ int iommu_domain_init(struct domain *d, unsigned int opts)
     if ( !is_hardware_domain(d) || iommu_hwdom_strict )
         hd->need_sync = !iommu_use_hap_pt(d);
 
+    if ( hd->no_dma )
+    {
+        /* No-DMA mode is exclusive with HAP and sync_pt. */
+        hd->hap_pt_share = false;
+        hd->need_sync = false;
+    }
+
     ASSERT(!(hd->need_sync && hd->hap_pt_share));
 
     hd->allow_pv_iommu = true;
diff --git a/xen/drivers/passthrough/x86/iommu.c 
b/xen/drivers/passthrough/x86/iommu.c
index ac339a2ed3..b100c55e69 100644
--- a/xen/drivers/passthrough/x86/iommu.c
+++ b/xen/drivers/passthrough/x86/iommu.c
@@ -542,6 +542,10 @@ void __hwdom_init arch_iommu_hwdom_init(struct domain *d)
     if ( iommu_hwdom_reserved == -1 )
         iommu_hwdom_reserved = 1;
 
+    if ( iommu_hwdom_no_dma )
+        /* Skip special mappings with no-dma mode */
+        return;
+
     if ( iommu_hwdom_inclusive )
     {
         printk(XENLOG_WARNING
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index 3c77dfaf41..55bd9c9704 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -108,6 +108,7 @@ extern bool iommu_debug;
 extern bool amd_iommu_perdev_intremap;
 
 extern bool iommu_hwdom_strict, iommu_hwdom_passthrough, iommu_hwdom_inclusive;
+extern bool iommu_hwdom_no_dma;
 extern int8_t iommu_hwdom_reserved;
 
 extern unsigned int iommu_dev_iotlb_timeout;
@@ -487,6 +488,8 @@ struct domain_iommu {
     /* SAF-2-safe enum constant in arithmetic operation */
     DECLARE_BITMAP(features, IOMMU_FEAT_count);
 
+    /* Do the IOMMU block all DMA on default context (implies !has_pt_share) ? 
*/
+    bool no_dma;
 
     /* Is the domain allowed to use PV-IOMMU ? */
     bool allow_pv_iommu;
-- 
2.51.2



--
Teddy Astie | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech




 


Rackspace

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