On Mon, Jul 24, 2017 at 04:22:45AM -0500, Suravee Suthikulpanit wrote: > For family17h, current cpu_core_id is directly taken from the value > CPUID_Fn8000001E_EBX[7:0] (CoreId), which is the physical ID of the > core within a die. However, on system with downcore configuration > (where not all physical cores within a die are available), this could > result in the case where cpu_core_id > (cores_per_node - 1).
And that is a problem because...? > Fix up the cpu_core_id by breaking down the bitfields of CoreId, > and calculate relative ID using available topology information. > > Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpa...@amd.com> > --- > arch/x86/kernel/cpu/amd.c | 74 > ++++++++++++++++++++++++++++++++++------------- > 1 file changed, 54 insertions(+), 20 deletions(-) Btw, I have to say, it is much easier to review now. > diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c > index a2a52b5..b5ea28f 100644 > --- a/arch/x86/kernel/cpu/amd.c > +++ b/arch/x86/kernel/cpu/amd.c > @@ -305,37 +305,71 @@ static void __get_topoext(struct cpuinfo_x86 *c, int > cpu) > { > u32 eax, ebx, ecx, edx; > u8 node_id; > + u16 l3_nshared = 0; > + > + if (cpuid_edx(0x80000006)) { Ok, so Janakarajan did some L3 detection: https://lkml.kernel.org/r/cover.1497452002.git.janakarajan.natara...@amd.com and now that you need it too, I'd like you to refactor and unify that L3 detection code and put it in arch/x86/kernel/cpu/intel_cacheinfo.c (yes, we will rename that file one fine day :-)) along with accessors for other users to call. init_amd_cacheinfo() looks good to me right now. > + cpuid_count(0x8000001d, 3, &eax, &ebx, &ecx, &edx); > + l3_nshared = ((eax >> 14) & 0xfff) + 1; > + } > > cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); > > node_id = ecx & 0xff; > smp_num_siblings = ((ebx >> 8) & 0xff) + 1; > > - if (c->x86 == 0x15) > - c->cu_id = ebx & 0xff; > - > - if (c->x86 >= 0x17) { > - c->cpu_core_id = ebx & 0xff; > - > - if (smp_num_siblings > 1) > - c->x86_max_cores /= smp_num_siblings; > - } > + switch (c->x86) { > + case 0x17: { > + u32 tmp, ccx_offset, cpu_offset; > > - /* > - * We may have multiple LLCs if L3 caches exist, so check if we > - * have an L3 cache by looking at the L3 cache CPUID leaf. > - */ > - if (cpuid_edx(0x80000006)) { > - if (c->x86 == 0x17) { > + /* > + * In family 17h, the CPUID_Fn8000001E_EBX[7:0] (CoreId) > + * is non-contiguous in downcore and non-SMT cases. > + * Fixup the cpu_core_id to be contiguous for cores within > + * the die. Why do we need it to be contiguous? It is not contiguous on Intel too. > + */ > + tmp = ebx & 0xff; > + if (smp_num_siblings == 1) { > /* > - * LLC is at the core complex level. > - * Core complex id is ApicId[3]. > + * CoreId bit-encoding for SMT-disabled > + * [7:4] : die > + * [3] : ccx > + * [2:0] : core > */ > - per_cpu(cpu_llc_id, cpu) = c->apicid >> 3; > + ccx_offset = ((tmp >> 3) & 1) * l3_nshared; > + cpu_offset = tmp & 7; > } else { > - /* LLC is at the node level. */ > - per_cpu(cpu_llc_id, cpu) = node_id; > + /* > + * CoreId bit-encoding for SMT-enabled > + * [7:3] : die > + * [2] : ccx > + * [1:0] : core > + */ > + ccx_offset = ((tmp >> 2) & 1) * l3_nshared / > + smp_num_siblings; > + cpu_offset = tmp & 3; > + c->x86_max_cores /= smp_num_siblings; > + > } > + c->cpu_core_id = ccx_offset + cpu_offset; > + > + /* > + * Family17h L3 cache (LLC) is at Core Complex (CCX). > + * There could be multiple CCXs in a node. > + * CCX ID is ApicId[3]. > + */ > + per_cpu(cpu_llc_id, cpu) = c->apicid >> 3; > + > + pr_debug("Fixup coreid:%#x to cpu_core_id:%#x\n", > + tmp, c->cpu_core_id); > + break; > + } > + case 0x15: > + c->cu_id = ebx & 0xff; > + /* Follow through */ > + default: > + /* LLC is default to L3, which generally per-node */ > + if (l3_nshared > 0) > + per_cpu(cpu_llc_id, cpu) = node_id; If this needs to be executed unconditionally, just move it out of the switch-case. -- Regards/Gruss, Boris. SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg) --