diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt index ac781c9cc8..59fa96a82e 100644 --- a/docs/misc/arm/device-tree/booting.txt +++ b/docs/misc/arm/device-tree/booting.txt @@ -167,6 +167,17 @@ with the following properties: Refer to docs/misc/cache_coloring.rst for syntax. This option is applicable only to Arm64 guests. +- capabilities + Optional. A 32-bit integer representing a bit field of domain capabilities + for a disaggregated system. A traditional dom0 has all of these + capabilities, and a domU has none of them. + + 0x1 DOMAIN_CAPS_CONTROL - A privileged, control domain + 0x2 DOMAIN_CAPS_HARDWARE - The hardware domain - there can be only 1 + 0x4 DOMAIN_CAPS_XENSTORE - The xenstore domain - there can be only 1 + + The default is no capabilities. + - vpl011 An empty property to enable/disable a virtual pl011 for the guest to diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c index 50d2d3e4e4..a356fc94fc 100644 --- a/xen/arch/arm/dom0less-build.c +++ b/xen/arch/arm/dom0less-build.c @@ -12,11 +12,13 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -928,6 +930,8 @@ static int __init construct_domU(struct domain *d, d->max_vcpus, mem); kinfo.vpl011 = dt_property_read_bool(node, "vpl011"); + if ( kinfo.vpl011 && is_hardware_domain(d) ) + panic("hardware domain cannot specify vpl011\n"); rc = dt_property_read_string(node, "xen,enhanced", &dom0less_enhanced); if ( rc == -EILSEQ || @@ -1043,6 +1047,37 @@ void __init create_domUs(void) if ( (max_init_domid + 1) >= DOMID_FIRST_RESERVED ) panic("No more domain IDs available\n"); + if ( dt_property_read_u32(node, "capabilities", &val) ) + { + if ( val & ~DOMAIN_CAPS_MASK ) + panic("Invalid capabilities (%"PRIx32")\n", val); + + if ( val & DOMAIN_CAPS_CONTROL ) + flags |= CDF_privileged; + + if ( val & DOMAIN_CAPS_HARDWARE ) + { + if ( hardware_domain ) + panic("Only 1 hardware domain can be specified! (%pd)\n", + hardware_domain); + + d_cfg.max_grant_frames = gnttab_dom0_frames(); + d_cfg.max_evtchn_port = -1; + flags |= CDF_hardware; + iommu = true; + } + + if ( val & DOMAIN_CAPS_XENSTORE ) + { + if ( xs_domid != DOMID_INVALID ) + panic("Only 1 xenstore domain can be specified! (%u)\n", + xs_domid); + + d_cfg.flags |= XEN_DOMCTL_CDF_xs_domain; + d_cfg.max_evtchn_port = -1; + } + } + if ( dt_find_property(node, "xen,static-mem", NULL) ) { if ( llc_coloring_enabled ) @@ -1064,12 +1099,26 @@ void __init create_domUs(void) panic("Missing property 'cpus' for domain %s\n", dt_node_name(node)); - if ( !dt_property_read_string(node, "passthrough", &dom0less_iommu) && - !strcmp(dom0less_iommu, "enabled") ) - iommu = true; + if ( !dt_property_read_string(node, "passthrough", &dom0less_iommu) ) + { + if ( flags & CDF_hardware ) + panic("Don't specify passthrough for hardware domain\n"); + + if ( !strcmp(dom0less_iommu, "enabled") ) + iommu = true; + } + + if ( (flags & CDF_hardware) && !(flags & CDF_directmap) && + !iommu_enabled ) + panic("non-direct mapped hardware domain requires iommu\n"); if ( dt_find_compatible_node(node, NULL, "multiboot,device-tree") ) + { + if ( flags & CDF_hardware ) + panic("\"multiboot,device-tree\" incompatible with hardware domain\n"); + has_dtb = true; + } if ( iommu_enabled && (iommu || has_dtb) ) d_cfg.flags |= XEN_DOMCTL_CDF_iommu; @@ -1106,6 +1155,8 @@ void __init create_domUs(void) d_cfg.arch.nr_spis = MAX(d_cfg.arch.nr_spis, vpl011_virq - 32 + 1); } + else if ( flags & CDF_hardware ) + panic("nr_spis cannot be specified for hardware domain\n"); /* Get the optional property domain-cpupool */ cpupool_node = dt_parse_phandle(node, "domain-cpupool", 0); diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 3ba959f866..dc4b4e84c1 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -608,7 +608,8 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) { unsigned int max_vcpus; unsigned int flags_required = (XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap); - unsigned int flags_optional = (XEN_DOMCTL_CDF_iommu | XEN_DOMCTL_CDF_vpmu); + unsigned int flags_optional = (XEN_DOMCTL_CDF_iommu | XEN_DOMCTL_CDF_vpmu | + XEN_DOMCTL_CDF_xs_domain ); unsigned int sve_vl_bits = sve_decode_vl(config->arch.sve_vl); if ( (config->flags & ~flags_optional) != flags_required ) diff --git a/xen/include/public/bootfdt.h b/xen/include/public/bootfdt.h new file mode 100644 index 0000000000..86c46b42a9 --- /dev/null +++ b/xen/include/public/bootfdt.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Xen Device Tree boot information + * + * Information for configuring Xen domains created at boot time. + */ + +#ifndef __XEN_PUBLIC_BOOTFDT_H__ +#define __XEN_PUBLIC_BOOTFDT_H__ + +/* + * Domain Capabilities specified in the "capabilities" property. Use of + * this property allows splitting up the monolithic dom0 into separate, + * less privileged components. A regular domU has no capabilities + * (which is the default if nothing is specified). A traditional dom0 + * has all three capabilities. + */ + +/* Control/Privileged domain capable of affecting other domains. */ +#define DOMAIN_CAPS_CONTROL (1U << 0) +/* + * Hardware domain controlling physical hardware. Typically providing + * backends to other domains. + */ +#define DOMAIN_CAPS_HARDWARE (1U << 1) +/* Xenstore domain. */ +#define DOMAIN_CAPS_XENSTORE (1U << 2) +#define DOMAIN_CAPS_MASK (DOMAIN_CAPS_CONTROL | DOMAIN_CAPS_HARDWARE | \ + DOMAIN_CAPS_XENSTORE) + +#endif /* __XEN_PUBLIC_BOOTFDT_H__ */