@@ -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 ( (max_init_domid + 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(++max_init_domid, &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);
}
/*
@@ -996,6 +996,7 @@ static struct domain *__init create_dom0(struct boot_info *bi)
domid_t domid;
struct boot_module *image;
unsigned int idx;
+ int rc;
idx = first_boot_module_index(bi, BOOTMOD_KERNEL);
if ( idx >= bi->nr_modules )
@@ -1003,6 +1004,12 @@ static struct domain *__init create_dom0(struct boot_info *bi)
image = &bi->mods[idx];
+ 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;
+
if ( opt_dom0_pvh )
{
dom0_cfg.flags |= (XEN_DOMCTL_CDF_hvm |
@@ -1017,7 +1024,6 @@ static struct domain *__init create_dom0(struct boot_info *bi)
dom0_cfg.flags |= XEN_DOMCTL_CDF_iommu;
/* Create initial domain. Not d0 for pvshim. */
- domid = get_initial_domain_id();
d = domain_create(domid, &dom0_cfg, pv_shim ? 0 : CDF_privileged);
if ( IS_ERR(d) )
panic("Error creating d%u: %ld\n", domid, PTR_ERR(d));
@@ -66,6 +66,51 @@ DEFINE_RCU_READ_LOCK(domlist_read_lock);
static struct domain *domain_hash[DOMAIN_HASH_SIZE];
struct domain *domain_list;
+static inline bool is_free_domid(domid_t dom)
+{
+ struct domain *d = rcu_lock_domain_by_id(dom);
+
+ if ( d )
+ rcu_unlock_domain(d);
+
+ return !d;
+}
+
+/*
+ * 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 = 0; domid < DOMID_FIRST_RESERVED; domid++ )
+ {
+ if ( domid == hardware_domid )
+ continue;
+ if ( is_free_domid(domid) )
+ break;
+ }
+
+ if ( domid == DOMID_FIRST_RESERVED )
+ return -ENOMEM;
+ }
+
+ return domid;
+}
+
/*
* Insert a domain into the domlist/hash. This allows the domain to be looked
* up by domid, and therefore to be the subject of hypercalls/etc.
@@ -49,20 +49,6 @@ static int xenctl_bitmap_to_nodemask(nodemask_t *nodemask,
MAX_NUMNODES);
}
-static inline int is_free_domid(domid_t dom)
-{
- struct domain *d;
-
- if ( dom >= DOMID_FIRST_RESERVED )
- return 0;
-
- if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
- return 1;
-
- rcu_unlock_domain(d);
- return 0;
-}
-
void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
{
struct vcpu *v;
@@ -421,34 +407,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);
@@ -37,6 +37,9 @@ void arch_get_domain_info(const struct domain *d,
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)