[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 12/23] i386/cpu: Decouple CPUID[0x1F] subleaf with specific topolo
From: |
Paolo Bonzini |
Subject: |
[PULL 12/23] i386/cpu: Decouple CPUID[0x1F] subleaf with specific topology level |
Date: |
Thu, 23 May 2024 17:00:25 +0200 |
From: Zhao Liu <zhao1.liu@intel.com>
At present, the subleaf 0x02 of CPUID[0x1F] is bound to the "die" level.
In fact, the specific topology level exposed in 0x1F depends on the
platform's support for extension levels (module, tile and die).
To help expose "module" level in 0x1F, decouple CPUID[0x1F] subleaf
with specific topology level.
Tested-by: Yongwei Ma <yongwei.ma@intel.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Message-ID: <20240424154929.1487382-12-zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/cpu.c | 135 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 110 insertions(+), 25 deletions(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index d350eb8a736..f95d539eeff 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -269,6 +269,115 @@ static void encode_cache_cpuid4(CPUCacheInfo *cache,
(cache->complex_indexing ? CACHE_COMPLEX_IDX : 0);
}
+static uint32_t num_threads_by_topo_level(X86CPUTopoInfo *topo_info,
+ enum CPUTopoLevel topo_level)
+{
+ switch (topo_level) {
+ case CPU_TOPO_LEVEL_SMT:
+ return 1;
+ case CPU_TOPO_LEVEL_CORE:
+ return topo_info->threads_per_core;
+ case CPU_TOPO_LEVEL_DIE:
+ return topo_info->threads_per_core * topo_info->cores_per_die;
+ case CPU_TOPO_LEVEL_PACKAGE:
+ return topo_info->threads_per_core * topo_info->cores_per_die *
+ topo_info->dies_per_pkg;
+ default:
+ g_assert_not_reached();
+ }
+ return 0;
+}
+
+static uint32_t apicid_offset_by_topo_level(X86CPUTopoInfo *topo_info,
+ enum CPUTopoLevel topo_level)
+{
+ switch (topo_level) {
+ case CPU_TOPO_LEVEL_SMT:
+ return 0;
+ case CPU_TOPO_LEVEL_CORE:
+ return apicid_core_offset(topo_info);
+ case CPU_TOPO_LEVEL_DIE:
+ return apicid_die_offset(topo_info);
+ case CPU_TOPO_LEVEL_PACKAGE:
+ return apicid_pkg_offset(topo_info);
+ default:
+ g_assert_not_reached();
+ }
+ return 0;
+}
+
+static uint32_t cpuid1f_topo_type(enum CPUTopoLevel topo_level)
+{
+ switch (topo_level) {
+ case CPU_TOPO_LEVEL_INVALID:
+ return CPUID_1F_ECX_TOPO_LEVEL_INVALID;
+ case CPU_TOPO_LEVEL_SMT:
+ return CPUID_1F_ECX_TOPO_LEVEL_SMT;
+ case CPU_TOPO_LEVEL_CORE:
+ return CPUID_1F_ECX_TOPO_LEVEL_CORE;
+ case CPU_TOPO_LEVEL_DIE:
+ return CPUID_1F_ECX_TOPO_LEVEL_DIE;
+ default:
+ /* Other types are not supported in QEMU. */
+ g_assert_not_reached();
+ }
+ return 0;
+}
+
+static void encode_topo_cpuid1f(CPUX86State *env, uint32_t count,
+ X86CPUTopoInfo *topo_info,
+ uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx)
+{
+ X86CPU *cpu = env_archcpu(env);
+ unsigned long level, next_level;
+ uint32_t num_threads_next_level, offset_next_level;
+
+ assert(count + 1 < CPU_TOPO_LEVEL_MAX);
+
+ /*
+ * Find the No.(count + 1) topology level in avail_cpu_topo bitmap.
+ * The search starts from bit 1 (CPU_TOPO_LEVEL_INVALID + 1).
+ */
+ level = CPU_TOPO_LEVEL_INVALID;
+ for (int i = 0; i <= count; i++) {
+ level = find_next_bit(env->avail_cpu_topo,
+ CPU_TOPO_LEVEL_PACKAGE,
+ level + 1);
+
+ /*
+ * CPUID[0x1f] doesn't explicitly encode the package level,
+ * and it just encodes the invalid level (all fields are 0)
+ * into the last subleaf of 0x1f.
+ */
+ if (level == CPU_TOPO_LEVEL_PACKAGE) {
+ level = CPU_TOPO_LEVEL_INVALID;
+ break;
+ }
+ }
+
+ if (level == CPU_TOPO_LEVEL_INVALID) {
+ num_threads_next_level = 0;
+ offset_next_level = 0;
+ } else {
+ next_level = find_next_bit(env->avail_cpu_topo,
+ CPU_TOPO_LEVEL_PACKAGE,
+ level + 1);
+ num_threads_next_level = num_threads_by_topo_level(topo_info,
+ next_level);
+ offset_next_level = apicid_offset_by_topo_level(topo_info,
+ next_level);
+ }
+
+ *eax = offset_next_level;
+ /* The count (bits 15-00) doesn't need to be reliable. */
+ *ebx = num_threads_next_level & 0xffff;
+ *ecx = (count & 0xff) | (cpuid1f_topo_type(level) << 8);
+ *edx = cpu->apic_id;
+
+ assert(!(*eax & ~0x1f));
+}
+
/* Encode cache info for CPUID[0x80000005].ECX or CPUID[0x80000005].EDX */
static uint32_t encode_cache_cpuid80000005(CPUCacheInfo *cache)
{
@@ -6447,31 +6556,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index,
uint32_t count,
break;
}
- *ecx = count & 0xff;
- *edx = cpu->apic_id;
- switch (count) {
- case 0:
- *eax = apicid_core_offset(&topo_info);
- *ebx = topo_info.threads_per_core;
- *ecx |= CPUID_1F_ECX_TOPO_LEVEL_SMT << 8;
- break;
- case 1:
- *eax = apicid_die_offset(&topo_info);
- *ebx = topo_info.cores_per_die * topo_info.threads_per_core;
- *ecx |= CPUID_1F_ECX_TOPO_LEVEL_CORE << 8;
- break;
- case 2:
- *eax = apicid_pkg_offset(&topo_info);
- *ebx = threads_per_pkg;
- *ecx |= CPUID_1F_ECX_TOPO_LEVEL_DIE << 8;
- break;
- default:
- *eax = 0;
- *ebx = 0;
- *ecx |= CPUID_1F_ECX_TOPO_LEVEL_INVALID << 8;
- }
- assert(!(*eax & ~0x1f));
- *ebx &= 0xffff; /* The count doesn't need to be reliable. */
+ encode_topo_cpuid1f(env, count, &topo_info, eax, ebx, ecx, edx);
break;
case 0xD: {
/* Processor Extended State */
--
2.45.1
- [PULL 05/23] target/i386: add control bits support for LAM, (continued)
- [PULL 05/23] target/i386: add control bits support for LAM, Paolo Bonzini, 2024/05/23
- [PULL 06/23] i386/cpu: Fix i/d-cache topology to core level for Intel CPU, Paolo Bonzini, 2024/05/23
- [PULL 07/23] i386/cpu: Use APIC ID info to encode cache topo in CPUID[4], Paolo Bonzini, 2024/05/23
- [PULL 08/23] i386/cpu: Use APIC ID info get NumSharingCache for CPUID[0x8000001D].EAX[bits 25:14], Paolo Bonzini, 2024/05/23
- [PULL 09/23] i386/cpu: Consolidate the use of topo_info in cpu_x86_cpuid(), Paolo Bonzini, 2024/05/23
- [PULL 10/23] i386/cpu: Introduce bitmap to cache available CPU topology levels, Paolo Bonzini, 2024/05/23
- [PULL 11/23] i386: Split topology types of CPUID[0x1F] from the definitions of CPUID[0xB], Paolo Bonzini, 2024/05/23
- [PULL 17/23] i386/cpu: Introduce module-id to X86CPU, Paolo Bonzini, 2024/05/23
- [PULL 14/23] i386: Support modules_per_die in X86CPUTopoInfo, Paolo Bonzini, 2024/05/23
- [PULL 16/23] i386: Support module_id in X86CPUTopoIDs, Paolo Bonzini, 2024/05/23
- [PULL 12/23] i386/cpu: Decouple CPUID[0x1F] subleaf with specific topology level,
Paolo Bonzini <=
- [PULL 13/23] i386: Introduce module level cpu topology to CPUX86State, Paolo Bonzini, 2024/05/23
- [PULL 18/23] tests: Add test case of APIC ID for module level parsing, Paolo Bonzini, 2024/05/23
- [PULL 15/23] i386: Expose module level in CPUID[0x1F], Paolo Bonzini, 2024/05/23
- [PULL 19/23] hw/i386/pc: Support smp.modules for x86 PC machine, Paolo Bonzini, 2024/05/23
- [PULL 21/23] i386/cpu: Use CPUCacheInfo.share_level to encode CPUID[4], Paolo Bonzini, 2024/05/23
- [PULL 20/23] i386: Add cache topology info in CPUCacheInfo, Paolo Bonzini, 2024/05/23
- [PULL 22/23] i386/cpu: Use CPUCacheInfo.share_level to encode CPUID[0x8000001D].EAX[bits 25:14], Paolo Bonzini, 2024/05/23
- [PULL 23/23] target-i386: hyper-v: Correct kvm_hv_handle_exit return value, Paolo Bonzini, 2024/05/23
- Re: [PULL 00/23] i386 changes for 2024-05-23, Richard Henderson, 2024/05/23