On AMD and Hygon processors supporting X86_FEATURE_TOPOEXT set the l2c_id using the Extended APIC ID and the Cache Properties CPUID. Tested-by: Oleksandr Natalenko <oleksandr@xxxxxxxxxxxxxx> Signed-off-by: K Prateek Nayak <kprateek.nayak@xxxxxxx> --- o v1->v2 - No functional changes since v1 for AMD processors. - Renamed cacheinfo_amd_init_l2c_id() to cacheinfo_topoext_init_l2c_id() and added the call to same in Hygon's topology init path. - Collected tags from v1. --- arch/x86/include/asm/cacheinfo.h | 1 + arch/x86/kernel/cpu/amd.c | 1 + arch/x86/kernel/cpu/cacheinfo.c | 36 ++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/hygon.c | 1 + 4 files changed, 39 insertions(+) diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h index ce9685fc78d8..2034cd556c07 100644 --- a/arch/x86/include/asm/cacheinfo.h +++ b/arch/x86/include/asm/cacheinfo.h @@ -7,6 +7,7 @@ extern unsigned int memory_caching_control; #define CACHE_MTRR 0x01 #define CACHE_PAT 0x02 +void cacheinfo_topoext_init_l2c_id(struct cpuinfo_x86 *c, int cpu); void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu); void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu); diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index f769d6d08b43..500401b9e645 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -358,6 +358,7 @@ static void amd_get_topology(struct cpuinfo_x86 *c) if (!err) c->x86_coreid_bits = get_count_order(c->x86_max_cores); + cacheinfo_topoext_init_l2c_id(c, cpu); cacheinfo_amd_init_llc_id(c, cpu); } else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) { diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c index f4e5aa27eec6..bed7b9633451 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -659,6 +659,42 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c) return i; } +void cacheinfo_topoext_init_l2c_id(struct cpuinfo_x86 *c, int cpu) +{ + u32 eax, ebx, ecx, edx, num_sharing_cache; + int i = 0, bits; + + /* Check if L2 cache identifiers exists. */ + if (!cpuid_ecx(0x80000006)) + return; + + while (true) { + u32 level; + + cpuid_count(0x8000001d, i, &eax, &ebx, &ecx, &edx); + if (!eax) + return; + + /* + * Check if the current leaf is for L2 cache using + * eax[7:5] used to describe the cache level. + */ + level = (eax >> 5) & 0x7; + if (level == 2) + break; + + ++i; + } + + /* + * L2 ID is calculated from the number of threads + * sharing the L2 cache. + */ + num_sharing_cache = ((eax >> 14) & 0xfff) + 1; + bits = get_count_order(num_sharing_cache); + per_cpu(cpu_l2c_id, cpu) = c->apicid >> bits; +} + void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu) { /* diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c index 5a2962c492d3..cb0025b4a2fd 100644 --- a/arch/x86/kernel/cpu/hygon.c +++ b/arch/x86/kernel/cpu/hygon.c @@ -89,6 +89,7 @@ static void hygon_get_topology(struct cpuinfo_x86 *c) /* Socket ID is ApicId[6] for these processors. */ c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT; + cacheinfo_topoext_init_l2c_id(c, cpu); cacheinfo_hygon_init_llc_id(c, cpu); } else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) { u64 value; -- 2.34.1