@@ -975,14 +975,18 @@ void __init create_domUs(void)
.grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version),
};
unsigned int flags = 0U;
+ domid_t domid;
uint32_t val;
int rc;
if ( !dt_device_is_compatible(node, "xen,domain") )
continue;
- if ( (domid_top + 1) >= DOMID_FIRST_RESERVED )
- panic("No more domain IDs available\n");
+ rc = domid_alloc(DOMID_AUTO);
+ if ( rc < 0 )
+ panic("cannot allocate domain ID for domain %s (rc = %d)\n",
+ dt_node_name(node), rc);
+ domid = rc;
if ( dt_find_property(node, "xen,static-mem", NULL) )
{
@@ -1107,12 +1111,7 @@ void __init create_domUs(void)
if ( !llc_coloring_enabled && llc_colors_str )
panic("'llc-colors' found, but LLC coloring is disabled\n");
- /*
- * The variable max_init_domid is initialized with zero, so here it's
- * very important to use the pre-increment operator to call
- * domain_create() with a domid > 0. (domid == 0 is reserved for Dom0)
- */
- d = domain_create(++domid_top, &d_cfg, flags);
+ d = domain_create(domid, &d_cfg, flags);
if ( IS_ERR(d) )
panic("Error creating domain %s (rc = %ld)\n",
dt_node_name(node), PTR_ERR(d));
@@ -2367,8 +2367,15 @@ void __init create_dom0(void)
.grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version),
};
unsigned int flags = CDF_privileged;
+ domid_t domid;
int rc;
+ rc = domid_alloc(get_initial_domain_id());
+ if ( rc < 0 )
+ panic("Cannot use domain ID %d (rc = %d)\n",
+ get_initial_domain_id(), rc);
+ domid = rc;
+
/* The vGIC for DOM0 is exactly emulating the hardware GIC */
dom0_cfg.arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
dom0_cfg.arch.nr_spis = VGIC_DEF_NR_SPIS;
@@ -2391,19 +2398,21 @@ void __init create_dom0(void)
if ( !llc_coloring_enabled )
flags |= CDF_directmap;
- dom0 = domain_create(0, &dom0_cfg, flags);
+ dom0 = domain_create(domid, &dom0_cfg, flags);
if ( IS_ERR(dom0) )
- panic("Error creating domain 0 (rc = %ld)\n", PTR_ERR(dom0));
+ panic("Error creating domain %d (rc = %ld)\n", domid, PTR_ERR(dom0));
if ( llc_coloring_enabled && (rc = dom0_set_llc_colors(dom0)) )
- panic("Error initializing LLC coloring for domain 0 (rc = %d)\n", rc);
+ panic("Error initializing LLC coloring for domain %d (rc = %d)\n",
+ domid, rc);
if ( alloc_dom0_vcpu0(dom0) == NULL )
- panic("Error creating domain 0 vcpu0\n");
+ panic("Error creating domain %d vcpu0\n", domid);
rc = construct_dom0(dom0);
if ( rc )
- panic("Could not set up DOM0 guest OS (rc = %d)\n", rc);
+ panic("Could not set up guest OS for domain %d (rc = %d)\n",
+ domid, rc);
}
/*
@@ -63,6 +63,46 @@ static inline int is_free_domid(domid_t dom)
return 0;
}
+/*
+ * Allocate new domain ID based on the hint.
+ *
+ * If hint is outside of valid [0..DOMID_FIRST_RESERVED] range of IDs,
+ * perform an exhaustive search of the first free domain ID excluding
+ * hardware_domid.
+ */
+int domid_alloc(int hint)
+{
+ domid_t domid;
+
+ if ( hint >= 0 && hint < DOMID_FIRST_RESERVED )
+ {
+ if ( !is_free_domid(hint) )
+ return -EEXIST;
+
+ domid = hint;
+ }
+ else
+ {
+ for ( domid = domid_top + 1; domid != domid_top; domid++ )
+ {
+ if ( domid == DOMID_FIRST_RESERVED )
+ domid = 0;
+ if ( domid == hardware_domid )
+ continue;
+ if ( is_free_domid(domid) )
+ break;
+ }
+
+ if ( domid == domid_top )
+ return -ENOMEM;
+ }
+
+ if ( domid_top < domid )
+ domid_top = domid;
+
+ return domid;
+}
+
void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
{
struct vcpu *v;
@@ -421,34 +461,11 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
case XEN_DOMCTL_createdomain:
{
- domid_t dom;
- static domid_t rover = 0;
+ ret = domid_alloc(op->domain);
+ if ( ret < 0 )
+ break;
- dom = op->domain;
- if ( (dom > 0) && (dom < DOMID_FIRST_RESERVED) )
- {
- ret = -EEXIST;
- if ( !is_free_domid(dom) )
- break;
- }
- else
- {
- for ( dom = rover + 1; dom != rover; dom++ )
- {
- if ( dom == DOMID_FIRST_RESERVED )
- dom = 1;
- if ( is_free_domid(dom) )
- break;
- }
-
- ret = -ENOMEM;
- if ( dom == rover )
- break;
-
- rover = dom;
- }
-
- d = domain_create(dom, &op->u.createdomain, false);
+ d = domain_create(ret, &op->u.createdomain, false);
if ( IS_ERR(d) )
{
ret = PTR_ERR(d);
@@ -568,6 +568,14 @@ static long xenver_varbuf_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
return sz;
}
+static int __init cf_check globals_init(void)
+{
+ domid_top = get_initial_domain_id();
+
+ return 0;
+}
+__initcall(globals_init);
+
long do_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
{
bool deny = xsm_xen_version(XSM_OTHER, cmd);
@@ -39,6 +39,9 @@ extern domid_t domid_top;
domid_t get_initial_domain_id(void);
+#define DOMID_AUTO (-1)
+int domid_alloc(int hint);
+
/* CDF_* constant. Internal flags for domain creation. */
/* Is this a privileged domain? */
#define CDF_privileged (1U << 0)
Move domain ID allocation to a dedicated function domid_alloc() and use it during domain creation. Update domid_top within domid_alloc() to reflect the highest known domain ID. Initialize domid_top using the result of get_initial_domain_id(). Allocation algorithm: - If an explicit domain ID is provided, verify its availability and use it if free; - Otherwise, perform an exhaustive search for the first available ID within the [0..DOMID_FIRST_RESERVED) range, excluding hardware_domid. The change is a prerequisite for enabling console input rotation across domains on x86 (currently, limited to dom0, PV shim and Xen). Signed-off-by: Denis Mukhin <dmukhin@ford.com> --- xen/arch/arm/dom0less-build.c | 15 ++++---- xen/arch/arm/domain_build.c | 19 +++++++--- xen/common/domctl.c | 71 ++++++++++++++++++++++------------- xen/common/kernel.c | 8 ++++ xen/include/xen/domain.h | 3 ++ 5 files changed, 76 insertions(+), 40 deletions(-)