mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-22 21:06:53 +07:00
6c4f5abaf3
Current implementation does not communicate whether it can successfully detect CPUID function 0xB information. Therefore, modify the function to return success or error codes. This will be used by subsequent patches. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Borislav Petkov <bp@suse.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Borislav Petkov <bp@suse.de> Link: http://lkml.kernel.org/r/1524865681-112110-2-git-send-email-suravee.suthikulpanit@amd.com
101 lines
2.5 KiB
C
101 lines
2.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Check for extended topology enumeration cpuid leaf 0xb and if it
|
|
* exists, use it for populating initial_apicid and cpu topology
|
|
* detection.
|
|
*/
|
|
|
|
#include <linux/cpu.h>
|
|
#include <asm/apic.h>
|
|
#include <asm/pat.h>
|
|
#include <asm/processor.h>
|
|
|
|
/* leaf 0xb SMT level */
|
|
#define SMT_LEVEL 0
|
|
|
|
/* leaf 0xb sub-leaf types */
|
|
#define INVALID_TYPE 0
|
|
#define SMT_TYPE 1
|
|
#define CORE_TYPE 2
|
|
|
|
#define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff)
|
|
#define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f)
|
|
#define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff)
|
|
|
|
/*
|
|
* Check for extended topology enumeration cpuid leaf 0xb and if it
|
|
* exists, use it for populating initial_apicid and cpu topology
|
|
* detection.
|
|
*/
|
|
int detect_extended_topology(struct cpuinfo_x86 *c)
|
|
{
|
|
#ifdef CONFIG_SMP
|
|
unsigned int eax, ebx, ecx, edx, sub_index;
|
|
unsigned int ht_mask_width, core_plus_mask_width;
|
|
unsigned int core_select_mask, core_level_siblings;
|
|
static bool printed;
|
|
|
|
if (c->cpuid_level < 0xb)
|
|
return -1;
|
|
|
|
cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
|
|
|
|
/*
|
|
* check if the cpuid leaf 0xb is actually implemented.
|
|
*/
|
|
if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
|
|
return -1;
|
|
|
|
set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
|
|
|
|
/*
|
|
* initial apic id, which also represents 32-bit extended x2apic id.
|
|
*/
|
|
c->initial_apicid = edx;
|
|
|
|
/*
|
|
* Populate HT related information from sub-leaf level 0.
|
|
*/
|
|
core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
|
|
core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
|
|
|
|
sub_index = 1;
|
|
do {
|
|
cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx);
|
|
|
|
/*
|
|
* Check for the Core type in the implemented sub leaves.
|
|
*/
|
|
if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
|
|
core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
|
|
core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
|
|
break;
|
|
}
|
|
|
|
sub_index++;
|
|
} while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
|
|
|
|
core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
|
|
|
|
c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, ht_mask_width)
|
|
& core_select_mask;
|
|
c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, core_plus_mask_width);
|
|
/*
|
|
* Reinit the apicid, now that we have extended initial_apicid.
|
|
*/
|
|
c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
|
|
|
|
c->x86_max_cores = (core_level_siblings / smp_num_siblings);
|
|
|
|
if (!printed) {
|
|
pr_info("CPU: Physical Processor ID: %d\n",
|
|
c->phys_proc_id);
|
|
if (c->x86_max_cores > 1)
|
|
pr_info("CPU: Processor Core ID: %d\n",
|
|
c->cpu_core_id);
|
|
printed = 1;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|