]> xenbits.xensource.com Git - people/liuw/xen.git/commitdiff
domain: introduce XEN_DOMCTL_CDF_iommu flag
authorPaul Durrant <paul.durrant@citrix.com>
Tue, 17 Sep 2019 14:10:38 +0000 (16:10 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 17 Sep 2019 14:10:38 +0000 (16:10 +0200)
This patch introduces a common domain creation flag to determine whether
the domain is permitted to make use of the IOMMU. Currently the flag is
always set for both dom0 and any domU created by libxl if the IOMMU is
globally enabled (i.e. iommu_enabled == 1). sanitise_domain_config() is
modified to reject the flag if !iommu_enabled.

A new helper function, is_iommu_enabled(), is added to test the flag and
iommu_domain_init() will return immediately if !is_iommu_enabled(). This is
slightly different to the previous behaviour based on !iommu_enabled where
the call to arch_iommu_domain_init() was made regardless, however it appears
that this call was only necessary to initialize the dt_devices list for ARM
such that iommu_release_dt_devices() can be called unconditionally by
domain_relinquish_resources(). Adding a simple check of is_iommu_enabled()
into iommu_release_dt_devices() keeps this unconditional call working.

No functional change should be observed with this patch applied.

Subsequent patches will allow the toolstack to control whether use of the
IOMMU is enabled for a domain.

NOTE: The introduction of the is_iommu_enabled() helper function might
      seem excessive but its use is expected to increase with subsequent
      patches. Also, having iommu_domain_init() bail before calling
      arch_iommu_domain_init() is not strictly necessary, but I think the
      consequent addition of the call to is_iommu_enabled() in
      iommu_release_dt_devices() makes the code clearer.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: "Roger Pau Monné" <roger.pau@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
Acked-by: Julien Grall <julien.grall@arm.com>
tools/ocaml/libs/xc/xenctrl.ml
tools/ocaml/libs/xc/xenctrl.mli
xen/arch/arm/domain.c
xen/arch/arm/setup.c
xen/arch/x86/setup.c
xen/common/domain.c
xen/common/domctl.c
xen/drivers/passthrough/device_tree.c
xen/drivers/passthrough/iommu.c
xen/include/public/domctl.h
xen/include/xen/sched.h

index 43aafa7e22b3250a60b8a2df1e38bf708aee2258..35dddbbd9c56b51cee479a900f3bc46d74ee1756 100644 (file)
@@ -63,6 +63,7 @@ type domain_create_flag =
        | CDF_S3_INTEGRITY
        | CDF_OOS_OFF
        | CDF_XS_DOMAIN
+       | CDF_IOMMU
 
 type domctl_create_config =
 {
index 1bcfa3f83977694b8b864fb92b96c5ca8fa5b45a..0dd55e9d8b35a5b00417118f2e4df9f0e789eb84 100644 (file)
@@ -56,6 +56,7 @@ type domain_create_flag =
   | CDF_S3_INTEGRITY
   | CDF_OOS_OFF
   | CDF_XS_DOMAIN
+  | CDF_IOMMU
 
 type domctl_create_config = {
   ssidref: int32;
index a9c4113c267560a2c5301692105b6ed9ee32baaa..ae13e47e861885e974bf37a4204676f5bcd697f0 100644 (file)
@@ -608,9 +608,12 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
 {
     unsigned int max_vcpus;
 
-    if ( config->flags != (XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap) )
+    /* HVM and HAP must be set. IOMMU may or may not be */
+    if ( (config->flags & ~XEN_DOMCTL_CDF_iommu) !=
+         (XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap) )
     {
-        dprintk(XENLOG_INFO, "Unsupported configuration %#x\n", config->flags);
+        dprintk(XENLOG_INFO, "Unsupported configuration %#x\n",
+                config->flags);
         return -EINVAL;
     }
 
index ebbfad94e41dde985b588a0b2f396ba2e64e653e..077b8d02a06ec83cffeb5b274d44aec388db54be 100644 (file)
@@ -947,6 +947,9 @@ void __init start_xen(unsigned long boot_phys_offset,
     dom0_cfg.arch.tee_type = tee_get_type();
     dom0_cfg.max_vcpus = dom0_max_vcpus();
 
+    if ( iommu_enabled )
+        dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu;
+
     dom0 = domain_create(0, &dom0_cfg, true);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
         panic("Error creating domain 0\n");
index 27981adc0ba17816993e1e8d2193fdb2531f2fa4..dec60d03019cd43da17fc1b5d7d7e2628bcf8ace 100644 (file)
@@ -1732,6 +1732,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     }
     dom0_cfg.max_vcpus = dom0_max_vcpus();
 
+    if ( iommu_enabled )
+        dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu;
+
     /* Create initial domain 0. */
     dom0 = domain_create(get_initial_domain_id(), &dom0_cfg, !pv_shim);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
index 09917b288559cc7e518753104fb2babab84a183e..4681f29c8b25ef0459a673d74b71be355cbbee68 100644 (file)
@@ -301,7 +301,8 @@ static int sanitise_domain_config(struct xen_domctl_createdomain *config)
                            XEN_DOMCTL_CDF_hap |
                            XEN_DOMCTL_CDF_s3_integrity |
                            XEN_DOMCTL_CDF_oos_off |
-                           XEN_DOMCTL_CDF_xs_domain) )
+                           XEN_DOMCTL_CDF_xs_domain |
+                           XEN_DOMCTL_CDF_iommu) )
     {
         dprintk(XENLOG_INFO, "Unknown CDF flags %#x\n", config->flags);
         return -EINVAL;
@@ -320,6 +321,12 @@ static int sanitise_domain_config(struct xen_domctl_createdomain *config)
         return -EINVAL;
     }
 
+    if ( (config->flags & XEN_DOMCTL_CDF_iommu) && !iommu_enabled )
+    {
+        dprintk(XENLOG_INFO, "IOMMU is not enabled\n");
+        return -EINVAL;
+    }
+
     return arch_sanitise_domain_config(config);
 }
 
index 6e6e9b986682a1862d804f166426d1859057c4c7..5dcfe3c8f6a164b39d28d0366978c7b70312d158 100644 (file)
@@ -515,6 +515,19 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
             rover = dom;
         }
 
+        /*
+         * For now, make sure the createdomain IOMMU flag is set if the
+         * IOMMU is enabled. When the flag comes under toolstack control
+         * this can go away.
+         */
+        if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_iommu )
+        {
+            ASSERT_UNREACHABLE();
+            return -EINVAL;
+        }
+        if ( iommu_enabled )
+            op->u.createdomain.flags |= XEN_DOMCTL_CDF_iommu;
+
         d = domain_create(dom, &op->u.createdomain, false);
         if ( IS_ERR(d) )
         {
index b6eaae728319b1ef5633bdc2f68c4193e1e2951b..d32b17266414d4dcb54c01335ea3180e8215ff79 100644 (file)
@@ -119,6 +119,9 @@ int iommu_release_dt_devices(struct domain *d)
     struct dt_device_node *dev, *_dev;
     int rc;
 
+    if ( !is_iommu_enabled(d) )
+        return 0;
+
     list_for_each_entry_safe(dev, _dev, &hd->dt_devices, domain_list)
     {
         rc = iommu_deassign_dt_device(d, dev);
index b82f778479d915892e55f486b6748203811c8c57..f42402bc92ec3792d541097bec96220acdc19842 100644 (file)
@@ -151,6 +151,9 @@ int iommu_domain_init(struct domain *d)
     struct domain_iommu *hd = dom_iommu(d);
     int ret = 0;
 
+    if ( !is_iommu_enabled(d) )
+        return 0;
+
 #ifdef CONFIG_NUMA
     hd->node = NUMA_NO_NODE;
 #endif
@@ -159,9 +162,6 @@ int iommu_domain_init(struct domain *d)
     if ( ret )
         return ret;
 
-    if ( !iommu_enabled )
-        return 0;
-
     hd->platform_ops = iommu_get_ops();
     return hd->platform_ops->init(d);
 }
index 77f546cbb8b4cf2de3d3985fb86d57eed26ea047..1b3176adb51a9bcf4df79f852aa4f353b6ef4552 100644 (file)
@@ -64,9 +64,12 @@ struct xen_domctl_createdomain {
  /* Is this a xenstore domain? */
 #define _XEN_DOMCTL_CDF_xs_domain     4
 #define XEN_DOMCTL_CDF_xs_domain      (1U<<_XEN_DOMCTL_CDF_xs_domain)
+ /* Should this domain be permitted to use the IOMMU? */
+#define _XEN_DOMCTL_CDF_iommu         5
+#define XEN_DOMCTL_CDF_iommu          (1U<<_XEN_DOMCTL_CDF_iommu)
 
 /* Max XEN_DOMCTL_CDF_* constant.  Used for ABI checking. */
-#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_xs_domain
+#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_iommu
 
     uint32_t flags;
 
index e3601c1935d7190e07fc7a009eb9de63c4c4cb5f..2d17c849155dcb82ff6b5ddac8e845ee2edb4486 100644 (file)
@@ -983,6 +983,11 @@ static inline bool is_xenstore_domain(const struct domain *d)
     return d->options & XEN_DOMCTL_CDF_xs_domain;
 }
 
+static inline bool is_iommu_enabled(const struct domain *d)
+{
+    return evaluate_nospec(d->options & XEN_DOMCTL_CDF_iommu);
+}
+
 extern bool sched_smt_power_savings;
 
 extern enum cpufreq_controller {