x86, cacheinfo: Use AMD topology extensions
cover x86, cacheinfo: Use AMD topology extensions
Hi,
Following patches modify cachinfo code to make use of AMD's topology extension CPUID functions. Thus (hopefully) we can avoid CPU specific modifications whenever cache topology changes.
Please apply.
Thanks,
Andreas
PATCH 1/4 x86: Add cpu_has_topoext
Introduce cpu_has_topoext to check for AMD's CPUID topology extensions support. It indicates support for
CPUID Fn8000_001D_EAX_x[N:0]-CPUID Fn8000_001E_EDX
See AMD's CPUID Specification, Publication # 25481 (as of Rev. 2.34 September 2010)
--- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/kernel/cpu/amd.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/cpufeature.h +1 -0
@@ -309,6 +309,7 @@ extern const char * const x86_power_flags[32];#define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8)#define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16)#define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU) +#define cpu_has_topoext boot_cpu_has(X86_FEATURE_TOPOEXT)#if defined(CONFIG_X86_INVLPG ) || defined(CONFIG_X86_64 )# define cpu_has_invlpg 1
arch/x86/kernel/cpu/amd.c +1 -1
@@ -304,7 +304,7 @@ static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)int cpu =smp_processor_id ();/* get information required for multi-node processors */ -if (cpu_has (c,X86_FEATURE_TOPOEXT )) { +if (cpu_has_topoext) {u32 eax, ebx, ecx, edx;cpuid (0x8000001e , &eax, &ebx, &ecx, &edx);
arch/x86/kernel/smpboot.c +1 -1
@@ -313,7 +313,7 @@ do { \static bool __cpuinit match_smt (struct cpuinfo_x86 *c,struct cpuinfo_x86 *o) { -if (cpu_has (c,X86_FEATURE_TOPOEXT )) { +if (cpu_has_topoext) {int cpu1 = c->cpu_index, cpu2 = o->cpu_index; if (c->phys_proc_id == o->phys_proc_id &&
Signature · 1 line
1.7.8.6
[tip:x86/cpu] x86: Add cpu_has_topoext
Commit-ID: 193f3fcb3ab769bab4a2b9fa181eef3e5699a352 Gitweb: http://git.kernel.org/tip/193f3fcb3ab769bab4a2b9fa181eef3e5699a352 Author: Andreas Herrmann <[email protected]> AuthorDate: Fri, 19 Oct 2012 10:58:13 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 13 Nov 2012 11:22:28 -0800
x86: Add cpu_has_topoext
Introduce cpu_has_topoext to check for AMD's CPUID topology extensions support. It indicates support for
CPUID Fn8000_001D_EAX_x[N:0]-CPUID Fn8000_001E_EDX
See AMD's CPUID Specification, Publication # 25481 (as of Rev. 2.34 September 2010)
--- arch/x86/include/asm/cpufeature.h | 1 + arch/x86/kernel/cpu/amd.c | 2 +- arch/x86/kernel/smpboot.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/cpufeature.h +1 -0
@@ -311,6 +311,7 @@ extern const char * const x86_power_flags[32];#define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8)#define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16)#define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU) +#define cpu_has_topoext boot_cpu_has(X86_FEATURE_TOPOEXT)#if defined(CONFIG_X86_INVLPG ) || defined(CONFIG_X86_64 )# define cpu_has_invlpg 1
arch/x86/kernel/cpu/amd.c +1 -1
@@ -304,7 +304,7 @@ static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)int cpu =smp_processor_id ();/* get information required for multi-node processors */ -if (cpu_has (c,X86_FEATURE_TOPOEXT )) { +if (cpu_has_topoext) {u32 eax, ebx, ecx, edx;cpuid (0x8000001e , &eax, &ebx, &ecx, &edx);
arch/x86/kernel/smpboot.c +1 -1
@@ -313,7 +313,7 @@ do { \static bool __cpuinit match_smt (struct cpuinfo_x86 *c,struct cpuinfo_x86 *o) { -if (cpu_has (c,X86_FEATURE_TOPOEXT )) { +if (cpu_has_topoext) {int cpu1 = c->cpu_index, cpu2 = o->cpu_index; if (c->phys_proc_id == o->phys_proc_id &&
PATCH 2/4 x86, cacheinfo: Determine number of cache leafs using CPUID 0x8000001d on AMD
In reply to Andreas HerrmannCPUID 0x8000001d works quite similar to Intels' CPUID function 4. Use it to determine number of cache leafs.
--- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/cpu/amd.c | 7 +------ arch/x86/kernel/cpu/intel_cacheinfo.c | 28 +++++++++++++++++++++++----- 3 files changed, 25 insertions(+), 12 deletions(-)
arch/x86/include/asm/processor.h +1 -1
@@ -187,7 +187,7 @@ extern void print_cpu_info(struct cpuinfo_x86 *);void print_cpu_msr (struct cpuinfo_x86 *);extern void init_scattered_cpuid_features (struct cpuinfo_x86 *c);extern unsigned int init_intel_cacheinfo (struct cpuinfo_x86 *c); -extern unsigned short num_cache_leaves; +extern void init_amd_cacheinfo (struct cpuinfo_x86 *c);extern void detect_extended_topology (struct cpuinfo_x86 *c);extern void detect_ht (struct cpuinfo_x86 *c);
arch/x86/kernel/cpu/amd.c +1 -6
@@ -643,12 +643,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)detect_ht (c);#endif -if (c->extended_cpuid_level >=0x80000006 ) { -if (cpuid_edx (0x80000006 ) &0xf000 ) - num_cache_leaves =4 ; -else - num_cache_leaves =3 ; - } +init_amd_cacheinfo (c);if (c->x86 >=0xf )set_cpu_cap (c,X86_FEATURE_K8 );
arch/x86/kernel/cpu/intel_cacheinfo.c +23 -5
@@ -557,21 +557,39 @@ __cpuinit cpuid4_cache_lookup_regs(int index,return 0 ; } -static int __cpuinit find_num_cache_leaves (void ) +static int __cpuinit find_num_cache_leaves (struct cpuinfo_x86 *c) { -unsigned int eax, ebx, ecx, edx; +unsigned int eax, ebx, ecx, edx, op;union _cpuid4_leaf_eax cache_eax;int i =-1 ; +if (c->x86_vendor ==X86_VENDOR_AMD ) + op =0x8000001d ; +else + op =4 ; +do { ++i; -/* Do cpuid(4) loop to find out num_cache_leaves */ -cpuid_count (4 , i, &eax, &ebx, &ecx, &edx); +/* Do cpuid(op) loop to find out num_cache_leaves */ +cpuid_count (op, i, &eax, &ebx, &ecx, &edx); cache_eax.full = eax; }while (cache_eax.split.type !=CACHE_TYPE_NULL );return i; } +void __cpuinit init_amd_cacheinfo (struct cpuinfo_x86 *c) +{ + +if (cpu_has_topoext) { + num_cache_leaves =find_num_cache_leaves (c); + }else if (c->extended_cpuid_level >=0x80000006 ) { +if (cpuid_edx (0x80000006 ) &0xf000 ) + num_cache_leaves =4 ; +else + num_cache_leaves =3 ; + } +} +unsigned int __cpuinit init_intel_cacheinfo (struct cpuinfo_x86 *c) {/* Cache sizes */
@@ -588,7 +606,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)if (is_initialized ==0 ) {/* Init num_cache_leaves from boot CPU */ - num_cache_leaves =find_num_cache_leaves (); + num_cache_leaves =find_num_cache_leaves (c); is_initialized++; }
Signature · 1 line
1.7.8.6
[tip:x86/cpu] x86, cacheinfo: Determine number of cache leafs using CPUID 0x8000001d on AMD
Commit-ID: 04a1541828ea223169eb44a336bfad8ec0dfb46a Gitweb: http://git.kernel.org/tip/04a1541828ea223169eb44a336bfad8ec0dfb46a Author: Andreas Herrmann <[email protected]> AuthorDate: Fri, 19 Oct 2012 10:59:33 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 13 Nov 2012 11:22:29 -0800
x86, cacheinfo: Determine number of cache leafs using CPUID 0x8000001d on AMD
CPUID 0x8000001d works quite similar to Intels' CPUID function 4. Use it to determine number of cache leafs.
--- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/cpu/amd.c | 7 +------ arch/x86/kernel/cpu/intel_cacheinfo.c | 28 +++++++++++++++++++++++----- 3 files changed, 25 insertions(+), 12 deletions(-)
arch/x86/include/asm/processor.h +1 -1
@@ -187,7 +187,7 @@ extern void print_cpu_info(struct cpuinfo_x86 *);void print_cpu_msr (struct cpuinfo_x86 *);extern void init_scattered_cpuid_features (struct cpuinfo_x86 *c);extern unsigned int init_intel_cacheinfo (struct cpuinfo_x86 *c); -extern unsigned short num_cache_leaves; +extern void init_amd_cacheinfo (struct cpuinfo_x86 *c);extern void detect_extended_topology (struct cpuinfo_x86 *c);extern void detect_ht (struct cpuinfo_x86 *c);
arch/x86/kernel/cpu/amd.c +1 -6
@@ -643,12 +643,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)detect_ht (c);#endif -if (c->extended_cpuid_level >=0x80000006 ) { -if (cpuid_edx (0x80000006 ) &0xf000 ) - num_cache_leaves =4 ; -else - num_cache_leaves =3 ; - } +init_amd_cacheinfo (c);if (c->x86 >=0xf )set_cpu_cap (c,X86_FEATURE_K8 );
arch/x86/kernel/cpu/intel_cacheinfo.c +23 -5
@@ -557,21 +557,39 @@ __cpuinit cpuid4_cache_lookup_regs(int index,return 0 ; } -static int __cpuinit find_num_cache_leaves (void ) +static int __cpuinit find_num_cache_leaves (struct cpuinfo_x86 *c) { -unsigned int eax, ebx, ecx, edx; +unsigned int eax, ebx, ecx, edx, op;union _cpuid4_leaf_eax cache_eax;int i =-1 ; +if (c->x86_vendor ==X86_VENDOR_AMD ) + op =0x8000001d ; +else + op =4 ; +do { ++i; -/* Do cpuid(4) loop to find out num_cache_leaves */ -cpuid_count (4 , i, &eax, &ebx, &ecx, &edx); +/* Do cpuid(op) loop to find out num_cache_leaves */ +cpuid_count (op, i, &eax, &ebx, &ecx, &edx); cache_eax.full = eax; }while (cache_eax.split.type !=CACHE_TYPE_NULL );return i; } +void __cpuinit init_amd_cacheinfo (struct cpuinfo_x86 *c) +{ + +if (cpu_has_topoext) { + num_cache_leaves =find_num_cache_leaves (c); + }else if (c->extended_cpuid_level >=0x80000006 ) { +if (cpuid_edx (0x80000006 ) &0xf000 ) + num_cache_leaves =4 ; +else + num_cache_leaves =3 ; + } +} +unsigned int __cpuinit init_intel_cacheinfo (struct cpuinfo_x86 *c) {/* Cache sizes */
@@ -588,7 +606,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)if (is_initialized ==0 ) {/* Init num_cache_leaves from boot CPU */ - num_cache_leaves =find_num_cache_leaves (); + num_cache_leaves =find_num_cache_leaves (c); is_initialized++; }
PATCH 3/4 x86, cacheinfo: Make use of CPUID 0x8000001d for cache information on AMD
In reply to Andreas HerrmannRely on CPUID 0x8000001d for cache information when AMD CPUID topology extensions are available.
--- arch/x86/kernel/cpu/intel_cacheinfo.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +5 -1
@@ -538,7 +538,11 @@ __cpuinit cpuid4_cache_lookup_regs(int index,unsigned edx;if (boot_cpu_data.x86_vendor ==X86_VENDOR_AMD ) { -amd_cpuid4 (index, &eax, &ebx, &ecx); +if (cpu_has_topoext) +cpuid_count (0x8000001d , index, &eax.full, + &ebx.full, &ecx.full, &edx); +else +amd_cpuid4 (index, &eax, &ebx, &ecx);amd_init_l3_cache (this_leaf, index); }else {cpuid_count (4 , index, &eax.full, &ebx.full, &ecx.full, &edx);
Signature · 1 line
1.7.8.6
[tip:x86/cpu] x86, cacheinfo: Make use of CPUID 0x8000001d for cache information on AMD
Commit-ID: 2e8458dfe4202df75543402c7343b8f94de4101e Gitweb: http://git.kernel.org/tip/2e8458dfe4202df75543402c7343b8f94de4101e Author: Andreas Herrmann <[email protected]> AuthorDate: Fri, 19 Oct 2012 11:00:49 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 13 Nov 2012 11:22:30 -0800
x86, cacheinfo: Make use of CPUID 0x8000001d for cache information on AMD
Rely on CPUID 0x8000001d for cache information when AMD CPUID topology extensions are available.
--- arch/x86/kernel/cpu/intel_cacheinfo.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +5 -1
@@ -538,7 +538,11 @@ __cpuinit cpuid4_cache_lookup_regs(int index,unsigned edx;if (boot_cpu_data.x86_vendor ==X86_VENDOR_AMD ) { -amd_cpuid4 (index, &eax, &ebx, &ecx); +if (cpu_has_topoext) +cpuid_count (0x8000001d , index, &eax.full, + &ebx.full, &ecx.full, &edx); +else +amd_cpuid4 (index, &eax, &ebx, &ecx);amd_init_l3_cache (this_leaf, index); }else {cpuid_count (4 , index, &eax.full, &ebx.full, &ecx.full, &edx);
PATCH 4/4 x86, cacheinfo: Base cache sharing info on CPUID 0x8000001d on AMD
In reply to Andreas HerrmannThe patch is based on a patch submitted by Hans Rosenfeld. See http://marc.info/?l=linux-kernel&m=133908777200931
Note that CPUID Fn8000_001D_EAX slightly differs to Intel's CPUID function 4.
Bits 14-25 contain NumSharingCache. Actual number of cores sharing
this cache. SW to add value of one to get result.
The corresponding bits on Intel are defined as "maximum number of threads sharing this cache" (with a "plus 1" encoding).
Thus a different method to determine which cores are sharing a cache level has to be used.
--- arch/x86/kernel/cpu/intel_cacheinfo.c | 41 +++++++++++++++++++++----------- 1 files changed, 27 insertions(+), 14 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +27 -14
@@ -750,37 +750,50 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);static int __cpuinit cache_shared_amd_cpu_map_setup (unsigned int cpu,int index) {struct _cpuid4_info *this_leaf; -int ret, i, sibling; -struct cpuinfo_x86 *c = &cpu_data (cpu); +int i, sibling; - ret =0 ; -if (index ==3 ) { - ret =1 ; -for_each_cpu (i,cpu_llc_shared_mask (cpu)) { +if (cpu_has_topoext) { +unsigned int apicid, nshared, first, last; + +if (!per_cpu (ici_cpuid4_info, cpu)) +return 0 ; + + this_leaf =CPUID4_INFO_IDX (cpu, index); + nshared = this_leaf->base.eax.split.num_threads_sharing +1 ; + apicid =cpu_data (cpu).apicid; + first = apicid - (apicid % nshared); + last = first + nshared -1 ; + +for_each_online_cpu (i) { + apicid =cpu_data (i).apicid; +if ((apicid < first) || (apicid > last)) +continue ;if (!per_cpu (ici_cpuid4_info, i))continue ; this_leaf =CPUID4_INFO_IDX (i, index); -for_each_cpu (sibling,cpu_llc_shared_mask (cpu)) { -if (!cpu_online (sibling)) + +for_each_online_cpu (sibling) { + apicid =cpu_data (sibling).apicid; +if ((apicid < first) || (apicid > last))continue ;set_bit (sibling, this_leaf->shared_cpu_map); } } - }else if ((c->x86 ==0x15 ) && ((index ==1 ) || (index ==2 ))) { - ret =1 ; -for_each_cpu (i,cpu_sibling_mask (cpu)) { + }else if (index ==3 ) { +for_each_cpu (i,cpu_llc_shared_mask (cpu)) {if (!per_cpu (ici_cpuid4_info, i))continue ; this_leaf =CPUID4_INFO_IDX (i, index); -for_each_cpu (sibling,cpu_sibling_mask (cpu)) { +for_each_cpu (sibling,cpu_llc_shared_mask (cpu)) {if (!cpu_online (sibling))continue ;set_bit (sibling, this_leaf->shared_cpu_map); } } - } + }else +return 0 ; -return ret; +return 1 ; }static void __cpuinit cache_shared_cpu_map_setup (unsigned int cpu,int index)
Signature · 1 line
1.7.8.6
[tip:x86/cpu] x86, cacheinfo: Base cache sharing info on CPUID 0x8000001d on AMD
Commit-ID: 27d3a8a26ada7660116fdd6830096008c063ee96 Gitweb: http://git.kernel.org/tip/27d3a8a26ada7660116fdd6830096008c063ee96 Author: Andreas Herrmann <[email protected]> AuthorDate: Fri, 19 Oct 2012 11:02:09 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 13 Nov 2012 11:22:31 -0800
x86, cacheinfo: Base cache sharing info on CPUID 0x8000001d on AMD
The patch is based on a patch submitted by Hans Rosenfeld. See http://marc.info/?l=linux-kernel&m=133908777200931
Note that CPUID Fn8000_001D_EAX slightly differs to Intel's CPUID function 4.
Bits 14-25 contain NumSharingCache. Actual number of cores sharing
this cache. SW to add value of one to get result.
The corresponding bits on Intel are defined as "maximum number of threads sharing this cache" (with a "plus 1" encoding).
Thus a different method to determine which cores are sharing a cache level has to be used.
--- arch/x86/kernel/cpu/intel_cacheinfo.c | 41 +++++++++++++++++++++----------- 1 files changed, 27 insertions(+), 14 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +27 -14
@@ -750,37 +750,50 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);static int __cpuinit cache_shared_amd_cpu_map_setup (unsigned int cpu,int index) {struct _cpuid4_info *this_leaf; -int ret, i, sibling; -struct cpuinfo_x86 *c = &cpu_data (cpu); +int i, sibling; - ret =0 ; -if (index ==3 ) { - ret =1 ; -for_each_cpu (i,cpu_llc_shared_mask (cpu)) { +if (cpu_has_topoext) { +unsigned int apicid, nshared, first, last; + +if (!per_cpu (ici_cpuid4_info, cpu)) +return 0 ; + + this_leaf =CPUID4_INFO_IDX (cpu, index); + nshared = this_leaf->base.eax.split.num_threads_sharing +1 ; + apicid =cpu_data (cpu).apicid; + first = apicid - (apicid % nshared); + last = first + nshared -1 ; + +for_each_online_cpu (i) { + apicid =cpu_data (i).apicid; +if ((apicid < first) || (apicid > last)) +continue ;if (!per_cpu (ici_cpuid4_info, i))continue ; this_leaf =CPUID4_INFO_IDX (i, index); -for_each_cpu (sibling,cpu_llc_shared_mask (cpu)) { -if (!cpu_online (sibling)) + +for_each_online_cpu (sibling) { + apicid =cpu_data (sibling).apicid; +if ((apicid < first) || (apicid > last))continue ;set_bit (sibling, this_leaf->shared_cpu_map); } } - }else if ((c->x86 ==0x15 ) && ((index ==1 ) || (index ==2 ))) { - ret =1 ; -for_each_cpu (i,cpu_sibling_mask (cpu)) { + }else if (index ==3 ) { +for_each_cpu (i,cpu_llc_shared_mask (cpu)) {if (!per_cpu (ici_cpuid4_info, i))continue ; this_leaf =CPUID4_INFO_IDX (i, index); -for_each_cpu (sibling,cpu_sibling_mask (cpu)) { +for_each_cpu (sibling,cpu_llc_shared_mask (cpu)) {if (!cpu_online (sibling))continue ;set_bit (sibling, this_leaf->shared_cpu_map); } } - } + }else +return 0 ; -return ret; +return 1 ; }static void __cpuinit cache_shared_cpu_map_setup (unsigned int cpu,int index)
Quoted 7 lines · Andreas Herrmann
Hi,
Following patches modify cachinfo code to make use of AMD's topology extension CPUID functions. Thus (hopefully) we can avoid CPU specific modifications whenever cache topology changes.
Please apply.
Ping ?
Any feedback ? If not could we get it into tip ?
Thank you,
Quoted 14 lines
Thanks,
Andreas
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
H. Peter Anvin
reviewerToo many of us at LCE right now...
Quoted 34 lines · Jacob Shin
Quoted 7 lines · Andreas Herrmann
Hi,
Following patches modify cachinfo code to make use of AMD's topology extension CPUID functions. Thus (hopefully) we can avoid CPU specific modifications whenever cache topology changes.
Please apply.
Acked-by Jacob Shin <[email protected]>Ping ?
Any feedback ? If not could we get it into tip ?
Thank you,
Quoted 8 lines
Thanks,
Andreas
--
To unsubscribe from this list: send the line "unsubscribelinux-kernel" in
Quoted 6 lines
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 1 line
Sent from my mobile phone. Please excuse brevity and lack of formatting.
Quoted 1 line · H. Peter Anvin
Too many of us at LCE right now...
Hi, ping'ing once again, could you take a look at the patchset when you get the chance, and if no problems commit them into tip?
Thanks!
-Jacob
Quoted 41 lines
Quoted 34 lines · Jacob Shin
Quoted 7 lines · Andreas Herrmann
Hi,
Following patches modify cachinfo code to make use of AMD's topology extension CPUID functions. Thus (hopefully) we can avoid CPU specific modifications whenever cache topology changes.
Please apply.
Acked-by Jacob Shin <[email protected]>Ping ?
Any feedback ? If not could we get it into tip ?
Thank you,
Quoted 8 lines
Thanks,
Andreas
--
To unsubscribe from this list: send the line "unsubscribelinux-kernel" in
Quoted 6 lines
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/Signature · 1 line
Sent from my mobile phone. Please excuse brevity and lack of formatting.