diff options
| -rw-r--r-- | arch/x86/include/asm/cpufeature.h | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/processor.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/intel_cacheinfo.c | 75 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 2 |
5 files changed, 60 insertions, 29 deletions
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 8c297aa53ee..c22a492daf5 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
| @@ -311,6 +311,7 @@ extern const char * const x86_power_flags[32]; | |||
| 311 | #define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8) | 311 | #define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8) |
| 312 | #define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) | 312 | #define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) |
| 313 | #define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU) | 313 | #define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU) |
| 314 | #define cpu_has_topoext boot_cpu_has(X86_FEATURE_TOPOEXT) | ||
| 314 | 315 | ||
| 315 | #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) | 316 | #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) |
| 316 | # define cpu_has_invlpg 1 | 317 | # define cpu_has_invlpg 1 |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index ad1fc851167..db0d8c32090 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 1b7d1656a04..ce71a25f452 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 93c5451bdd5..fe9edec6698 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) |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index c635663b20d..ed0fe385289 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -332,7 +332,7 @@ do { \ | |||
| 332 | 332 | ||
| 333 | static bool __cpuinit match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) | 333 | static bool __cpuinit match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) |
| 334 | { | 334 | { |
| 335 | if (cpu_has(c, X86_FEATURE_TOPOEXT)) { | 335 | if (cpu_has_topoext) { |
| 336 | int cpu1 = c->cpu_index, cpu2 = o->cpu_index; | 336 | int cpu1 = c->cpu_index, cpu2 = o->cpu_index; |
| 337 | 337 | ||
| 338 | if (c->phys_proc_id == o->phys_proc_id && | 338 | if (c->phys_proc_id == o->phys_proc_id && |
