x86: adapt CPU topology detection for AMD Magny-Cours
Subsystems (2)
v2 cover x86: adapt CPU topology detection for AMD Magny-Cours
Hi,
Second attempt to fix CPU topology representation for multi-node processors.
Using topology information from /sys/devices/system/cpu/cpu*/topology you can identify
phys_package by physical_package_id
core by core_id + physical_package_id
Corresponding sibling information is
Level | Set of CPUs --------------|--------------- phys_package | core_siblings core | thread_siblings thread | one CPU
Example:
cpu19: physical_package_id : 1 cpu19: core_id : 7 cpu19: thread_siblings : 00080000 cpu19: thread_siblings_list : 19 cpu19: core_siblings : 00fff000 cpu19: core_siblings_list : 12-23
I am adding cpu_node_id, cpu_node_siblings, cpu_node_siblings_list to get the complete hierarchy. Now you can identify
phys_package by physical_package_id
cpu_node by physical_package_id + cpu_node_id
core by physical_package_id + cpu_node_id + core_id
In contrast to first patch set I don't change the meaning of core_siblings. Thus we have following sets of CPUs on a socket
Level | Set of CPUs --------------|--------------- phys_package | core_siblings cpu_node | cpu_node_siblings core | thread_siblings thread | one CPU
Example:
cpu19: physical_package_id : 1 cpu19: core_id : 1 cpu19: thread_siblings : 00080000 cpu19: thread_siblings_list : 19 cpu19: cpu_node_id : 0 cpu19: cpu_node_siblings : 00fc0000 cpu19: cpu_node_siblings_list : 18-23 cpu19: core_siblings : 00fff000 cpu19: core_siblings_list : 12-23
The cpu_node level information is stored in struct cpuinfo_x86.cpu_node_id and in cpu_node_map. It can be accessed using topology_cpu_node_id(cpu) and topology_cpu_node_cpumask(cpu).
Note:
A cpu_node is a functional unit. In case of AMD Magny-Cours it contains a number of cores, configuration registers, memory controler, ... A cpu_node is _not_ necessarily a NUMA node.
If you doubt this. Think of node interleaving where strictly speaking you have no NUMA but spread memory accesses across all nodes (depending on some bits of the memory address). The NUMA node topology is provided via ACPI tables (e.g. SRAT, SLIT). The contents of such tables might vary with different BIOS settings - the CPU topology is constant.
Patches are against tip/master.
Please apply.
Thanks,
Andreas
Signature · 5 lines
Operating | Advanced Micro Devices GmbH System | Karl-Hammerschmidt-Str. 34, 85609 Dornach b. München, Germany Research | Geschäftsführer: Thomas M. McCoy, Giuliano Meroni Center | Sitz: Dornach, Gemeinde Aschheim, Landkreis München (OSRC) | Registergericht München, HRB Nr. 43632
PATCH v2 1/3 x86: provide CPU topology information for multi-node processors
This support can be switched off/on using a new config option MULTI_NODE_CPU. If the option is set the CPU topology information is extended with cpu_node information. This includes a cpu_node_id, cpu_node_siblings and cpu_node_siblings_list.
--- arch/x86/Kconfig | 9 +++++++++ arch/x86/include/asm/processor.h | 4 ++++ arch/x86/include/asm/smp.h | 8 ++++++++ arch/x86/include/asm/topology.h | 5 +++++ arch/x86/kernel/cpu/common.c | 4 ++++ arch/x86/kernel/cpu/proc.c | 3 +++ arch/x86/kernel/smpboot.c | 14 ++++++++++++++ drivers/base/topology.c | 14 ++++++++++++++ 8 files changed, 61 insertions(+), 0 deletions(-)
arch/x86/Kconfig +9 -0
@@ -710,6 +710,15 @@ config SCHED_MC making when dealing with multi-core CPU chips at a cost of slightly increased overhead in some places. If unsure say N here. +config MULTI_NODE_CPU + def_bool y + prompt "Multi-node processor support" + depends on SMP + ---help--- + Multi-node processor support allows proper representation of + CPU topology for processors having multiple-nodes per socket. + If unsure say N here. + source "kernel/Kconfig.preempt" config X86_UP_APIC
arch/x86/include/asm/processor.h +4 -0
@@ -106,6 +106,10 @@ struct cpuinfo_x86 {u16 booted_cores;/* Physical processor id: */ u16 phys_proc_id; +#ifdef CONFIG_MULTI_NODE_CPU +/* Node id in case of multi-node processor: */ +u16 cpu_node_id; +#endif /* Core id: */ u16 cpu_core_id;/* Index into per_cpu list: */
arch/x86/include/asm/smp.h +8 -0
@@ -31,6 +31,14 @@ static inline struct cpumask *cpu_sibling_mask(int cpu)return per_cpu (cpu_sibling_map, cpu); } +#ifdef CONFIG_MULTI_NODE_CPU +DECLARE_PER_CPU (cpumask_var_t, cpu_node_map); +static inline struct cpumask *cpu_node_mask (int cpu) +{ +return per_cpu (cpu_node_map, cpu); +} +#endif +static inline struct cpumask *cpu_core_mask (int cpu) {return per_cpu (cpu_core_map, cpu);
arch/x86/include/asm/topology.h +5 -0
@@ -190,6 +190,11 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu);#define topology_core_id (cpu) (cpu_data(cpu).cpu_core_id)#define topology_core_cpumask (cpu) (per_cpu(cpu_core_map, cpu))#define topology_thread_cpumask (cpu) (per_cpu(cpu_sibling_map, cpu)) +#ifdef CONFIG_MULTI_NODE_CPU +#define topology_cpu_node_id (cpu) (cpu_data(cpu).cpu_node_id) +#define topology_cpu_node_cpumask (cpu) (per_cpu(cpu_node_map, cpu)) +#define arch_provides_multi_node_cpu_topology yes +#endif /* indicates that pointers to the topology cpumask_t maps are valid */ #define arch_provides_topology_pointers yes
arch/x86/kernel/cpu/common.c +4 -0
@@ -478,6 +478,10 @@ out:if ((c->x86_max_cores * smp_num_siblings) >1 ) {printk (KERN_INFO "CPU: Physical Processor ID: %d\n" , c->phys_proc_id); +#ifdef CONFIG_MULTI_NODE_CPU +printk (KERN_INFO "CPU: Processor Node ID: %d\n" , + c->cpu_node_id); +#endif printk (KERN_INFO "CPU: Processor Core ID: %d\n" , c->cpu_core_id); }
arch/x86/kernel/cpu/proc.c +3 -0
@@ -15,6 +15,9 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,seq_printf (m,"physical id\t: %d\n" , c->phys_proc_id);seq_printf (m,"siblings\t: %d\n" ,cpumask_weight (cpu_core_mask (cpu))); +#ifdef CONFIG_MULTI_NODE_CPU +seq_printf (m,"node id\t\t: %d\n" , c->cpu_node_id); +#endif seq_printf (m,"core id\t\t: %d\n" , c->cpu_core_id);seq_printf (m,"cpu cores\t: %d\n" , c->booted_cores);seq_printf (m,"apicid\t\t: %d\n" , c->apicid);
arch/x86/kernel/smpboot.c +14 -0
@@ -108,6 +108,10 @@ EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);DEFINE_PER_CPU (cpumask_var_t, cpu_core_map);EXPORT_PER_CPU_SYMBOL (cpu_core_map); +/* representing node silbings on multi-node CPU */ +DEFINE_PER_CPU (cpumask_var_t, cpu_node_map); +EXPORT_PER_CPU_SYMBOL (cpu_node_map); +/* Per CPU bogomips and other parameters */ DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);EXPORT_PER_CPU_SYMBOL (cpu_info);
@@ -401,6 +405,13 @@ void __cpuinit set_cpu_sibling_map(int cpu)cpumask_set_cpu (i, c->llc_shared_map);cpumask_set_cpu (cpu,cpu_data (i).llc_shared_map); } +#ifdef CONFIG_MULTI_NODE_CPU +if ((c->phys_proc_id ==cpu_data (i).phys_proc_id) && + (c->cpu_node_id ==cpu_data (i).cpu_node_id)) { +cpumask_set_cpu (i,cpu_node_mask (cpu)); +cpumask_set_cpu (cpu,cpu_node_mask (i)); + } +#endif if (c->phys_proc_id ==cpu_data (i).phys_proc_id) {cpumask_set_cpu (i,cpu_core_mask (cpu));cpumask_set_cpu (cpu,cpu_core_mask (i));
@@ -1220,6 +1231,9 @@ static void remove_siblinginfo(int cpu) c->phys_proc_id =0 ; c->cpu_core_id =0 ;cpumask_clear_cpu (cpu, cpu_sibling_setup_mask); +#ifdef CONFIG_MULTI_NODE_CPU + c->cpu_node_id =0 ; +#endif }static void __ref remove_cpu_from_maps (int cpu)
drivers/base/topology.c +14 -0
@@ -114,11 +114,25 @@ define_siblings_show_func(core_cpumask);define_one_ro_named (core_siblings, show_core_cpumask);define_one_ro_named (core_siblings_list, show_core_cpumask_list); +#ifdef arch_provides_multi_node_cpu_topology +define_id_show_func (cpu_node_id); +define_one_ro (cpu_node_id); +define_siblings_show_func (cpu_node_cpumask); +define_one_ro_named (cpu_node_siblings, show_cpu_node_cpumask); +define_one_ro_named (cpu_node_siblings_list, show_cpu_node_cpumask_list); +#endif + +static struct attribute *default_attrs[] = { &attr_physical_package_id.attr, &attr_core_id.attr, &attr_thread_siblings.attr, &attr_thread_siblings_list.attr, +#ifdef arch_provides_multi_node_cpu_topology + &attr_cpu_node_id.attr, + &attr_cpu_node_siblings.attr, + &attr_cpu_node_siblings_list.attr, +#endif &attr_core_siblings.attr, &attr_core_siblings_list.attr,NULL
Signature · 1 line
1.6.3.1
PATCH v2 2/3 x86: add topology detection for AMD multi-node processors
In reply to Andreas HerrmannThis adapts CPU topology detection for AMD Magny-Cours.
Here is example output from two cores on same package but different internal cpu_nodes:
/sys/devices/system/cpu/cpu5:
physical_package_id : 0 core_id : 5 thread_siblings : 00000020 thread_siblings_list : 5 cpu_node_id : 0 cpu_node_siblings : 0000003f cpu_node_siblings_list : 0-5 core_siblings : 00000fff core_siblings_list : 0-11 /sys/devices/system/cpu/cpu6: physical_package_id : 0 core_id : 0 thread_siblings : 00000040 thread_siblings_list : 6 cpu_node_id : 1 cpu_node_siblings : 00000fc0 cpu_node_siblings_list : 6-11 core_siblings : 00000fff core_siblings_list : 0-11
--- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/kernel/cpu/amd.c | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 0 deletions(-)
arch/x86/include/asm/cpufeature.h +1 -0
@@ -94,6 +94,7 @@#define X86_FEATURE_TSC_RELIABLE (3*32+23)/* TSC is known to be reliable */ #define X86_FEATURE_NONSTOP_TSC (3*32+24)/* TSC does not stop in C states */ #define X86_FEATURE_CLFLUSH_MONITOR (3*32+25)/* "" clflush reqd with monitor */ +#define X86_FEATURE_AMD_DCM (3*32+26)/* multi-node processor */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0)/* "pni" SSE-3 */
arch/x86/kernel/cpu/amd.c +63 -0
88 lines not on this page · raw message
Signature · 1 line
1.6.3.1
PATCH v2 3/3 x86: cacheinfo: fixup L3 cache information for AMD multi-node processors
In reply to Andreas HerrmannL3 cache size, associativity and shared_cpu information need to be adapted to show information for an internal node instead of the entire physical package.
--- arch/x86/kernel/cpu/intel_cacheinfo.c | 22 +++++++++++++++++----- 1 files changed, 17 insertions(+), 5 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +17 -5
@@ -241,7 +241,7 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,case 0 :if (!l1->val)return ; - assoc = l1->assoc; + assoc = assocs[l1->assoc]; line_size = l1->line_size; lines_per_tag = l1->lines_per_tag; size_in_kb = l1->size_in_kb;
@@ -249,7 +249,7 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,case 2 :if (!l2.val)return ; - assoc = l2.assoc; + assoc = assocs[l2.assoc]; line_size = l2.line_size; lines_per_tag = l2.lines_per_tag;/* cpu_data has errata corrections for K7 applied */
@@ -258,10 +258,14 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,case 3 :if (!l3.val)return ; - assoc = l3.assoc; + assoc = assocs[l3.assoc]; line_size = l3.line_size; lines_per_tag = l3.lines_per_tag; size_in_kb = l3.size_encoded *512 ; +if (boot_cpu_has (X86_FEATURE_AMD_DCM )) { + size_in_kb = size_in_kb >>1 ; + assoc = assoc >>1 ; + }break ;default :return ;
@@ -278,10 +282,10 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, eax->split.num_cores_on_die = current_cpu_data.x86_max_cores -1 ; -if (assoc ==0xf ) +if (assoc ==0xffff ) eax->split.is_fully_associative =1 ; ebx->split.coherency_line_size = line_size -1 ; - ebx->split.ways_of_associativity = assocs[assoc] -1 ; + ebx->split.ways_of_associativity = assoc -1 ; ebx->split.physical_line_partition = lines_per_tag -1 ; ecx->split.number_of_sets = (size_in_kb *1024 ) / line_size / (ebx->split.ways_of_associativity +1 ) -1 ;
@@ -598,7 +602,15 @@ static void __cpuinit get_cpu_leaves(void *_retval)cache_remove_shared_cpu_map (cpu, i);break ; } +#ifdef CONFIG_MULTI_NODE_CPU +if (boot_cpu_has (X86_FEATURE_AMD_DCM )) +cpumask_copy (to_cpumask (this_leaf->shared_cpu_map), +topology_cpu_node_cpumask (cpu)); +else +cache_shared_cpu_map_setup (cpu, j); +#else cache_shared_cpu_map_setup (cpu, j); +#endif } }
Signature · 1 line
1.6.3.1
Re: [PATCH 1/3] x86: provide CPU topology information for multi-node processors
In reply to Andreas HerrmannQuoted 4 lines · Andreas Herrmann
This support can be switched off/on using a new config option
MULTI_NODE_CPU. If the option is set the CPU topology information is extended withcpu_nodeinformation. This includes acpu_node_id,cpu_node_siblingsandcpu_node_siblings_list.
I think this would be a step back after commit c50cbb05a05cf1f9ca3592272eff053c847727d8. Which exported default topology information, in case the architecture does not provide these information.
Regards,
Bert
Quoted 2 lines
Signed-off-by Andreas Herrmann <[email protected]>
Re: [PATCH 1/3] x86: provide CPU topology information for multi-node processors
Quoted 11 lines · Bert Wesarg
Quoted 4 lines · Andreas Herrmann
This support can be switched off/on using a new config option
MULTI_NODE_CPU. If the option is set the CPU topology information is extended withcpu_nodeinformation. This includes acpu_node_id,cpu_node_siblingsandcpu_node_siblings_list.I think this would be a step back after commit
c50cbb05a05cf1f9ca3592272eff053c847727d8. Which exported default topology information, in case the architecture does not provide these information.
I am fine with exporting default topology information for all architectures.
I just wanted to avoid pollution of sysfs with useless information when this information is not provided on an architecture.
Further thoughts -- e.g. concerning the MULTI_NODE_CPU config option?
If I provide defaults for cpu_node_id, cpu_node_siblings etc. the config option becomes rather useless and I'll remove it.
Regards,
Andreas
Re: [PATCH 1/3] x86: provide CPU topology information for multi-node processors
Quoted 16 lines · Andreas Herrmann
Quoted 11 lines · Bert Wesarg
Quoted 4 lines · Andreas Herrmann
This support can be switched off/on using a new config option
MULTI_NODE_CPU. If the option is set the CPU topology information is extended withcpu_nodeinformation. This includes acpu_node_id,cpu_node_siblingsandcpu_node_siblings_list.I think this would be a step back after commit
c50cbb05a05cf1f9ca3592272eff053c847727d8. Which exported default topology information, in case the architecture does not provide these information.I am fine with exporting default topology information for all architectures.
Quoted 7 lines
I just wanted to avoid pollution of sysfs with useless information when this information is not provided on an architecture.
Further thoughts -- e.g. concerning the
MULTI_NODE_CPUconfig option?If I provide defaults for
cpu_node_id,cpu_node_siblingsetc. the config option becomes rather useless and I'll remove it.
Exactly ;-)
The interface to the exported API should not depend on config options. Only the kernel version number should indicate, whether the cpu_node information is available or not.
Thanks,
Bert
Quoted 7 lines
Regards,
Andreas