]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
xen/dom0less: support for vcpu affinity
authorXenia Ragiadakou <xenia.ragiadakou@amd.com>
Thu, 20 Feb 2025 21:37:12 +0000 (13:37 -0800)
committerStefano Stabellini <stefano.stabellini@amd.com>
Tue, 4 Mar 2025 00:05:13 +0000 (16:05 -0800)
Add vcpu affinity to the dom0less bindings. Example:

    dom1 {
            ...
            cpus = <4>;
            vcpu0 {
                   compatible = "xen,vcpu";
                   id = <0>;
                   hard-affinity = "4-7";
            };
            vcpu1 {
                   compatible = "xen,vcpu";
                   id = <1>;
                   hard-affinity = "0-3,5";
            };
            vcpu2 {
                   compatible = "xen,vcpu";
                   id = <2>;
                   hard-affinity = "1,6";
            };
            ...

Note that the property hard-affinity is optional. It is possible to add
other properties in the future not only to specify soft affinity, but
also to provide more precise methods for configuring affinity. For
instance, on ARM the MPIDR could be use to specify the pCPU. For now, it
is left to the future.

Signed-off-by: Xenia Ragiadakou <xenia.ragiadakou@amd.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@amd.com>
Acked-by: Julien Grall <jgrall@amazon.com>
docs/misc/arm/device-tree/booting.txt
xen/arch/arm/dom0less-build.c

index 4d6d859c666c412e288a6813bdbc458b84a043a5..ac781c9cc8032e984dcb9cd11a5e8335a8190296 100644 (file)
@@ -329,6 +329,28 @@ The ramdisk sub-node has the following properties:
     property because it will be created by the UEFI stub on boot.
     This option is needed only when UEFI boot is used.
 
+Under the "xen,domain" compatible node, it is possible optionally to add
+one or more sub-nodes to configure vCPU affinity. The vCPU affinity
+sub-node has the following properties:
+
+- compatible
+
+    "xen,vcpu"
+
+- id
+
+    A 32-bit integer that specifies the vCPU id. 0 is the first vCPU.
+    The last vCPU is cpus-1, where "cpus" is the number of vCPUs
+    specified with the "cpus" property under the "xen,domain" node.
+    Each "xen,vcpu" node must have a unique vCPU id.
+
+- hard-affinity
+
+    Optional. A string specifying the hard affinity configuration for the
+    vCPU: a comma-separated list of pCPUs or ranges of pCPUs is used.
+    Ranges are hyphen-separated intervals (such as `0-4`) and are inclusive
+    on both sides. The numbers refer to logical pCPU ids.
+
 
 Example
 =======
@@ -342,6 +364,18 @@ chosen {
         cpus = <2>;
         vpl011;
 
+        vcpu0 {
+            compatible = "xen,vcpu";
+            id = <0>;
+            hard-affinity = "0-3";
+        };
+
+        vcpu1 {
+            compatible = "xen,vcpu";
+            id = <1>;
+            hard-affinity = "1,4-7";
+        };
+
         module@0x4a000000 {
             compatible = "multiboot,kernel", "multiboot,module";
             reg = <0x0 0x4a000000 0xffffff>;
index 1d735f86db6034ad12e307c5e63c79df72df0b12..31f31c38da3fcddd97a5d25573d5fbd3e87aae85 100644 (file)
@@ -779,6 +779,68 @@ static int __init alloc_xenstore_params(struct kernel_info *kinfo)
     return rc;
 }
 
+static void __init domain_vcpu_affinity(struct domain *d,
+                                        const struct dt_device_node *node)
+{
+    struct dt_device_node *np;
+
+    dt_for_each_child_node(node, np)
+    {
+        const char *hard_affinity_str = NULL;
+        uint32_t val;
+        int rc;
+        struct vcpu *v;
+        cpumask_t affinity;
+
+        if ( !dt_device_is_compatible(np, "xen,vcpu") )
+            continue;
+
+        if ( !dt_property_read_u32(np, "id", &val) )
+            panic("Invalid xen,vcpu node for domain %s\n", dt_node_name(node));
+
+        if ( val >= d->max_vcpus )
+            panic("Invalid vcpu_id %u for domain %s, max_vcpus=%u\n", val,
+                  dt_node_name(node), d->max_vcpus);
+
+        v = d->vcpu[val];
+        rc = dt_property_read_string(np, "hard-affinity", &hard_affinity_str);
+        if ( rc < 0 )
+            continue;
+
+        cpumask_clear(&affinity);
+        while ( *hard_affinity_str != '\0' )
+        {
+            unsigned int start, end;
+
+            start = simple_strtoul(hard_affinity_str, &hard_affinity_str, 0);
+
+            if ( *hard_affinity_str == '-' )    /* Range */
+            {
+                hard_affinity_str++;
+                end = simple_strtoul(hard_affinity_str, &hard_affinity_str, 0);
+            }
+            else                /* Single value */
+                end = start;
+
+            if ( end >= nr_cpu_ids )
+                panic("Invalid pCPU %u for domain %s\n", end, dt_node_name(node));
+
+            for ( ; start <= end; start++ )
+                cpumask_set_cpu(start, &affinity);
+
+            if ( *hard_affinity_str == ',' )
+                hard_affinity_str++;
+            else if ( *hard_affinity_str != '\0' )
+                break;
+        }
+
+        rc = vcpu_set_hard_affinity(v, &affinity);
+        if ( rc )
+            panic("vcpu%d: failed (rc=%d) to set hard affinity for domain %s\n",
+                  v->vcpu_id, rc, dt_node_name(node));
+    }
+}
+
 static int __init construct_domU(struct domain *d,
                                  const struct dt_device_node *node)
 {
@@ -880,6 +942,8 @@ static int __init construct_domU(struct domain *d,
     if ( rc < 0 )
         return rc;
 
+    domain_vcpu_affinity(d, node);
+
     return alloc_xenstore_params(&kinfo);
 }