From: Zhao Liu <zhao1....@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.d...@intel.com> Signed-off-by: Zhuocheng Ding <zhuocheng.d...@intel.com> Signed-off-by: Zhao Liu <zhao1....@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