Commit c749ce39 authored by Thomas Gleixner's avatar Thomas Gleixner

x86/cpu: Use common topology code for AMD

Switch it over to the new topology evaluation mechanism and remove the
random bits and pieces which are sprinkled all over the place.

No functional change intended.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarJuergen Gross <jgross@suse.com>
Tested-by: default avatarSohil Mehta <sohil.mehta@intel.com>
Tested-by: default avatarMichael Kelley <mhklinux@outlook.com>
Tested-by: default avatarZhang Rui <rui.zhang@intel.com>
Tested-by: default avatarWang Wendy <wendy.wang@intel.com>
Tested-by: default avatarK Prateek Nayak <kprateek.nayak@amd.com>
Link: https://lore.kernel.org/r/20240212153625.145745053@linutronix.de
parent ace278e7
...@@ -707,12 +707,10 @@ static inline u32 per_cpu_l2c_id(unsigned int cpu) ...@@ -707,12 +707,10 @@ static inline u32 per_cpu_l2c_id(unsigned int cpu)
} }
#ifdef CONFIG_CPU_SUP_AMD #ifdef CONFIG_CPU_SUP_AMD
extern u32 amd_get_nodes_per_socket(void);
extern u32 amd_get_highest_perf(void); extern u32 amd_get_highest_perf(void);
extern void amd_clear_divider(void); extern void amd_clear_divider(void);
extern void amd_check_microcode(void); extern void amd_check_microcode(void);
#else #else
static inline u32 amd_get_nodes_per_socket(void) { return 0; }
static inline u32 amd_get_highest_perf(void) { return 0; } static inline u32 amd_get_highest_perf(void) { return 0; }
static inline void amd_clear_divider(void) { } static inline void amd_clear_divider(void) { }
static inline void amd_check_microcode(void) { } static inline void amd_check_microcode(void) { }
......
...@@ -27,13 +27,6 @@ ...@@ -27,13 +27,6 @@
#include "cpu.h" #include "cpu.h"
/*
* nodes_per_socket: Stores the number of nodes per socket.
* Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
* Node Identifiers[10:8]
*/
static u32 nodes_per_socket = 1;
static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
{ {
u32 gprs[8] = { 0 }; u32 gprs[8] = { 0 };
...@@ -300,97 +293,6 @@ static int nearby_node(int apicid) ...@@ -300,97 +293,6 @@ static int nearby_node(int apicid)
} }
#endif #endif
/*
* Fix up topo::core_id for pre-F17h systems to be in the
* [0 .. cores_per_node - 1] range. Not really needed but
* kept so as not to break existing setups.
*/
static void legacy_fixup_core_id(struct cpuinfo_x86 *c)
{
u32 cus_per_node;
if (c->x86 >= 0x17)
return;
cus_per_node = c->x86_max_cores / nodes_per_socket;
c->topo.core_id %= cus_per_node;
}
/*
* Fixup core topology information for
* (1) AMD multi-node processors
* Assumption: Number of cores in each internal node is the same.
* (2) AMD processors supporting compute units
*/
static void amd_get_topology(struct cpuinfo_x86 *c)
{
/* get information required for multi-node processors */
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
int err;
u32 eax, ebx, ecx, edx;
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
c->topo.die_id = ecx & 0xff;
if (c->x86 == 0x15)
c->topo.cu_id = ebx & 0xff;
if (c->x86 >= 0x17) {
c->topo.core_id = ebx & 0xff;
if (smp_num_siblings > 1)
c->x86_max_cores /= smp_num_siblings;
}
/*
* In case leaf B is available, use it to derive
* topology information.
*/
err = detect_extended_topology(c);
if (!err)
c->x86_coreid_bits = get_count_order(c->x86_max_cores);
cacheinfo_amd_init_llc_id(c, c->topo.die_id);
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;
rdmsrl(MSR_FAM10H_NODE_ID, value);
c->topo.die_id = value & 7;
c->topo.llc_id = c->topo.die_id;
} else
return;
if (nodes_per_socket > 1) {
set_cpu_cap(c, X86_FEATURE_AMD_DCM);
legacy_fixup_core_id(c);
}
}
/*
* On a AMD dual core setup the lower bits of the APIC id distinguish the cores.
* Assumes number of cores is a power of two.
*/
static void amd_detect_cmp(struct cpuinfo_x86 *c)
{
unsigned bits;
bits = c->x86_coreid_bits;
/* Low order bits define the core id (index of core in socket) */
c->topo.core_id = c->topo.initial_apicid & ((1 << bits)-1);
/* Convert the initial APIC ID into the socket ID */
c->topo.pkg_id = c->topo.initial_apicid >> bits;
/* use socket ID also for last level cache */
c->topo.llc_id = c->topo.die_id = c->topo.pkg_id;
}
u32 amd_get_nodes_per_socket(void)
{
return nodes_per_socket;
}
EXPORT_SYMBOL_GPL(amd_get_nodes_per_socket);
static void srat_detect_node(struct cpuinfo_x86 *c) static void srat_detect_node(struct cpuinfo_x86 *c)
{ {
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
...@@ -442,32 +344,6 @@ static void srat_detect_node(struct cpuinfo_x86 *c) ...@@ -442,32 +344,6 @@ static void srat_detect_node(struct cpuinfo_x86 *c)
#endif #endif
} }
static void early_init_amd_mc(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
unsigned bits, ecx;
/* Multi core CPU? */
if (c->extended_cpuid_level < 0x80000008)
return;
ecx = cpuid_ecx(0x80000008);
c->x86_max_cores = (ecx & 0xff) + 1;
/* CPU telling us the core id bits shift? */
bits = (ecx >> 12) & 0xF;
/* Otherwise recompute */
if (bits == 0) {
while ((1 << bits) < c->x86_max_cores)
bits++;
}
c->x86_coreid_bits = bits;
#endif
}
static void bsp_init_amd(struct cpuinfo_x86 *c) static void bsp_init_amd(struct cpuinfo_x86 *c)
{ {
if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
...@@ -500,18 +376,6 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) ...@@ -500,18 +376,6 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
if (cpu_has(c, X86_FEATURE_MWAITX)) if (cpu_has(c, X86_FEATURE_MWAITX))
use_mwaitx_delay(); use_mwaitx_delay();
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
u32 ecx;
ecx = cpuid_ecx(0x8000001e);
__max_die_per_package = nodes_per_socket = ((ecx >> 8) & 7) + 1;
} else if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) {
u64 value;
rdmsrl(MSR_FAM10H_NODE_ID, value);
__max_die_per_package = nodes_per_socket = ((value >> 3) & 7) + 1;
}
if (!boot_cpu_has(X86_FEATURE_AMD_SSBD) && if (!boot_cpu_has(X86_FEATURE_AMD_SSBD) &&
!boot_cpu_has(X86_FEATURE_VIRT_SSBD) && !boot_cpu_has(X86_FEATURE_VIRT_SSBD) &&
c->x86 >= 0x15 && c->x86 <= 0x17) { c->x86 >= 0x15 && c->x86 <= 0x17) {
...@@ -649,8 +513,6 @@ static void early_init_amd(struct cpuinfo_x86 *c) ...@@ -649,8 +513,6 @@ static void early_init_amd(struct cpuinfo_x86 *c)
u64 value; u64 value;
u32 dummy; u32 dummy;
early_init_amd_mc(c);
if (c->x86 >= 0xf) if (c->x86 >= 0xf)
set_cpu_cap(c, X86_FEATURE_K8); set_cpu_cap(c, X86_FEATURE_K8);
...@@ -730,9 +592,6 @@ static void early_init_amd(struct cpuinfo_x86 *c) ...@@ -730,9 +592,6 @@ static void early_init_amd(struct cpuinfo_x86 *c)
} }
} }
if (cpu_has(c, X86_FEATURE_TOPOEXT))
smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1;
if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) { if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) {
if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB)) if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB))
setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE); setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
...@@ -1076,9 +935,6 @@ static void init_amd(struct cpuinfo_x86 *c) ...@@ -1076,9 +935,6 @@ static void init_amd(struct cpuinfo_x86 *c)
if (cpu_has(c, X86_FEATURE_FSRM)) if (cpu_has(c, X86_FEATURE_FSRM))
set_cpu_cap(c, X86_FEATURE_FSRS); set_cpu_cap(c, X86_FEATURE_FSRS);
/* get apicid instead of initial apic id from cpuid */
c->topo.apicid = read_apic_id();
/* K6s reports MCEs but don't actually have all the MSRs */ /* K6s reports MCEs but don't actually have all the MSRs */
if (c->x86 < 6) if (c->x86 < 6)
clear_cpu_cap(c, X86_FEATURE_MCE); clear_cpu_cap(c, X86_FEATURE_MCE);
...@@ -1114,8 +970,6 @@ static void init_amd(struct cpuinfo_x86 *c) ...@@ -1114,8 +970,6 @@ static void init_amd(struct cpuinfo_x86 *c)
cpu_detect_cache_sizes(c); cpu_detect_cache_sizes(c);
amd_detect_cmp(c);
amd_get_topology(c);
srat_detect_node(c); srat_detect_node(c);
init_amd_cacheinfo(c); init_amd_cacheinfo(c);
......
...@@ -433,8 +433,7 @@ static u32 get_nbc_for_node(int node_id) ...@@ -433,8 +433,7 @@ static u32 get_nbc_for_node(int node_id)
struct cpuinfo_x86 *c = &boot_cpu_data; struct cpuinfo_x86 *c = &boot_cpu_data;
u32 cores_per_node; u32 cores_per_node;
cores_per_node = (c->x86_max_cores * smp_num_siblings) / amd_get_nodes_per_socket(); cores_per_node = (c->x86_max_cores * smp_num_siblings) / topology_amd_nodes_per_pkg();
return cores_per_node * node_id; return cores_per_node * node_id;
} }
......
...@@ -72,7 +72,6 @@ bool topo_is_converted(struct cpuinfo_x86 *c) ...@@ -72,7 +72,6 @@ bool topo_is_converted(struct cpuinfo_x86 *c)
{ {
/* Temporary until everything is converted over. */ /* Temporary until everything is converted over. */
switch (boot_cpu_data.x86_vendor) { switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
case X86_VENDOR_HYGON: case X86_VENDOR_HYGON:
return false; return false;
default: default:
...@@ -133,6 +132,10 @@ static void parse_topology(struct topo_scan *tscan, bool early) ...@@ -133,6 +132,10 @@ static void parse_topology(struct topo_scan *tscan, bool early)
tscan->ebx1_nproc_shift = get_count_order(ebx.nproc); tscan->ebx1_nproc_shift = get_count_order(ebx.nproc);
switch (c->x86_vendor) { switch (c->x86_vendor) {
case X86_VENDOR_AMD:
if (IS_ENABLED(CONFIG_CPU_SUP_AMD))
cpu_parse_topology_amd(tscan);
break;
case X86_VENDOR_CENTAUR: case X86_VENDOR_CENTAUR:
case X86_VENDOR_ZHAOXIN: case X86_VENDOR_ZHAOXIN:
parse_legacy(tscan); parse_legacy(tscan);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment