aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 22:58:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 22:58:29 -0500
commita05a4e24dcd73c2de4ef3f8d520b8bbb44570c60 (patch)
treef9f8c12829e82c95b26b2bb19e0818ca6fcd836c /arch/x86/kernel/cpu
parente9a5a919719673b932ac968dfb4332b6f892b025 (diff)
parent27d3a8a26ada7660116fdd6830096008c063ee96 (diff)
Merge branch 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 topology discovery improvements from Ingo Molnar: "These changes improve topology discovery on AMD CPUs. Right now this feeds information displayed in /sys/devices/system/cpu/cpuX/cache/indexY/* - but in the future we could use this to set up a better scheduling topology." * 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, cacheinfo: Base cache sharing info on CPUID 0x8000001d on AMD x86, cacheinfo: Make use of CPUID 0x8000001d for cache information on AMD x86, cacheinfo: Determine number of cache leafs using CPUID 0x8000001d on AMD x86: Add cpu_has_topoext
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r--arch/x86/kernel/cpu/amd.c9
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c75
2 files changed, 57 insertions, 27 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 1b7d1656a042..ce71a25f4523 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -304,7 +304,7 @@ static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
304 int cpu = smp_processor_id(); 304 int cpu = smp_processor_id();
305 305
306 /* get information required for multi-node processors */ 306 /* get information required for multi-node processors */
307 if (cpu_has(c, X86_FEATURE_TOPOEXT)) { 307 if (cpu_has_topoext) {
308 u32 eax, ebx, ecx, edx; 308 u32 eax, ebx, ecx, edx;
309 309
310 cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); 310 cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
@@ -657,12 +657,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
657 detect_ht(c); 657 detect_ht(c);
658#endif 658#endif
659 659
660 if (c->extended_cpuid_level >= 0x80000006) { 660 init_amd_cacheinfo(c);
661 if (cpuid_edx(0x80000006) & 0xf000)
662 num_cache_leaves = 4;
663 else
664 num_cache_leaves = 3;
665 }
666 661
667 if (c->x86 >= 0xf) 662 if (c->x86 >= 0xf)
668 set_cpu_cap(c, X86_FEATURE_K8); 663 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..fe9edec6698a 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -538,7 +538,11 @@ __cpuinit cpuid4_cache_lookup_regs(int index,
538 unsigned edx; 538 unsigned edx;
539 539
540 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { 540 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
541 amd_cpuid4(index, &eax, &ebx, &ecx); 541 if (cpu_has_topoext)
542 cpuid_count(0x8000001d, index, &eax.full,
543 &ebx.full, &ecx.full, &edx);
544 else
545 amd_cpuid4(index, &eax, &ebx, &ecx);
542 amd_init_l3_cache(this_leaf, index); 546 amd_init_l3_cache(this_leaf, index);
543 } else { 547 } else {
544 cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); 548 cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
@@ -557,21 +561,39 @@ __cpuinit cpuid4_cache_lookup_regs(int index,
557 return 0; 561 return 0;
558} 562}
559 563
560static int __cpuinit find_num_cache_leaves(void) 564static int __cpuinit find_num_cache_leaves(struct cpuinfo_x86 *c)
561{ 565{
562 unsigned int eax, ebx, ecx, edx; 566 unsigned int eax, ebx, ecx, edx, op;
563 union _cpuid4_leaf_eax cache_eax; 567 union _cpuid4_leaf_eax cache_eax;
564 int i = -1; 568 int i = -1;
565 569
570 if (c->x86_vendor == X86_VENDOR_AMD)
571 op = 0x8000001d;
572 else
573 op = 4;
574
566 do { 575 do {
567 ++i; 576 ++i;
568 /* Do cpuid(4) loop to find out num_cache_leaves */ 577 /* Do cpuid(op) loop to find out num_cache_leaves */
569 cpuid_count(4, i, &eax, &ebx, &ecx, &edx); 578 cpuid_count(op, i, &eax, &ebx, &ecx, &edx);
570 cache_eax.full = eax; 579 cache_eax.full = eax;
571 } while (cache_eax.split.type != CACHE_TYPE_NULL); 580 } while (cache_eax.split.type != CACHE_TYPE_NULL);
572 return i; 581 return i;
573} 582}
574 583
584void __cpuinit init_amd_cacheinfo(struct cpuinfo_x86 *c)
585{
586
587 if (cpu_has_topoext) {
588 num_cache_leaves = find_num_cache_leaves(c);
589 } else if (c->extended_cpuid_level >= 0x80000006) {
590 if (cpuid_edx(0x80000006) & 0xf000)
591 num_cache_leaves = 4;
592 else
593 num_cache_leaves = 3;
594 }
595}
596
575unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) 597unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
576{ 598{
577 /* Cache sizes */ 599 /* Cache sizes */
@@ -588,7 +610,7 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
588 610
589 if (is_initialized == 0) { 611 if (is_initialized == 0) {
590 /* Init num_cache_leaves from boot CPU */ 612 /* Init num_cache_leaves from boot CPU */
591 num_cache_leaves = find_num_cache_leaves(); 613 num_cache_leaves = find_num_cache_leaves(c);
592 is_initialized++; 614 is_initialized++;
593 } 615 }
594 616
@@ -728,37 +750,50 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);
728static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) 750static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index)
729{ 751{
730 struct _cpuid4_info *this_leaf; 752 struct _cpuid4_info *this_leaf;
731 int ret, i, sibling; 753 int i, sibling;
732 struct cpuinfo_x86 *c = &cpu_data(cpu);
733 754
734 ret = 0; 755 if (cpu_has_topoext) {
735 if (index == 3) { 756 unsigned int apicid, nshared, first, last;
736 ret = 1; 757
737 for_each_cpu(i, cpu_llc_shared_mask(cpu)) { 758 if (!per_cpu(ici_cpuid4_info, cpu))
759 return 0;
760
761 this_leaf = CPUID4_INFO_IDX(cpu, index);
762 nshared = this_leaf->base.eax.split.num_threads_sharing + 1;
763 apicid = cpu_data(cpu).apicid;
764 first = apicid - (apicid % nshared);
765 last = first + nshared - 1;
766
767 for_each_online_cpu(i) {
768 apicid = cpu_data(i).apicid;
769 if ((apicid < first) || (apicid > last))
770 continue;
738 if (!per_cpu(ici_cpuid4_info, i)) 771 if (!per_cpu(ici_cpuid4_info, i))
739 continue; 772 continue;
740 this_leaf = CPUID4_INFO_IDX(i, index); 773 this_leaf = CPUID4_INFO_IDX(i, index);
741 for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) { 774
742 if (!cpu_online(sibling)) 775 for_each_online_cpu(sibling) {
776 apicid = cpu_data(sibling).apicid;
777 if ((apicid < first) || (apicid > last))
743 continue; 778 continue;
744 set_bit(sibling, this_leaf->shared_cpu_map); 779 set_bit(sibling, this_leaf->shared_cpu_map);
745 } 780 }
746 } 781 }
747 } else if ((c->x86 == 0x15) && ((index == 1) || (index == 2))) { 782 } else if (index == 3) {
748 ret = 1; 783 for_each_cpu(i, cpu_llc_shared_mask(cpu)) {
749 for_each_cpu(i, cpu_sibling_mask(cpu)) {
750 if (!per_cpu(ici_cpuid4_info, i)) 784 if (!per_cpu(ici_cpuid4_info, i))
751 continue; 785 continue;
752 this_leaf = CPUID4_INFO_IDX(i, index); 786 this_leaf = CPUID4_INFO_IDX(i, index);
753 for_each_cpu(sibling, cpu_sibling_mask(cpu)) { 787 for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) {
754 if (!cpu_online(sibling)) 788 if (!cpu_online(sibling))
755 continue; 789 continue;
756 set_bit(sibling, this_leaf->shared_cpu_map); 790 set_bit(sibling, this_leaf->shared_cpu_map);
757 } 791 }
758 } 792 }
759 } 793 } else
794 return 0;
760 795
761 return ret; 796 return 1;
762} 797}
763 798
764static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) 799static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)