diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 22:58:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-11 22:58:29 -0500 |
commit | a05a4e24dcd73c2de4ef3f8d520b8bbb44570c60 (patch) | |
tree | f9f8c12829e82c95b26b2bb19e0818ca6fcd836c /arch/x86/kernel/cpu | |
parent | e9a5a919719673b932ac968dfb4332b6f892b025 (diff) | |
parent | 27d3a8a26ada7660116fdd6830096008c063ee96 (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.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 75 |
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 | ||
560 | static int __cpuinit find_num_cache_leaves(void) | 564 | static 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 | ||
584 | void __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 | |||
575 | unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | 597 | unsigned 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); | |||
728 | static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) | 750 | static 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 | ||
764 | static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) | 799 | static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) |