diff mbox series

[v1,4/8] xen/domain: introduce domid_alloc()

Message ID 20250318233617.849903-5-dmukhin@ford.com (mailing list archive)
State New
Headers show
Series xen/console: cleanup console input switch logic | expand

Commit Message

Denis Mukhin March 18, 2025, 11:36 p.m. UTC
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(-)
diff mbox series

Patch

diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index d7d7665c0a..4b9e22039e 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -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));
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 2b5b433183..2d8c2931d6 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -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);
 }
 
 /*
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index bfe2e1f9f0..9964aa000a 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -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);
diff --git a/xen/common/kernel.c b/xen/common/kernel.c
index 8b63ca55f1..50c44b986e 100644
--- a/xen/common/kernel.c
+++ b/xen/common/kernel.c
@@ -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);
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index b7425827b8..c91b9704de 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -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)