summary refs log tree commit diff stats
path: root/hw/core/machine-smp.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-12-31 09:33:56 -0800
committerRichard Henderson <richard.henderson@linaro.org>2021-12-31 09:33:56 -0800
commit814a0505302d6af277557f10f88d3639eff7a547 (patch)
treeb40e7bf8b74a28bfe03e5b9cf66cec5244a22f36 /hw/core/machine-smp.c
parent69f153667fce723ee546d2f047d66d0cfa67c3cc (diff)
parent2ece6e64846e1929c4ed338c73328d3b126e48d3 (diff)
downloadfocaccia-qemu-814a0505302d6af277557f10f88d3639eff7a547.tar.gz
focaccia-qemu-814a0505302d6af277557f10f88d3639eff7a547.zip
Merge tag 'machine-core-20211231' of https://github.com/philmd/qemu into staging
Machine core patches

- Clarify qdev_connect_gpio_out() documentation
- Rework test-smp-parse tests following QOM style
- Introduce CPU cluster topology support (Yanan Wang)
- MAINTAINERS updates (Yanan Wang, Li Zhijian, myself)

# gpg: Signature made Fri 31 Dec 2021 04:45:35 AM PST
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]

* tag 'machine-core-20211231' of https://github.com/philmd/qemu:
  MAINTAINERS: email address change
  MAINTAINERS: Change philmd's email address
  MAINTAINERS: Self-recommended as reviewer of "Machine core"
  tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in machine_base_class_init
  tests/unit/test-smp-parse: No need to explicitly zero MachineClass members
  tests/unit/test-smp-parse: Add testcases for CPU clusters
  hw/core/machine: Introduce CPU cluster topology support
  qemu-options: Improve readability of SMP related Docs
  hw/core: Rename smp_parse() -> machine_parse_smp_config()
  tests/unit/test-smp-parse: Constify some pointer/struct
  tests/unit/test-smp-parse: Simplify pointer to compound literal use
  tests/unit/test-smp-parse: Add 'smp-generic-valid' machine type
  tests/unit/test-smp-parse: Add 'smp-generic-invalid' machine type
  tests/unit/test-smp-parse: Add 'smp-with-dies' machine type
  tests/unit/test-smp-parse: Split the 'generic' test in valid / invalid
  tests/unit/test-smp-parse: Pass machine type as argument to tests
  hw/qdev: Rename qdev_connect_gpio_out*() 'input_pin' parameter
  hw/qdev: Correct qdev_connect_gpio_out_named() documentation
  hw/qdev: Correct qdev_init_gpio_out_named() documentation
  hw/qdev: Cosmetic around documentation

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw/core/machine-smp.c')
-rw-r--r--hw/core/machine-smp.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c
index 116a0cbbfa..b39ed21e65 100644
--- a/hw/core/machine-smp.c
+++ b/hw/core/machine-smp.c
@@ -37,6 +37,10 @@ static char *cpu_hierarchy_to_string(MachineState *ms)
         g_string_append_printf(s, " * dies (%u)", ms->smp.dies);
     }
 
+    if (mc->smp_props.clusters_supported) {
+        g_string_append_printf(s, " * clusters (%u)", ms->smp.clusters);
+    }
+
     g_string_append_printf(s, " * cores (%u)", ms->smp.cores);
     g_string_append_printf(s, " * threads (%u)", ms->smp.threads);
 
@@ -44,7 +48,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms)
 }
 
 /*
- * smp_parse - Generic function used to parse the given SMP configuration
+ * machine_parse_smp_config: Generic function used to parse the given
+ *                           SMP configuration
  *
  * Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be
  * automatically computed based on the provided ones.
@@ -63,12 +68,14 @@ static char *cpu_hierarchy_to_string(MachineState *ms)
  * introduced topology members which are likely to be target specific should
  * be directly set as 1 if they are omitted (e.g. dies for PC since 4.1).
  */
-void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
+void machine_parse_smp_config(MachineState *ms,
+                              const SMPConfiguration *config, Error **errp)
 {
     MachineClass *mc = MACHINE_GET_CLASS(ms);
     unsigned cpus    = config->has_cpus ? config->cpus : 0;
     unsigned sockets = config->has_sockets ? config->sockets : 0;
     unsigned dies    = config->has_dies ? config->dies : 0;
+    unsigned clusters = config->has_clusters ? config->clusters : 0;
     unsigned cores   = config->has_cores ? config->cores : 0;
     unsigned threads = config->has_threads ? config->threads : 0;
     unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
@@ -80,6 +87,7 @@ void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
     if ((config->has_cpus && config->cpus == 0) ||
         (config->has_sockets && config->sockets == 0) ||
         (config->has_dies && config->dies == 0) ||
+        (config->has_clusters && config->clusters == 0) ||
         (config->has_cores && config->cores == 0) ||
         (config->has_threads && config->threads == 0) ||
         (config->has_maxcpus && config->maxcpus == 0)) {
@@ -95,8 +103,13 @@ void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
         error_setg(errp, "dies not supported by this machine's CPU topology");
         return;
     }
+    if (!mc->smp_props.clusters_supported && clusters > 1) {
+        error_setg(errp, "clusters not supported by this machine's CPU topology");
+        return;
+    }
 
     dies = dies > 0 ? dies : 1;
+    clusters = clusters > 0 ? clusters : 1;
 
     /* compute missing values based on the provided ones */
     if (cpus == 0 && maxcpus == 0) {
@@ -111,41 +124,42 @@ void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
             if (sockets == 0) {
                 cores = cores > 0 ? cores : 1;
                 threads = threads > 0 ? threads : 1;
-                sockets = maxcpus / (dies * cores * threads);
+                sockets = maxcpus / (dies * clusters * cores * threads);
             } else if (cores == 0) {
                 threads = threads > 0 ? threads : 1;
-                cores = maxcpus / (sockets * dies * threads);
+                cores = maxcpus / (sockets * dies * clusters * threads);
             }
         } else {
             /* prefer cores over sockets since 6.2 */
             if (cores == 0) {
                 sockets = sockets > 0 ? sockets : 1;
                 threads = threads > 0 ? threads : 1;
-                cores = maxcpus / (sockets * dies * threads);
+                cores = maxcpus / (sockets * dies * clusters * threads);
             } else if (sockets == 0) {
                 threads = threads > 0 ? threads : 1;
-                sockets = maxcpus / (dies * cores * threads);
+                sockets = maxcpus / (dies * clusters * cores * threads);
             }
         }
 
         /* try to calculate omitted threads at last */
         if (threads == 0) {
-            threads = maxcpus / (sockets * dies * cores);
+            threads = maxcpus / (sockets * dies * clusters * cores);
         }
     }
 
-    maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
+    maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * clusters * cores * threads;
     cpus = cpus > 0 ? cpus : maxcpus;
 
     ms->smp.cpus = cpus;
     ms->smp.sockets = sockets;
     ms->smp.dies = dies;
+    ms->smp.clusters = clusters;
     ms->smp.cores = cores;
     ms->smp.threads = threads;
     ms->smp.max_cpus = maxcpus;
 
     /* sanity-check of the computed topology */
-    if (sockets * dies * cores * threads != maxcpus) {
+    if (sockets * dies * clusters * cores * threads != maxcpus) {
         g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
         error_setg(errp, "Invalid CPU topology: "
                    "product of the hierarchy must match maxcpus: "