Skip to content

Commit 1822478

Browse files
wenqian77Michael Tokarev
authored andcommitted
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 <[email protected]> Signed-off-by: Qian Wen <[email protected]> Signed-off-by: Zhao Liu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Bonzini <[email protected]> (cherry picked from commit 3e86124e7cb9b66e07fb992667865a308f16fcf2) Signed-off-by: Michael Tokarev <[email protected]>
1 parent d097553 commit 1822478

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

target/i386/cpu.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,17 @@ static void encode_cache_cpuid4(CPUCacheInfo *cache,
283283
assert(cache->size == cache->line_size * cache->associativity *
284284
cache->partitions * cache->sets);
285285

286+
/*
287+
* The following fields have bit-width limitations, so consider the
288+
* maximum values to avoid overflow:
289+
* Bits 25-14: maximum 4095.
290+
* Bits 31-26: maximum 63.
291+
*/
286292
*eax = CACHE_TYPE(cache->type) |
287293
CACHE_LEVEL(cache->level) |
288294
(cache->self_init ? CACHE_SELF_INIT_LEVEL : 0) |
289-
(max_core_ids_in_package(topo_info) << 26) |
290-
(max_thread_ids_for_cache(topo_info, cache->share_level) << 14);
295+
(MIN(max_core_ids_in_package(topo_info), 63) << 26) |
296+
(MIN(max_thread_ids_for_cache(topo_info, cache->share_level), 4095) << 14);
291297

292298
assert(cache->line_size > 0);
293299
assert(cache->partitions > 0);
@@ -6867,13 +6873,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
68676873
int host_vcpus_per_cache = 1 + ((*eax & 0x3FFC000) >> 14);
68686874

68696875
*eax &= ~0xFC000000;
6870-
*eax |= max_core_ids_in_package(topo_info) << 26;
6876+
*eax |= MIN(max_core_ids_in_package(topo_info), 63) << 26;
68716877
if (host_vcpus_per_cache > threads_per_pkg) {
68726878
*eax &= ~0x3FFC000;
68736879

68746880
/* Share the cache at package level. */
6875-
*eax |= max_thread_ids_for_cache(topo_info,
6876-
CPU_TOPOLOGY_LEVEL_SOCKET) << 14;
6881+
*eax |= MIN(max_thread_ids_for_cache(topo_info,
6882+
CPU_TOPOLOGY_LEVEL_SOCKET), 4095) << 14;
68776883
}
68786884
}
68796885
} else if (cpu->vendor_cpuid_only && IS_AMD_CPU(env)) {

0 commit comments

Comments
 (0)