diff options
author | Andreas Herrmann <andreas.herrmann3@amd.com> | 2012-10-19 04:59:33 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-11-13 14:22:29 -0500 |
commit | 04a1541828ea223169eb44a336bfad8ec0dfb46a (patch) | |
tree | a670df6305266009a488f52ad763eb5a13767abf | |
parent | 193f3fcb3ab769bab4a2b9fa181eef3e5699a352 (diff) |
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.
Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
Link: http://lkml.kernel.org/r/20121019085933.GE26718@alberich
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | arch/x86/include/asm/processor.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/amd.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 28 |
3 files changed, 25 insertions, 12 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index ad1fc8511674..db0d8c32090c 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -187,7 +187,7 @@ extern void print_cpu_info(struct cpuinfo_x86 *); | |||
187 | void print_cpu_msr(struct cpuinfo_x86 *); | 187 | void print_cpu_msr(struct cpuinfo_x86 *); |
188 | extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c); | 188 | extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c); |
189 | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); | 189 | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); |
190 | extern unsigned short num_cache_leaves; | 190 | extern void init_amd_cacheinfo(struct cpuinfo_x86 *c); |
191 | 191 | ||
192 | extern void detect_extended_topology(struct cpuinfo_x86 *c); | 192 | extern void detect_extended_topology(struct cpuinfo_x86 *c); |
193 | extern void detect_ht(struct cpuinfo_x86 *c); | 193 | extern void detect_ht(struct cpuinfo_x86 *c); |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 64e9ad4e49a0..a8538e6d2ff2 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -643,12 +643,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
643 | detect_ht(c); | 643 | detect_ht(c); |
644 | #endif | 644 | #endif |
645 | 645 | ||
646 | if (c->extended_cpuid_level >= 0x80000006) { | 646 | init_amd_cacheinfo(c); |
647 | if (cpuid_edx(0x80000006) & 0xf000) | ||
648 | num_cache_leaves = 4; | ||
649 | else | ||
650 | num_cache_leaves = 3; | ||
651 | } | ||
652 | 647 | ||
653 | if (c->x86 >= 0xf) | 648 | if (c->x86 >= 0xf) |
654 | set_cpu_cap(c, X86_FEATURE_K8); | 649 | set_cpu_cap(c, X86_FEATURE_K8); |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 93c5451bdd52..8ce7a83252f9 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -557,21 +557,39 @@ __cpuinit cpuid4_cache_lookup_regs(int index, | |||
557 | return 0; | 557 | return 0; |
558 | } | 558 | } |
559 | 559 | ||
560 | static int __cpuinit find_num_cache_leaves(void) | 560 | static int __cpuinit find_num_cache_leaves(struct cpuinfo_x86 *c) |
561 | { | 561 | { |
562 | unsigned int eax, ebx, ecx, edx; | 562 | unsigned int eax, ebx, ecx, edx, op; |
563 | union _cpuid4_leaf_eax cache_eax; | 563 | union _cpuid4_leaf_eax cache_eax; |
564 | int i = -1; | 564 | int i = -1; |
565 | 565 | ||
566 | if (c->x86_vendor == X86_VENDOR_AMD) | ||
567 | op = 0x8000001d; | ||
568 | else | ||
569 | op = 4; | ||
570 | |||
566 | do { | 571 | do { |
567 | ++i; | 572 | ++i; |
568 | /* Do cpuid(4) loop to find out num_cache_leaves */ | 573 | /* Do cpuid(op) loop to find out num_cache_leaves */ |
569 | cpuid_count(4, i, &eax, &ebx, &ecx, &edx); | 574 | cpuid_count(op, i, &eax, &ebx, &ecx, &edx); |
570 | cache_eax.full = eax; | 575 | cache_eax.full = eax; |
571 | } while (cache_eax.split.type != CACHE_TYPE_NULL); | 576 | } while (cache_eax.split.type != CACHE_TYPE_NULL); |
572 | return i; | 577 | return i; |
573 | } | 578 | } |
574 | 579 | ||
580 | void __cpuinit init_amd_cacheinfo(struct cpuinfo_x86 *c) | ||
581 | { | ||
582 | |||
583 | if (cpu_has_topoext) { | ||
584 | num_cache_leaves = find_num_cache_leaves(c); | ||
585 | } else if (c->extended_cpuid_level >= 0x80000006) { | ||
586 | if (cpuid_edx(0x80000006) & 0xf000) | ||
587 | num_cache_leaves = 4; | ||
588 | else | ||
589 | num_cache_leaves = 3; | ||
590 | } | ||
591 | } | ||
592 | |||
575 | unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | 593 | unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) |
576 | { | 594 | { |
577 | /* Cache sizes */ | 595 | /* Cache sizes */ |
@@ -588,7 +606,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | |||
588 | 606 | ||
589 | if (is_initialized == 0) { | 607 | if (is_initialized == 0) { |
590 | /* Init num_cache_leaves from boot CPU */ | 608 | /* Init num_cache_leaves from boot CPU */ |
591 | num_cache_leaves = find_num_cache_leaves(); | 609 | num_cache_leaves = find_num_cache_leaves(c); |
592 | is_initialized++; | 610 | is_initialized++; |
593 | } | 611 | } |
594 | 612 | ||