]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/cacheinfo: Properly parse CPUID(0x80000006) L2/L3 associativity
authorAhmed S. Darwish <darwi@linutronix.de>
Wed, 9 Apr 2025 12:22:31 +0000 (14:22 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 9 Apr 2025 18:47:05 +0000 (20:47 +0200)
Complete the AMD CPUID(4) emulation logic, which uses CPUID(0x80000006)
for L2/L3 cache info and an assocs[] associativity mapping array, by
adding entries for 3-way caches and 6-way caches.

Properly handle the case where CPUID(0x80000006) returns an L2/L3
associativity of 9.  This is not real associativity, but a marker to
indicate that the respective L2/L3 cache information should be retrieved
from CPUID(0x8000001d) instead.  If such a marker is encountered, return
early from legacy_amd_cpuid4(), thus effectively emulating an "invalid
index" CPUID(4) response with a cache type of zero.

When checking if CPUID(0x80000006) L2/L3 cache info output is valid, and
given the associtivity marker 9 above, do not just check if the whole
ECX/EDX register is zero.  Rather, check if the associativity is zero or
9.  An associativity of zero implies no L2/L3 cache, which make it the
more correct check anyway vs. a zero check of the whole output register.

Fixes: a326e948c538 ("x86, cacheinfo: Fixup L3 cache information for AMD multi-node processors")
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: x86-cpuid@lists.linux.dev
Link: https://lore.kernel.org/r/20250409122233.1058601-3-darwi@linutronix.de
arch/x86/kernel/cpu/cacheinfo.c

index f4817cd50cfb3efb8f731d411e1231e9afd7b4ca..52727f8c0006a9d2cee5d4f1665e05d9b19a9c50 100644 (file)
@@ -89,9 +89,13 @@ static const enum cache_type cache_type_map[] = {
 /*
  * Fallback AMD CPUID(4) emulation
  * AMD CPUs with TOPOEXT can just use CPUID(0x8000001d)
+ *
+ * @AMD_L2_L3_INVALID_ASSOC: cache info for the respective L2/L3 cache should
+ * be determined from CPUID(0x8000001d) instead of CPUID(0x80000006).
  */
 
 #define AMD_CPUID4_FULLY_ASSOCIATIVE   0xffff
+#define AMD_L2_L3_INVALID_ASSOC                0x9
 
 union l1_cache {
        struct {
@@ -128,7 +132,9 @@ union l3_cache {
 static const unsigned short assocs[] = {
        [1]             = 1,
        [2]             = 2,
+       [3]             = 3,
        [4]             = 4,
+       [5]             = 6,
        [6]             = 8,
        [8]             = 16,
        [0xa]           = 32,
@@ -172,7 +178,7 @@ static void legacy_amd_cpuid4(int index, union _cpuid4_leaf_eax *eax,
                size_in_kb      = l1->size_in_kb;
                break;
        case 2:
-               if (!l2.val)
+               if (!l2.assoc || l2.assoc == AMD_L2_L3_INVALID_ASSOC)
                        return;
 
                /* Use x86_cache_size as it might have K7 errata fixes */
@@ -182,7 +188,7 @@ static void legacy_amd_cpuid4(int index, union _cpuid4_leaf_eax *eax,
                size_in_kb      = __this_cpu_read(cpu_info.x86_cache_size);
                break;
        case 3:
-               if (!l3.val)
+               if (!l3.assoc || l3.assoc == AMD_L2_L3_INVALID_ASSOC)
                        return;
 
                assoc           = assocs[l3.assoc];