Introduce the ability to specify the desired domain id for the domain
definition. The domain id will be populated in the domid property of the domain
node in the device tree configuration.
Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
Changes since v1
- coding style changes
- moved comment with code movement
- updated warning message
- unrolled match_fdt_property()
---
xen/arch/x86/domain-builder/fdt.c | 63 ++++++++++++++++++++++++++++-
xen/arch/x86/setup.c | 5 ++-
xen/include/xen/libfdt/libfdt-xen.h | 9 +++++
3 files changed, 73 insertions(+), 4 deletions(-)
diff --git a/xen/arch/x86/domain-builder/fdt.c b/xen/arch/x86/domain-builder/fdt.c
index 27bc37ad45c9..efce0927c645 100644
--- a/xen/arch/x86/domain-builder/fdt.c
+++ b/xen/arch/x86/domain-builder/fdt.c
@@ -8,6 +8,7 @@
#include <xen/libfdt/libfdt.h>
#include <asm/bootinfo.h>
+#include <asm/guest.h>
#include <asm/page.h>
#include <asm/setup.h>
@@ -61,10 +62,40 @@ static int __init dom0less_module_index(
static int __init process_domain_node(
struct boot_info *bi, void *fdt, int dom_node)
{
- int node;
+ int node, property;
struct boot_domain *bd = &bi->domains[bi->nr_domains];
const char *name = fdt_get_name(fdt, dom_node, NULL) ?: "unknown";
+ fdt_for_each_property_offset(property, fdt, dom_node)
+ {
+ const struct fdt_property *prop;
+ const char *prop_name;
+ int name_len;
+
+ prop = fdt_get_property_by_offset(fdt, property, NULL);
+ if ( !prop )
+ continue; /* silently skip */
+
+ prop_name = fdt_get_string(fdt, fdt32_to_cpu(prop->nameoff), &name_len);
+
+ if ( strncmp(prop_name, "domid", name_len) == 0 )
+ {
+ uint32_t val = DOMID_INVALID;
+ if ( fdt_prop_as_u32(prop, &val) != 0 )
+ {
+ printk(" failed processing domain id for domain %s\n", name);
+ return -EINVAL;
+ }
+ if ( val >= DOMID_FIRST_RESERVED )
+ {
+ printk(" invalid domain id for domain %s\n", name);
+ return -EINVAL;
+ }
+ bd->domid = (domid_t)val;
+ printk(" domid: %d\n", bd->domid);
+ }
+ }
+
fdt_for_each_subnode(node, fdt, dom_node)
{
if ( fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 )
@@ -125,7 +156,29 @@ static int __init process_domain_node(
else if (
fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 )
{
- int idx = dom0less_module_node(fdt, node, size_size, address_size);
+ unsigned int idx;
+ int ret = 0;
+
+ if ( bd->ramdisk )
+ {
+ printk(XENLOG_ERR "Duplicate ramdisk module for domain %s)\n",
+ name);
+ continue;
+ }
+
+ /* Try hyperlaunch property, fall back to dom0less property. */
+ if ( hl_module_index(fdt, node, &idx) < 0 )
+ {
+ int address_size = fdt_address_cells(fdt, dom_node);
+ int size_size = fdt_size_cells(fdt, dom_node);
+
+ if ( address_size < 0 || size_size < 0 )
+ ret = -EINVAL;
+ else
+ ret = dom0less_module_index(
+ fdt, node, size_size, address_size, &idx);
+ }
+
if ( idx < 0 )
{
printk(" failed processing ramdisk module for domain %s\n",
@@ -154,6 +207,12 @@ static int __init process_domain_node(
return -EFAULT;
}
+ if ( bd->domid == DOMID_INVALID )
+ bd->domid = get_initial_domain_id();
+ else if ( bd->domid != get_initial_domain_id() )
+ printk(XENLOG_WARNING
+ "WARN: Booting without initial domid not supported.\n");
+
return 0;
}
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 25ff029ecdda..027b224151d1 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1029,8 +1029,9 @@ static struct domain *__init create_dom0(struct boot_info *bi)
if ( iommu_enabled )
dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu;
- /* Create initial domain. Not d0 for pvshim. */
- bd->domid = get_initial_domain_id();
+ if ( bd->domid == DOMID_INVALID )
+ /* Create initial domain. Not d0 for pvshim. */
+ bd->domid = get_initial_domain_id();
d = domain_create(bd->domid, &dom0_cfg, pv_shim ? 0 : CDF_privileged);
if ( IS_ERR(d) )
panic("Error creating d%u: %ld\n", bd->domid, PTR_ERR(d));
diff --git a/xen/include/xen/libfdt/libfdt-xen.h b/xen/include/xen/libfdt/libfdt-xen.h
index 0e54aeeb6cc2..2057030dda45 100644
--- a/xen/include/xen/libfdt/libfdt-xen.h
+++ b/xen/include/xen/libfdt/libfdt-xen.h
@@ -28,6 +28,15 @@ static inline int __init fdt_cell_as_u64(const fdt32_t *cell, uint64_t *val)
return 0;
}
+static inline int __init fdt_prop_as_u32(
+ const struct fdt_property *prop, uint32_t *val)
+{
+ if ( !prop || fdt32_to_cpu(prop->len) < sizeof(u32) )
+ return -EINVAL;
+
+ return fdt_cell_as_u32((fdt32_t *)prop->data, val);
+}
+
static inline int __init fdt_get_prop_by_offset(
const void *fdt, int node, const char *name, unsigned long *offset)
{
--
2.30.2