aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQian Wen <qian.wen@intel.com>2025-07-14 16:08:58 +0800
committerPaolo Bonzini <pbonzini@redhat.com>2025-07-14 10:29:17 +0200
commit3e86124e7cb9b66e07fb992667865a308f16fcf2 (patch)
tree6f8d7599c15ca75daec4ee71fea21962301822b5
parenta62fef58299562aae6667b8d8552247423e886b3 (diff)
downloadqemu-3e86124e7cb9b66e07fb992667865a308f16fcf2.zip
qemu-3e86124e7cb9b66e07fb992667865a308f16fcf2.tar.gz
qemu-3e86124e7cb9b66e07fb992667865a308f16fcf2.tar.bz2
i386/cpu: Fix overflow of cache topology fields in CPUID.04H
According to SDM, CPUID.0x4:EAX[31:26] indicates the Maximum number of addressable IDs for processor cores in the physical package. If we launch over 64 cores VM, the 6-bit field will overflow, and the wrong core_id number will be reported. Since the HW reports 0x3f when the intel processor has over 64 cores, limit the max value written to EAX[31:26] to 63, so max num_cores should be 64. For EAX[14:25], though at present Q35 supports up to 4096 CPUs, by constructing a specific topology, the width of the APIC ID can be extended beyond 12 bits. For example, using `-smp threads=33,cores=9, modules=9` results in a die level offset of 6 + 4 + 4 = 14 bits, which can also cause overflow. check and honor the maximum value for EAX[14:25] as well. In addition, for host-cache-info case, also apply the same checks and fixes. Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com> Signed-off-by: Qian Wen <qian.wen@intel.com> Signed-off-by: Zhao Liu <zhao1.liu@intel.com> Link: https://lore.kernel.org/r/20250714080859.1960104-7-zhao1.liu@intel.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--target/i386/cpu.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 608fdcf..fdc6776 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -349,11 +349,17 @@ static void encode_cache_cpuid4(CPUCacheInfo *cache,
assert(cache->size == cache->line_size * cache->associativity *
cache->partitions * cache->sets);
+ /*
+ * The following fields have bit-width limitations, so consider the
+ * maximum values to avoid overflow:
+ * Bits 25-14: maximum 4095.
+ * Bits 31-26: maximum 63.
+ */
*eax = CACHE_TYPE(cache->type) |
CACHE_LEVEL(cache->level) |
(cache->self_init ? CACHE_SELF_INIT_LEVEL : 0) |
- (max_core_ids_in_package(topo_info) << 26) |
- (max_thread_ids_for_cache(topo_info, cache->share_level) << 14);
+ (MIN(max_core_ids_in_package(topo_info), 63) << 26) |
+ (MIN(max_thread_ids_for_cache(topo_info, cache->share_level), 4095) << 14);
assert(cache->line_size > 0);
assert(cache->partitions > 0);
@@ -7930,13 +7936,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
int host_vcpus_per_cache = 1 + ((*eax & 0x3FFC000) >> 14);
*eax &= ~0xFC000000;
- *eax |= max_core_ids_in_package(topo_info) << 26;
+ *eax |= MIN(max_core_ids_in_package(topo_info), 63) << 26;
if (host_vcpus_per_cache > threads_per_pkg) {
*eax &= ~0x3FFC000;
/* Share the cache at package level. */
- *eax |= max_thread_ids_for_cache(topo_info,
- CPU_TOPOLOGY_LEVEL_SOCKET) << 14;
+ *eax |= MIN(max_thread_ids_for_cache(topo_info,
+ CPU_TOPOLOGY_LEVEL_SOCKET), 4095) << 14;
}
}
} else if (cpu->vendor_cpuid_only && IS_AMD_CPU(env)) {