diff mbox series

target/i386: Add x-amd-ccx-size property

Message ID 20240521162347.9149-1-davydov-max@yandex-team.ru
State New
Headers show
Series target/i386: Add x-amd-ccx-size property | expand

Commit Message

Maksim Davydov May 21, 2024, 4:23 p.m. UTC
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(-)
diff mbox series

Patch

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index cfe7c92d6b..bbf8fb137c 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -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()
 };
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index ccccb62fc3..01104847a1 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -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;