@@ -63,6 +63,7 @@ type domain_create_flag =
| CDF_S3_INTEGRITY
| CDF_OOS_OFF
| CDF_XS_DOMAIN
+ | CDF_IOMMU
type domctl_create_config =
{
@@ -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;
@@ -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;
}
@@ -961,6 +961,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");
@@ -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) )
@@ -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);
}
@@ -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) )
{
@@ -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);
@@ -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);
}
@@ -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;
@@ -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 {