x86/CPU/AMD: Save AMD NodeId as cpu_die_id
AMD systems provide a "NodeId" value that represents a global ID indicating to which "Node" a logical CPU belongs. The "Node" is a physical structure equivalent to a Die, and it should not be confused with logical structures like NUMA nodes. Logical nodes can be adjusted based on firmware or other settings whereas the physical nodes/dies are fixed based on hardware topology. The NodeId value can be used when a physical ID is needed by software. Save the AMD NodeId to struct cpuinfo_x86.cpu_die_id. Use the value from CPUID or MSR as appropriate. Default to phys_proc_id otherwise. Do so for both AMD and Hygon systems. Drop the node_id parameter from cacheinfo_*_init_llc_id() as it is no longer needed. Update the x86 topology documentation. Suggested-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20201109210659.754018-2-Yazen.Ghannam@amd.com
This commit is contained in:
parent
09162bc32c
commit
028c221ed1
@ -41,6 +41,8 @@ Package
|
|||||||
Packages contain a number of cores plus shared resources, e.g. DRAM
|
Packages contain a number of cores plus shared resources, e.g. DRAM
|
||||||
controller, shared caches etc.
|
controller, shared caches etc.
|
||||||
|
|
||||||
|
Modern systems may also use the term 'Die' for package.
|
||||||
|
|
||||||
AMD nomenclature for package is 'Node'.
|
AMD nomenclature for package is 'Node'.
|
||||||
|
|
||||||
Package-related topology information in the kernel:
|
Package-related topology information in the kernel:
|
||||||
@ -53,11 +55,18 @@ Package-related topology information in the kernel:
|
|||||||
|
|
||||||
The number of dies in a package. This information is retrieved via CPUID.
|
The number of dies in a package. This information is retrieved via CPUID.
|
||||||
|
|
||||||
|
- cpuinfo_x86.cpu_die_id:
|
||||||
|
|
||||||
|
The physical ID of the die. This information is retrieved via CPUID.
|
||||||
|
|
||||||
- cpuinfo_x86.phys_proc_id:
|
- cpuinfo_x86.phys_proc_id:
|
||||||
|
|
||||||
The physical ID of the package. This information is retrieved via CPUID
|
The physical ID of the package. This information is retrieved via CPUID
|
||||||
and deduced from the APIC IDs of the cores in the package.
|
and deduced from the APIC IDs of the cores in the package.
|
||||||
|
|
||||||
|
Modern systems use this value for the socket. There may be multiple
|
||||||
|
packages within a socket. This value may differ from cpu_die_id.
|
||||||
|
|
||||||
- cpuinfo_x86.logical_proc_id:
|
- cpuinfo_x86.logical_proc_id:
|
||||||
|
|
||||||
The logical ID of the package. As we do not trust BIOSes to enumerate the
|
The logical ID of the package. As we do not trust BIOSes to enumerate the
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#ifndef _ASM_X86_CACHEINFO_H
|
#ifndef _ASM_X86_CACHEINFO_H
|
||||||
#define _ASM_X86_CACHEINFO_H
|
#define _ASM_X86_CACHEINFO_H
|
||||||
|
|
||||||
void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id);
|
void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
|
||||||
void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id);
|
void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
|
||||||
|
|
||||||
#endif /* _ASM_X86_CACHEINFO_H */
|
#endif /* _ASM_X86_CACHEINFO_H */
|
||||||
|
@ -330,7 +330,6 @@ static void legacy_fixup_core_id(struct cpuinfo_x86 *c)
|
|||||||
*/
|
*/
|
||||||
static void amd_get_topology(struct cpuinfo_x86 *c)
|
static void amd_get_topology(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
u8 node_id;
|
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
/* get information required for multi-node processors */
|
/* get information required for multi-node processors */
|
||||||
@ -340,7 +339,7 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
|
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
node_id = ecx & 0xff;
|
c->cpu_die_id = ecx & 0xff;
|
||||||
|
|
||||||
if (c->x86 == 0x15)
|
if (c->x86 == 0x15)
|
||||||
c->cu_id = ebx & 0xff;
|
c->cu_id = ebx & 0xff;
|
||||||
@ -360,15 +359,15 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
|
|||||||
if (!err)
|
if (!err)
|
||||||
c->x86_coreid_bits = get_count_order(c->x86_max_cores);
|
c->x86_coreid_bits = get_count_order(c->x86_max_cores);
|
||||||
|
|
||||||
cacheinfo_amd_init_llc_id(c, cpu, node_id);
|
cacheinfo_amd_init_llc_id(c, cpu);
|
||||||
|
|
||||||
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
|
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
rdmsrl(MSR_FAM10H_NODE_ID, value);
|
rdmsrl(MSR_FAM10H_NODE_ID, value);
|
||||||
node_id = value & 7;
|
c->cpu_die_id = value & 7;
|
||||||
|
|
||||||
per_cpu(cpu_llc_id, cpu) = node_id;
|
per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -393,7 +392,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
|
|||||||
/* Convert the initial APIC ID into the socket ID */
|
/* Convert the initial APIC ID into the socket ID */
|
||||||
c->phys_proc_id = c->initial_apicid >> bits;
|
c->phys_proc_id = c->initial_apicid >> bits;
|
||||||
/* use socket ID also for last level cache */
|
/* use socket ID also for last level cache */
|
||||||
per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
|
per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amd_detect_ppin(struct cpuinfo_x86 *c)
|
static void amd_detect_ppin(struct cpuinfo_x86 *c)
|
||||||
|
@ -646,7 +646,7 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
|
void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We may have multiple LLCs if L3 caches exist, so check if we
|
* We may have multiple LLCs if L3 caches exist, so check if we
|
||||||
@ -657,7 +657,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
|
|||||||
|
|
||||||
if (c->x86 < 0x17) {
|
if (c->x86 < 0x17) {
|
||||||
/* LLC is at the node level. */
|
/* LLC is at the node level. */
|
||||||
per_cpu(cpu_llc_id, cpu) = node_id;
|
per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
|
||||||
} else if (c->x86 == 0x17 && c->x86_model <= 0x1F) {
|
} else if (c->x86 == 0x17 && c->x86_model <= 0x1F) {
|
||||||
/*
|
/*
|
||||||
* LLC is at the core complex level.
|
* LLC is at the core complex level.
|
||||||
@ -684,7 +684,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
|
void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We may have multiple LLCs if L3 caches exist, so check if we
|
* We may have multiple LLCs if L3 caches exist, so check if we
|
||||||
|
@ -65,7 +65,6 @@ static void hygon_get_topology_early(struct cpuinfo_x86 *c)
|
|||||||
*/
|
*/
|
||||||
static void hygon_get_topology(struct cpuinfo_x86 *c)
|
static void hygon_get_topology(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
u8 node_id;
|
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
/* get information required for multi-node processors */
|
/* get information required for multi-node processors */
|
||||||
@ -75,7 +74,7 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
|
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
node_id = ecx & 0xff;
|
c->cpu_die_id = ecx & 0xff;
|
||||||
|
|
||||||
c->cpu_core_id = ebx & 0xff;
|
c->cpu_core_id = ebx & 0xff;
|
||||||
|
|
||||||
@ -93,14 +92,14 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
|
|||||||
/* Socket ID is ApicId[6] for these processors. */
|
/* Socket ID is ApicId[6] for these processors. */
|
||||||
c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
|
c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
|
||||||
|
|
||||||
cacheinfo_hygon_init_llc_id(c, cpu, node_id);
|
cacheinfo_hygon_init_llc_id(c, cpu);
|
||||||
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
|
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
rdmsrl(MSR_FAM10H_NODE_ID, value);
|
rdmsrl(MSR_FAM10H_NODE_ID, value);
|
||||||
node_id = value & 7;
|
c->cpu_die_id = value & 7;
|
||||||
|
|
||||||
per_cpu(cpu_llc_id, cpu) = node_id;
|
per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -123,7 +122,7 @@ static void hygon_detect_cmp(struct cpuinfo_x86 *c)
|
|||||||
/* Convert the initial APIC ID into the socket ID */
|
/* Convert the initial APIC ID into the socket ID */
|
||||||
c->phys_proc_id = c->initial_apicid >> bits;
|
c->phys_proc_id = c->initial_apicid >> bits;
|
||||||
/* use socket ID also for last level cache */
|
/* use socket ID also for last level cache */
|
||||||
per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
|
per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void srat_detect_node(struct cpuinfo_x86 *c)
|
static void srat_detect_node(struct cpuinfo_x86 *c)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user