1
linux/arch/x86/kernel/cpu/topology_amd.c

218 lines
6.0 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
#include <linux/cpu.h>
#include <asm/apic.h>
#include <asm/memtype.h>
#include <asm/processor.h>
#include "cpu.h"
static bool parse_8000_0008(struct topo_scan *tscan)
{
struct {
// ecx
u32 cpu_nthreads : 8, // Number of physical threads - 1
: 4, // Reserved
apicid_coreid_len : 4, // Number of thread core ID bits (shift) in APIC ID
perf_tsc_len : 2, // Performance time-stamp counter size
: 14; // Reserved
} ecx;
unsigned int sft;
if (tscan->c->extended_cpuid_level < 0x80000008)
return false;
cpuid_leaf_reg(0x80000008, CPUID_ECX, &ecx);
/* If the thread bits are 0, then get the shift value from ecx.cpu_nthreads */
sft = ecx.apicid_coreid_len;
if (!sft)
sft = get_count_order(ecx.cpu_nthreads + 1);
/*
* cpu_nthreads describes the number of threads in the package
* sft is the number of APIC ID bits per package
*
* As the number of actual threads per core is not described in
* this leaf, just set the CORE domain shift and let the later
* parsers set SMT shift. Assume one thread per core by default
* which is correct if there are no other CPUID leafs to parse.
*/
topology_update_dom(tscan, TOPO_SMT_DOMAIN, 0, 1);
topology_set_dom(tscan, TOPO_CORE_DOMAIN, sft, ecx.cpu_nthreads + 1);
return true;
}
static void store_node(struct topo_scan *tscan, u16 nr_nodes, u16 node_id)
{
/*
* Starting with Fam 17h the DIE domain could probably be used to
* retrieve the node info on AMD/HYGON. Analysis of CPUID dumps
* suggests it's the topmost bit(s) of the CPU cores area, but
* that's guess work and neither enumerated nor documented.
*
* Up to Fam 16h this does not work at all and the legacy node ID
* has to be used.
*/
tscan->amd_nodes_per_pkg = nr_nodes;
tscan->amd_node_id = node_id;
}
x86/cpu/topology: Add support for the AMD 0x80000026 leaf On AMD processors that support extended CPUID leaf 0x80000026, use the extended leaf to parse the topology information. In case of a failure, fall back to parsing the information from CPUID leaf 0xb. CPUID leaf 0x80000026 exposes the "CCX" and "CCD (Die)" information on AMD processors which have been mapped to TOPO_TILE_DOMAIN and TOPO_DIE_DOMAIN respectively. Since this information was previously not available via CPUID leaf 0xb or 0x8000001e, the "die_id", "logical_die_id", "max_die_per_pkg", "die_cpus", and "die_cpus_list" will differ with this addition on AMD processors that support extended CPUID leaf 0x80000026 and contain more than one "CCD (Die)" on the package. For example, following are the changes in the values reported by "/sys/kernel/debug/x86/topo/cpus/16" after applying this patch on a 4th Generation AMD EPYC System (1 x 128C/256T): (CPU16 is the first CPU of the second CCD on the package) tip:x86/apic tip:x86/apic + this patch online: 1 1 initial_apicid: 80 80 apicid: 80 80 pkg_id: 0 0 die_id: 0 4 * cu_id: 255 255 core_id: 64 64 logical_pkg_id: 0 0 logical_die_id: 0 4 * llc_id: 8 8 l2c_id: 65535 65535 amd_node_id: 0 0 amd_nodes_per_pkg: 1 1 num_threads: 256 256 num_cores: 128 128 max_dies_per_pkg: 1 8 * max_threads_per_core:2 2 [ prateek: commit log, updated comment in topoext_amd.c, changed has_0xb to has_topoext, rebased the changes on tip:x86/apic, tested the changes on 4th Gen AMD EPYC system ] [ mingo: tidy up the changelog a bit more ] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20240314050432.1710-1-kprateek.nayak@amd.com
2024-03-13 22:04:32 -07:00
static bool parse_8000_001e(struct topo_scan *tscan, bool has_topoext)
{
struct {
// eax
u32 ext_apic_id : 32; // Extended APIC ID
// ebx
u32 core_id : 8, // Unique per-socket logical core unit ID
core_nthreads : 8, // #Threads per core (zero-based)
: 16; // Reserved
// ecx
u32 node_id : 8, // Node (die) ID of invoking logical CPU
nnodes_per_socket : 3, // #nodes in invoking logical CPU's package/socket
: 21; // Reserved
// edx
u32 : 32; // Reserved
} leaf;
if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
return false;
cpuid_leaf(0x8000001e, &leaf);
tscan->c->topo.initial_apicid = leaf.ext_apic_id;
/*
* If leaf 0xb is available, then the domain shifts are set
* already and nothing to do here. Only valid for family >= 0x17.
*/
if (!has_topoext && tscan->c->x86 >= 0x17) {
/*
* Leaf 0x80000008 set the CORE domain shift already.
* Update the SMT domain, but do not propagate it.
*/
unsigned int nthreads = leaf.core_nthreads + 1;
topology_update_dom(tscan, TOPO_SMT_DOMAIN, get_count_order(nthreads), nthreads);
}
store_node(tscan, leaf.nnodes_per_socket + 1, leaf.node_id);
if (tscan->c->x86_vendor == X86_VENDOR_AMD) {
if (tscan->c->x86 == 0x15)
tscan->c->topo.cu_id = leaf.core_id;
cacheinfo_amd_init_llc_id(tscan->c, leaf.node_id);
} else {
/*
* Package ID is ApicId[6..] on certain Hygon CPUs. See
* commit e0ceeae708ce for explanation. The topology info
* is screwed up: The package shift is always 6 and the
* node ID is bit [4:5].
*/
if (!boot_cpu_has(X86_FEATURE_HYPERVISOR) && tscan->c->x86_model <= 0x3) {
topology_set_dom(tscan, TOPO_CORE_DOMAIN, 6,
tscan->dom_ncpus[TOPO_CORE_DOMAIN]);
}
cacheinfo_hygon_init_llc_id(tscan->c);
}
return true;
}
static void parse_fam10h_node_id(struct topo_scan *tscan)
{
union {
struct {
u64 node_id : 3,
nodes_per_pkg : 3,
unused : 58;
};
u64 msr;
} nid;
if (!boot_cpu_has(X86_FEATURE_NODEID_MSR))
return;
rdmsrl(MSR_FAM10H_NODE_ID, nid.msr);
store_node(tscan, nid.nodes_per_pkg + 1, nid.node_id);
tscan->c->topo.llc_id = nid.node_id;
}
static void legacy_set_llc(struct topo_scan *tscan)
{
unsigned int apicid = tscan->c->topo.initial_apicid;
/* If none of the parsers set LLC ID then use the die ID for it. */
if (tscan->c->topo.llc_id == BAD_APICID)
tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN];
}
static void topoext_fixup(struct topo_scan *tscan)
{
struct cpuinfo_x86 *c = tscan->c;
u64 msrval;
/* Try to re-enable TopologyExtensions if switched off by BIOS */
if (cpu_has(c, X86_FEATURE_TOPOEXT) || c->x86_vendor != X86_VENDOR_AMD ||
c->x86 != 0x15 || c->x86_model < 0x10 || c->x86_model > 0x6f)
return;
if (msr_set_bit(0xc0011005, 54) <= 0)
return;
rdmsrl(0xc0011005, msrval);
if (msrval & BIT_64(54)) {
set_cpu_cap(c, X86_FEATURE_TOPOEXT);
pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
}
}
static void parse_topology_amd(struct topo_scan *tscan)
{
x86/cpu/topology: Add support for the AMD 0x80000026 leaf On AMD processors that support extended CPUID leaf 0x80000026, use the extended leaf to parse the topology information. In case of a failure, fall back to parsing the information from CPUID leaf 0xb. CPUID leaf 0x80000026 exposes the "CCX" and "CCD (Die)" information on AMD processors which have been mapped to TOPO_TILE_DOMAIN and TOPO_DIE_DOMAIN respectively. Since this information was previously not available via CPUID leaf 0xb or 0x8000001e, the "die_id", "logical_die_id", "max_die_per_pkg", "die_cpus", and "die_cpus_list" will differ with this addition on AMD processors that support extended CPUID leaf 0x80000026 and contain more than one "CCD (Die)" on the package. For example, following are the changes in the values reported by "/sys/kernel/debug/x86/topo/cpus/16" after applying this patch on a 4th Generation AMD EPYC System (1 x 128C/256T): (CPU16 is the first CPU of the second CCD on the package) tip:x86/apic tip:x86/apic + this patch online: 1 1 initial_apicid: 80 80 apicid: 80 80 pkg_id: 0 0 die_id: 0 4 * cu_id: 255 255 core_id: 64 64 logical_pkg_id: 0 0 logical_die_id: 0 4 * llc_id: 8 8 l2c_id: 65535 65535 amd_node_id: 0 0 amd_nodes_per_pkg: 1 1 num_threads: 256 256 num_cores: 128 128 max_dies_per_pkg: 1 8 * max_threads_per_core:2 2 [ prateek: commit log, updated comment in topoext_amd.c, changed has_0xb to has_topoext, rebased the changes on tip:x86/apic, tested the changes on 4th Gen AMD EPYC system ] [ mingo: tidy up the changelog a bit more ] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20240314050432.1710-1-kprateek.nayak@amd.com
2024-03-13 22:04:32 -07:00
bool has_topoext = false;
/*
* If the extended topology leaf 0x8000_001e is available
x86/cpu/topology: Add support for the AMD 0x80000026 leaf On AMD processors that support extended CPUID leaf 0x80000026, use the extended leaf to parse the topology information. In case of a failure, fall back to parsing the information from CPUID leaf 0xb. CPUID leaf 0x80000026 exposes the "CCX" and "CCD (Die)" information on AMD processors which have been mapped to TOPO_TILE_DOMAIN and TOPO_DIE_DOMAIN respectively. Since this information was previously not available via CPUID leaf 0xb or 0x8000001e, the "die_id", "logical_die_id", "max_die_per_pkg", "die_cpus", and "die_cpus_list" will differ with this addition on AMD processors that support extended CPUID leaf 0x80000026 and contain more than one "CCD (Die)" on the package. For example, following are the changes in the values reported by "/sys/kernel/debug/x86/topo/cpus/16" after applying this patch on a 4th Generation AMD EPYC System (1 x 128C/256T): (CPU16 is the first CPU of the second CCD on the package) tip:x86/apic tip:x86/apic + this patch online: 1 1 initial_apicid: 80 80 apicid: 80 80 pkg_id: 0 0 die_id: 0 4 * cu_id: 255 255 core_id: 64 64 logical_pkg_id: 0 0 logical_die_id: 0 4 * llc_id: 8 8 l2c_id: 65535 65535 amd_node_id: 0 0 amd_nodes_per_pkg: 1 1 num_threads: 256 256 num_cores: 128 128 max_dies_per_pkg: 1 8 * max_threads_per_core:2 2 [ prateek: commit log, updated comment in topoext_amd.c, changed has_0xb to has_topoext, rebased the changes on tip:x86/apic, tested the changes on 4th Gen AMD EPYC system ] [ mingo: tidy up the changelog a bit more ] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20240314050432.1710-1-kprateek.nayak@amd.com
2024-03-13 22:04:32 -07:00
* try to get SMT, CORE, TILE, and DIE shifts from extended
* CPUID leaf 0x8000_0026 on supported processors first. If
* extended CPUID leaf 0x8000_0026 is not supported, try to
* get SMT and CORE shift from leaf 0xb first, then try to
* get the CORE shift from leaf 0x8000_0008.
*/
if (cpu_feature_enabled(X86_FEATURE_TOPOEXT))
x86/cpu/topology: Add support for the AMD 0x80000026 leaf On AMD processors that support extended CPUID leaf 0x80000026, use the extended leaf to parse the topology information. In case of a failure, fall back to parsing the information from CPUID leaf 0xb. CPUID leaf 0x80000026 exposes the "CCX" and "CCD (Die)" information on AMD processors which have been mapped to TOPO_TILE_DOMAIN and TOPO_DIE_DOMAIN respectively. Since this information was previously not available via CPUID leaf 0xb or 0x8000001e, the "die_id", "logical_die_id", "max_die_per_pkg", "die_cpus", and "die_cpus_list" will differ with this addition on AMD processors that support extended CPUID leaf 0x80000026 and contain more than one "CCD (Die)" on the package. For example, following are the changes in the values reported by "/sys/kernel/debug/x86/topo/cpus/16" after applying this patch on a 4th Generation AMD EPYC System (1 x 128C/256T): (CPU16 is the first CPU of the second CCD on the package) tip:x86/apic tip:x86/apic + this patch online: 1 1 initial_apicid: 80 80 apicid: 80 80 pkg_id: 0 0 die_id: 0 4 * cu_id: 255 255 core_id: 64 64 logical_pkg_id: 0 0 logical_die_id: 0 4 * llc_id: 8 8 l2c_id: 65535 65535 amd_node_id: 0 0 amd_nodes_per_pkg: 1 1 num_threads: 256 256 num_cores: 128 128 max_dies_per_pkg: 1 8 * max_threads_per_core:2 2 [ prateek: commit log, updated comment in topoext_amd.c, changed has_0xb to has_topoext, rebased the changes on tip:x86/apic, tested the changes on 4th Gen AMD EPYC system ] [ mingo: tidy up the changelog a bit more ] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20240314050432.1710-1-kprateek.nayak@amd.com
2024-03-13 22:04:32 -07:00
has_topoext = cpu_parse_topology_ext(tscan);
x86/cpu/topology: Add support for the AMD 0x80000026 leaf On AMD processors that support extended CPUID leaf 0x80000026, use the extended leaf to parse the topology information. In case of a failure, fall back to parsing the information from CPUID leaf 0xb. CPUID leaf 0x80000026 exposes the "CCX" and "CCD (Die)" information on AMD processors which have been mapped to TOPO_TILE_DOMAIN and TOPO_DIE_DOMAIN respectively. Since this information was previously not available via CPUID leaf 0xb or 0x8000001e, the "die_id", "logical_die_id", "max_die_per_pkg", "die_cpus", and "die_cpus_list" will differ with this addition on AMD processors that support extended CPUID leaf 0x80000026 and contain more than one "CCD (Die)" on the package. For example, following are the changes in the values reported by "/sys/kernel/debug/x86/topo/cpus/16" after applying this patch on a 4th Generation AMD EPYC System (1 x 128C/256T): (CPU16 is the first CPU of the second CCD on the package) tip:x86/apic tip:x86/apic + this patch online: 1 1 initial_apicid: 80 80 apicid: 80 80 pkg_id: 0 0 die_id: 0 4 * cu_id: 255 255 core_id: 64 64 logical_pkg_id: 0 0 logical_die_id: 0 4 * llc_id: 8 8 l2c_id: 65535 65535 amd_node_id: 0 0 amd_nodes_per_pkg: 1 1 num_threads: 256 256 num_cores: 128 128 max_dies_per_pkg: 1 8 * max_threads_per_core:2 2 [ prateek: commit log, updated comment in topoext_amd.c, changed has_0xb to has_topoext, rebased the changes on tip:x86/apic, tested the changes on 4th Gen AMD EPYC system ] [ mingo: tidy up the changelog a bit more ] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20240314050432.1710-1-kprateek.nayak@amd.com
2024-03-13 22:04:32 -07:00
if (!has_topoext && !parse_8000_0008(tscan))
return;
/* Prefer leaf 0x8000001e if available */
x86/cpu/topology: Add support for the AMD 0x80000026 leaf On AMD processors that support extended CPUID leaf 0x80000026, use the extended leaf to parse the topology information. In case of a failure, fall back to parsing the information from CPUID leaf 0xb. CPUID leaf 0x80000026 exposes the "CCX" and "CCD (Die)" information on AMD processors which have been mapped to TOPO_TILE_DOMAIN and TOPO_DIE_DOMAIN respectively. Since this information was previously not available via CPUID leaf 0xb or 0x8000001e, the "die_id", "logical_die_id", "max_die_per_pkg", "die_cpus", and "die_cpus_list" will differ with this addition on AMD processors that support extended CPUID leaf 0x80000026 and contain more than one "CCD (Die)" on the package. For example, following are the changes in the values reported by "/sys/kernel/debug/x86/topo/cpus/16" after applying this patch on a 4th Generation AMD EPYC System (1 x 128C/256T): (CPU16 is the first CPU of the second CCD on the package) tip:x86/apic tip:x86/apic + this patch online: 1 1 initial_apicid: 80 80 apicid: 80 80 pkg_id: 0 0 die_id: 0 4 * cu_id: 255 255 core_id: 64 64 logical_pkg_id: 0 0 logical_die_id: 0 4 * llc_id: 8 8 l2c_id: 65535 65535 amd_node_id: 0 0 amd_nodes_per_pkg: 1 1 num_threads: 256 256 num_cores: 128 128 max_dies_per_pkg: 1 8 * max_threads_per_core:2 2 [ prateek: commit log, updated comment in topoext_amd.c, changed has_0xb to has_topoext, rebased the changes on tip:x86/apic, tested the changes on 4th Gen AMD EPYC system ] [ mingo: tidy up the changelog a bit more ] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20240314050432.1710-1-kprateek.nayak@amd.com
2024-03-13 22:04:32 -07:00
if (parse_8000_001e(tscan, has_topoext))
return;
/* Try the NODEID MSR */
parse_fam10h_node_id(tscan);
}
void cpu_parse_topology_amd(struct topo_scan *tscan)
{
tscan->amd_nodes_per_pkg = 1;
topoext_fixup(tscan);
parse_topology_amd(tscan);
legacy_set_llc(tscan);
if (tscan->amd_nodes_per_pkg > 1)
set_cpu_cap(tscan->c, X86_FEATURE_AMD_DCM);
}
void cpu_topology_fixup_amd(struct topo_scan *tscan)
{
struct cpuinfo_x86 *c = tscan->c;
/*
* Adjust the core_id relative to the node when there is more than
* one node.
*/
if (tscan->c->x86 < 0x17 && tscan->amd_nodes_per_pkg > 1)
c->topo.core_id %= tscan->dom_ncpus[TOPO_CORE_DOMAIN] / tscan->amd_nodes_per_pkg;
}