@@ -328,10 +328,10 @@ static void encode_cache_cpuid80000006(CPUCacheInfo *l2,
/* Encode cache info for CPUID[8000001D] */
static void encode_cache_cpuid8000001d(CPUCacheInfo *cache,
X86CPUTopoInfo *topo_info,
+ uint32_t l3_threads,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
- uint32_t l3_threads;
assert(cache->size == cache->line_size * cache->associativity *
cache->partitions * cache->sets);
@@ -340,7 +340,8 @@ static void encode_cache_cpuid8000001d(CPUCacheInfo *cache,
/* L3 is shared among multiple cores */
if (cache->level == 3) {
- l3_threads = topo_info->cores_per_die * topo_info->threads_per_core;
+ l3_threads = (l3_threads ? l3_threads :
+ topo_info->cores_per_die * topo_info->threads_per_core);
*eax |= (l3_threads - 1) << 14;
} else {
*eax |= ((topo_info->threads_per_core - 1) << 14);
@@ -6757,19 +6758,23 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
switch (count) {
case 0: /* L1 dcache info */
encode_cache_cpuid8000001d(env->cache_info_amd.l1d_cache,
- &topo_info, eax, ebx, ecx, edx);
+ &topo_info, cpu->amd_ccx_size,
+ eax, ebx, ecx, edx);
break;
case 1: /* L1 icache info */
encode_cache_cpuid8000001d(env->cache_info_amd.l1i_cache,
- &topo_info, eax, ebx, ecx, edx);
+ &topo_info, cpu->amd_ccx_size,
+ eax, ebx, ecx, edx);
break;
case 2: /* L2 cache info */
encode_cache_cpuid8000001d(env->cache_info_amd.l2_cache,
- &topo_info, eax, ebx, ecx, edx);
+ &topo_info, cpu->amd_ccx_size,
+ eax, ebx, ecx, edx);
break;
case 3: /* L3 cache info */
encode_cache_cpuid8000001d(env->cache_info_amd.l3_cache,
- &topo_info, eax, ebx, ecx, edx);
+ &topo_info, cpu->amd_ccx_size,
+ eax, ebx, ecx, edx);
break;
default: /* end of info */
*eax = *ebx = *ecx = *edx = 0;
@@ -8105,6 +8110,8 @@ static Property x86_cpu_properties[] = {
false),
DEFINE_PROP_BOOL("x-intel-pt-auto-level", X86CPU, intel_pt_auto_level,
true),
+ DEFINE_PROP_UINT32("x-amd-ccx-size", X86CPU, amd_ccx_size, 0),
+
DEFINE_PROP_END_OF_LIST()
};
@@ -2036,6 +2036,9 @@ struct ArchCPU {
*/
uint32_t guest_phys_bits;
+ /* Number of logical processors that shares L3 cache */
+ uint32_t amd_ccx_size;
+
/* in order to simplify APIC support, we leave this pointer to the
user */
struct DeviceState *apic_state;
According to AMD64 Architecture Programmer's Manual volume 3, information about the cache topology is exposed by 0x8000001D CPUID leaf, and 0x8000001E CPUID leaf is exposing information about the topology of the entire processor. For example, CPUID on the real EPYC Milan 7713 shows: * 0x8000001D_EAX_3 = 0x0003c163 * 0x8000001E_ECX = 0x00000001 This means that 16 logical processors share one L3 cache, which gives 8 CCXs per processor, but only 1 node per processor. Thus, on real processor models, nodes and CCX are different things. What is more, Zen2, for example, has 2 CCX per die. It is also worth considering that for some desktop processors the number of cores is not a power of two, so the CCX size may vary within single family. Therefore, I suggest making it possible to set the CCX size as a property of the CPU. In this case, one will be able to set the CCX size if needed, but for others the default value will remain. Signed-off-by: Maksim Davydov <davydov-max@yandex-team.ru> --- target/i386/cpu.c | 19 +++++++++++++------ target/i386/cpu.h | 3 +++ 2 files changed, 16 insertions(+), 6 deletions(-)