[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC 37/52] i386: Update X86CPUTopoIDs generating rule for hybrid topolo
From: |
Zhao Liu |
Subject: |
[RFC 37/52] i386: Update X86CPUTopoIDs generating rule for hybrid topology |
Date: |
Mon, 13 Feb 2023 17:50:20 +0800 |
From: Zhao Liu <zhao1.liu@intel.com>
X86CPUTopoIDs can be parsed form cpu_index or APIC ID. For hybrid CPU
topology, the case, generating form cpu_index, need to update.
In x86_topo_ids_from_idx(), if current topology is hybrid, traverse all
clusters and cores to find the cluster, core and thread that cpu_index
matches.
Co-Developed-by: Zhuocheng Ding <zhuocheng.ding@intel.com>
Signed-off-by: Zhuocheng Ding <zhuocheng.ding@intel.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
hw/i386/x86.c | 78 ++++++++++++++++++++++++++++++-
include/hw/i386/topology.h | 36 --------------
tests/unit/test-x86-apicid.c | 91 +++++++++++++++++++++++-------------
3 files changed, 136 insertions(+), 69 deletions(-)
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 1c071f8120cb..a09df6d33fff 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -103,6 +103,82 @@ inline void init_apicid_topo_info(X86ApicidTopoInfo
*apicid_topo,
}
}
+/*
+ * Calculate thread/core/package IDs for a specific topology,
+ * based on (contiguous) CPU index
+ */
+static void x86_topo_ids_from_idx(X86MachineState *x86ms,
+ unsigned cpu_index,
+ X86CPUTopoIDs *topo_ids)
+{
+ MachineState *ms = MACHINE(x86ms);
+ unsigned nr_dies;
+ unsigned nr_modules;
+ unsigned nr_cores;
+ unsigned nr_threads;
+ unsigned cpus_per_pkg;
+ unsigned cpus_per_die;
+
+ nr_dies = machine_topo_get_dies(ms);
+ nr_modules = machine_topo_get_clusters(ms);
+ cpus_per_pkg = machine_topo_get_threads_per_socket(ms);
+ cpus_per_die = cpus_per_pkg / nr_dies;
+
+ topo_ids->pkg_id = cpu_index / cpus_per_pkg;
+ topo_ids->die_id = cpu_index / cpus_per_die % nr_dies;
+
+ if (machine_topo_is_smp(ms)) {
+ nr_cores = machine_topo_get_smp_cores(ms);
+ nr_threads = machine_topo_get_smp_threads(ms);
+
+ topo_ids->module_id = cpu_index / (nr_cores * nr_threads) %
+ nr_modules;
+ topo_ids->core_id = cpu_index / nr_threads % nr_cores;
+ topo_ids->smt_id = cpu_index % nr_threads;
+ } else {
+ /*
+ * Next we need to traverse in the die, so scale the cpu_index to
+ * the relative index in the die.
+ */
+ int idx = cpu_index % cpus_per_die;
+
+ topo_ids->module_id = 0;
+ topo_ids->core_id = 0;
+ topo_ids->smt_id = 0;
+
+ for (int i = 0; i < nr_modules; i++) {
+ nr_cores = machine_topo_get_cores(ms, i);
+
+ for (int j = 0; j < nr_cores; j++) {
+ nr_threads = machine_topo_get_threads(ms, i, j);
+
+ if (idx < nr_threads) {
+ topo_ids->module_id = i;
+ topo_ids->core_id = j;
+ topo_ids->smt_id = idx;
+ return;
+ } else {
+ idx -= nr_threads;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Make APIC ID for the CPU 'cpu_index'
+ *
+ * 'cpu_index' is a sequential, contiguous ID for the CPU.
+ */
+static inline apic_id_t x86_apicid_from_cpu_idx(X86MachineState *x86ms,
+ X86ApicidTopoInfo *apicid_topo,
+ unsigned cpu_index)
+{
+ X86CPUTopoIDs topo_ids;
+ x86_topo_ids_from_idx(x86ms, cpu_index, &topo_ids);
+ return x86_apicid_from_topo_ids(apicid_topo, &topo_ids);
+}
+
/*
* Calculates initial APIC ID for a specific CPU index
*
@@ -118,7 +194,7 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
init_apicid_topo_info(&apicid_topo, x86ms);
- return x86_apicid_from_cpu_idx(&apicid_topo, cpu_index);
+ return x86_apicid_from_cpu_idx(x86ms, &apicid_topo, cpu_index);
}
diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h
index 5b29c51329f1..06403ca77087 100644
--- a/include/hw/i386/topology.h
+++ b/include/hw/i386/topology.h
@@ -153,29 +153,6 @@ static inline apic_id_t
x86_apicid_from_topo_ids(X86ApicidTopoInfo *apicid_topo,
topo_ids->smt_id;
}
-/*
- * Calculate thread/core/package IDs for a specific topology,
- * based on (contiguous) CPU index
- */
-static inline void x86_topo_ids_from_idx(X86ApicidTopoInfo *apicid_topo,
- unsigned cpu_index,
- X86CPUTopoIDs *topo_ids)
-{
- unsigned nr_dies = apicid_topo->max_dies;
- unsigned nr_modules = apicid_topo->max_modules;
- unsigned nr_cores = apicid_topo->max_cores;
- unsigned nr_threads = apicid_topo->max_threads;
-
- topo_ids->pkg_id = cpu_index / (nr_dies * nr_modules *
- nr_cores * nr_threads);
- topo_ids->die_id = cpu_index / (nr_modules * nr_cores *
- nr_threads) % nr_dies;
- topo_ids->module_id = cpu_index / (nr_cores * nr_threads) %
- nr_modules;
- topo_ids->core_id = cpu_index / nr_threads % nr_cores;
- topo_ids->smt_id = cpu_index % nr_threads;
-}
-
/*
* Calculate thread/core/package IDs for a specific topology,
* based on APIC ID
@@ -198,17 +175,4 @@ static inline void x86_topo_ids_from_apicid(apic_id_t
apicid,
topo_ids->pkg_id = apicid >> apicid_pkg_offset(apicid_topo);
}
-/*
- * Make APIC ID for the CPU 'cpu_index'
- *
- * 'cpu_index' is a sequential, contiguous ID for the CPU.
- */
-static inline apic_id_t x86_apicid_from_cpu_idx(X86ApicidTopoInfo *apicid_topo,
- unsigned cpu_index)
-{
- X86CPUTopoIDs topo_ids;
- x86_topo_ids_from_idx(apicid_topo, cpu_index, &topo_ids);
- return x86_apicid_from_topo_ids(apicid_topo, &topo_ids);
-}
-
#endif /* HW_I386_TOPOLOGY_H */
diff --git a/tests/unit/test-x86-apicid.c b/tests/unit/test-x86-apicid.c
index fd76d1775a10..917d8c480436 100644
--- a/tests/unit/test-x86-apicid.c
+++ b/tests/unit/test-x86-apicid.c
@@ -23,9 +23,36 @@
*/
#include "qemu/osdep.h"
-
+#include "hw/core/cpu.h"
#include "hw/i386/topology.h"
+static void x86_smp_test_topo_ids_from_idx(X86ApicidTopoInfo *apicid_topo,
+ unsigned cpu_index,
+ X86CPUTopoIDs *topo_ids)
+{
+ unsigned nr_dies = apicid_topo->max_dies;
+ unsigned nr_modules = apicid_topo->max_modules;
+ unsigned nr_cores = apicid_topo->max_cores;
+ unsigned nr_threads = apicid_topo->max_threads;
+
+ topo_ids->pkg_id = cpu_index / (nr_dies * nr_modules *
+ nr_cores * nr_threads);
+ topo_ids->die_id = cpu_index / (nr_modules * nr_cores
+ * nr_threads) % nr_dies;
+ topo_ids->module_id = cpu_index / (nr_cores * nr_threads) % nr_modules;
+ topo_ids->core_id = cpu_index / nr_threads % nr_cores;
+ topo_ids->smt_id = cpu_index % nr_threads;
+}
+
+static apic_id_t
+x86_smp_test_apicid_from_cpu_idx(X86ApicidTopoInfo *apicid_topo,
+ unsigned cpu_index)
+{
+ X86CPUTopoIDs topo_ids;
+ x86_smp_test_topo_ids_from_idx(apicid_topo, cpu_index, &topo_ids);
+ return x86_apicid_from_topo_ids(apicid_topo, &topo_ids);
+}
+
static void test_topo_bits(void)
{
X86ApicidTopoInfo apicid_topo = {0};
@@ -41,10 +68,10 @@ static void test_topo_bits(void)
g_assert_cmpuint(apicid_die_width(&apicid_topo), ==, 0);
apicid_topo = (X86ApicidTopoInfo) {1, 1, 1, 1};
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 0), ==, 0);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 1), ==, 1);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 2), ==, 2);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 3), ==, 3);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 0), ==, 0);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 1), ==, 1);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 2), ==, 2);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 3), ==, 3);
/* Test field width calculation for multiple values
@@ -106,37 +133,37 @@ static void test_topo_bits(void)
g_assert_cmpuint(apicid_pkg_offset(&apicid_topo), ==, 5);
apicid_topo = (X86ApicidTopoInfo) {1, 1, 6, 3};
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 0), ==, 0);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 1), ==, 1);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 2), ==, 2);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 0), ==, 0);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 1), ==, 1);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 2), ==, 2);
apicid_topo = (X86ApicidTopoInfo) {1, 1, 6, 3};
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 1 * 3 + 0), ==,
- (1 << 2) | 0);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 1 * 3 + 1), ==,
- (1 << 2) | 1);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 1 * 3 + 2), ==,
- (1 << 2) | 2);
-
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 2 * 3 + 0), ==,
- (2 << 2) | 0);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 2 * 3 + 1), ==,
- (2 << 2) | 1);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 2 * 3 + 2), ==,
- (2 << 2) | 2);
-
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 5 * 3 + 0), ==,
- (5 << 2) | 0);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 5 * 3 + 1), ==,
- (5 << 2) | 1);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo, 5 * 3 + 2), ==,
- (5 << 2) | 2);
-
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo,
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 1 * 3 + 0),
+ ==, (1 << 2) | 0);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 1 * 3 + 1),
+ ==, (1 << 2) | 1);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 1 * 3 + 2),
+ ==, (1 << 2) | 2);
+
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 2 * 3 + 0),
+ ==, (2 << 2) | 0);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 2 * 3 + 1),
+ ==, (2 << 2) | 1);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 2 * 3 + 2),
+ ==, (2 << 2) | 2);
+
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 5 * 3 + 0),
+ ==, (5 << 2) | 0);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 5 * 3 + 1),
+ ==, (5 << 2) | 1);
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo, 5 * 3 + 2),
+ ==, (5 << 2) | 2);
+
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo,
1 * 6 * 3 + 0 * 3 + 0), ==, (1 << 5));
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo,
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo,
1 * 6 * 3 + 1 * 3 + 1), ==, (1 << 5) | (1 << 2) | 1);
- g_assert_cmpuint(x86_apicid_from_cpu_idx(&apicid_topo,
+ g_assert_cmpuint(x86_smp_test_apicid_from_cpu_idx(&apicid_topo,
3 * 6 * 3 + 5 * 3 + 2), ==, (3 << 5) | (5 << 2) | 2);
}
--
2.34.1
- Re: [RFC 32/52] i386: Rename X86CPUTopoInfo and its members to reflect relationship with APIC ID, (continued)
- [RFC 35/52] i386: Support APIC ID topology for hybrid CPU topology, Zhao Liu, 2023/02/13
- [RFC 33/52] i386: Rename init_topo_info() to init_apic_topo_info(), Zhao Liu, 2023/02/13
- [RFC 34/52] i386: Rename variable topo_info to apicid_topo, Zhao Liu, 2023/02/13
- [RFC 36/52] i386: Use init_apicid_topo_info() to initialize APIC ID topology for system emulator, Zhao Liu, 2023/02/13
- [RFC 38/52] i386: Introduce hybrid_core_type to CPUX86State, Zhao Liu, 2023/02/13
- [RFC 37/52] i386: Update X86CPUTopoIDs generating rule for hybrid topology,
Zhao Liu <=
- [RFC 41/52] machine: Introduce core_type() hook, Zhao Liu, 2023/02/13
- [RFC 42/52] hw/machine: Add hybrid_supported in generic topo properties, Zhao Liu, 2023/02/13