aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2014-06-24 07:25:04 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2014-07-14 15:21:40 -0400
commit26bfa5f89486a8926cd4d4ca81a04d3f0f174934 (patch)
tree5a51e1be2db950be44ffb3fb05f2df00811bda0f
parent80a208bd3948aceddf0429bd9f9b4cd858d526df (diff)
x86, amd: Cleanup init_amd
Distribute family-specific code to corresponding functions. Also, * move the direct mapping splitting around the TSEG SMM area to bsp_init_amd(). * kill ancient comment about what we should do for K5. * merge amd_k7_smp_check() into its only caller init_amd_k7 and drop cpu_has_mp macro. Signed-off-by: Borislav Petkov <bp@suse.de> Link: http://lkml.kernel.org/r/1403609105-8332-3-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/kernel/cpu/amd.c339
1 files changed, 161 insertions, 178 deletions
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 8714a78414bf..bc360d3df60e 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -8,6 +8,7 @@
8#include <asm/processor.h> 8#include <asm/processor.h>
9#include <asm/apic.h> 9#include <asm/apic.h>
10#include <asm/cpu.h> 10#include <asm/cpu.h>
11#include <asm/smp.h>
11#include <asm/pci-direct.h> 12#include <asm/pci-direct.h>
12 13
13#ifdef CONFIG_X86_64 14#ifdef CONFIG_X86_64
@@ -50,7 +51,6 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
50 return wrmsr_safe_regs(gprs); 51 return wrmsr_safe_regs(gprs);
51} 52}
52 53
53#ifdef CONFIG_X86_32
54/* 54/*
55 * B step AMD K6 before B 9730xxxx have hardware bugs that can cause 55 * B step AMD K6 before B 9730xxxx have hardware bugs that can cause
56 * misexecution of code under Linux. Owners of such processors should 56 * misexecution of code under Linux. Owners of such processors should
@@ -70,6 +70,7 @@ __asm__(".globl vide\n\t.align 4\nvide: ret");
70 70
71static void init_amd_k5(struct cpuinfo_x86 *c) 71static void init_amd_k5(struct cpuinfo_x86 *c)
72{ 72{
73#ifdef CONFIG_X86_32
73/* 74/*
74 * General Systems BIOSen alias the cpu frequency registers 75 * General Systems BIOSen alias the cpu frequency registers
75 * of the Elan at 0x000df000. Unfortuantly, one of the Linux 76 * of the Elan at 0x000df000. Unfortuantly, one of the Linux
@@ -83,11 +84,12 @@ static void init_amd_k5(struct cpuinfo_x86 *c)
83 if (inl(CBAR) & CBAR_ENB) 84 if (inl(CBAR) & CBAR_ENB)
84 outl(0 | CBAR_KEY, CBAR); 85 outl(0 | CBAR_KEY, CBAR);
85 } 86 }
87#endif
86} 88}
87 89
88
89static void init_amd_k6(struct cpuinfo_x86 *c) 90static void init_amd_k6(struct cpuinfo_x86 *c)
90{ 91{
92#ifdef CONFIG_X86_32
91 u32 l, h; 93 u32 l, h;
92 int mbytes = get_num_physpages() >> (20-PAGE_SHIFT); 94 int mbytes = get_num_physpages() >> (20-PAGE_SHIFT);
93 95
@@ -176,10 +178,44 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
176 /* placeholder for any needed mods */ 178 /* placeholder for any needed mods */
177 return; 179 return;
178 } 180 }
181#endif
179} 182}
180 183
181static void amd_k7_smp_check(struct cpuinfo_x86 *c) 184static void init_amd_k7(struct cpuinfo_x86 *c)
182{ 185{
186#ifdef CONFIG_X86_32
187 u32 l, h;
188
189 /*
190 * Bit 15 of Athlon specific MSR 15, needs to be 0
191 * to enable SSE on Palomino/Morgan/Barton CPU's.
192 * If the BIOS didn't enable it already, enable it here.
193 */
194 if (c->x86_model >= 6 && c->x86_model <= 10) {
195 if (!cpu_has(c, X86_FEATURE_XMM)) {
196 printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
197 msr_clear_bit(MSR_K7_HWCR, 15);
198 set_cpu_cap(c, X86_FEATURE_XMM);
199 }
200 }
201
202 /*
203 * It's been determined by AMD that Athlons since model 8 stepping 1
204 * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
205 * As per AMD technical note 27212 0.2
206 */
207 if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
208 rdmsr(MSR_K7_CLK_CTL, l, h);
209 if ((l & 0xfff00000) != 0x20000000) {
210 printk(KERN_INFO
211 "CPU: CLK_CTL MSR was %x. Reprogramming to %x\n",
212 l, ((l & 0x000fffff)|0x20000000));
213 wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
214 }
215 }
216
217 set_cpu_cap(c, X86_FEATURE_K7);
218
183 /* calling is from identify_secondary_cpu() ? */ 219 /* calling is from identify_secondary_cpu() ? */
184 if (!c->cpu_index) 220 if (!c->cpu_index)
185 return; 221 return;
@@ -207,7 +243,7 @@ static void amd_k7_smp_check(struct cpuinfo_x86 *c)
207 if (((c->x86_model == 6) && (c->x86_mask >= 2)) || 243 if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
208 ((c->x86_model == 7) && (c->x86_mask >= 1)) || 244 ((c->x86_model == 7) && (c->x86_mask >= 1)) ||
209 (c->x86_model > 7)) 245 (c->x86_model > 7))
210 if (cpu_has_mp) 246 if (cpu_has(c, X86_FEATURE_MP))
211 return; 247 return;
212 248
213 /* If we get here, not a certified SMP capable AMD system. */ 249 /* If we get here, not a certified SMP capable AMD system. */
@@ -219,45 +255,8 @@ static void amd_k7_smp_check(struct cpuinfo_x86 *c)
219 WARN_ONCE(1, "WARNING: This combination of AMD" 255 WARN_ONCE(1, "WARNING: This combination of AMD"
220 " processors is not suitable for SMP.\n"); 256 " processors is not suitable for SMP.\n");
221 add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE); 257 add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE);
222}
223
224static void init_amd_k7(struct cpuinfo_x86 *c)
225{
226 u32 l, h;
227
228 /*
229 * Bit 15 of Athlon specific MSR 15, needs to be 0
230 * to enable SSE on Palomino/Morgan/Barton CPU's.
231 * If the BIOS didn't enable it already, enable it here.
232 */
233 if (c->x86_model >= 6 && c->x86_model <= 10) {
234 if (!cpu_has(c, X86_FEATURE_XMM)) {
235 printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
236 msr_clear_bit(MSR_K7_HWCR, 15);
237 set_cpu_cap(c, X86_FEATURE_XMM);
238 }
239 }
240
241 /*
242 * It's been determined by AMD that Athlons since model 8 stepping 1
243 * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
244 * As per AMD technical note 27212 0.2
245 */
246 if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
247 rdmsr(MSR_K7_CLK_CTL, l, h);
248 if ((l & 0xfff00000) != 0x20000000) {
249 printk(KERN_INFO
250 "CPU: CLK_CTL MSR was %x. Reprogramming to %x\n",
251 l, ((l & 0x000fffff)|0x20000000));
252 wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
253 }
254 }
255
256 set_cpu_cap(c, X86_FEATURE_K7);
257
258 amd_k7_smp_check(c);
259}
260#endif 258#endif
259}
261 260
262#ifdef CONFIG_NUMA 261#ifdef CONFIG_NUMA
263/* 262/*
@@ -446,6 +445,26 @@ static void early_init_amd_mc(struct cpuinfo_x86 *c)
446 445
447static void bsp_init_amd(struct cpuinfo_x86 *c) 446static void bsp_init_amd(struct cpuinfo_x86 *c)
448{ 447{
448
449#ifdef CONFIG_X86_64
450 if (c->x86 >= 0xf) {
451 unsigned long long tseg;
452
453 /*
454 * Split up direct mapping around the TSEG SMM area.
455 * Don't do it for gbpages because there seems very little
456 * benefit in doing so.
457 */
458 if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
459 unsigned long pfn = tseg >> PAGE_SHIFT;
460
461 printk(KERN_DEBUG "tseg: %010llx\n", tseg);
462 if (pfn_range_is_mapped(pfn, pfn + 1))
463 set_memory_4k((unsigned long)__va(tseg), 1);
464 }
465 }
466#endif
467
449 if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { 468 if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
450 469
451 if (c->x86 > 0x10 || 470 if (c->x86 > 0x10 ||
@@ -515,10 +534,100 @@ static const int amd_erratum_383[];
515static const int amd_erratum_400[]; 534static const int amd_erratum_400[];
516static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); 535static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
517 536
537static void init_amd_k8(struct cpuinfo_x86 *c)
538{
539 u32 level;
540 u64 value;
541
542 /* On C+ stepping K8 rep microcode works well for copy/memset */
543 level = cpuid_eax(1);
544 if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
545 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
546
547 /*
548 * Some BIOSes incorrectly force this feature, but only K8 revision D
549 * (model = 0x14) and later actually support it.
550 * (AMD Erratum #110, docId: 25759).
551 */
552 if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM)) {
553 clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
554 if (!rdmsrl_amd_safe(0xc001100d, &value)) {
555 value &= ~BIT_64(32);
556 wrmsrl_amd_safe(0xc001100d, value);
557 }
558 }
559
560 if (!c->x86_model_id[0])
561 strcpy(c->x86_model_id, "Hammer");
562}
563
564static void init_amd_gh(struct cpuinfo_x86 *c)
565{
566#ifdef CONFIG_X86_64
567 /* do this for boot cpu */
568 if (c == &boot_cpu_data)
569 check_enable_amd_mmconf_dmi();
570
571 fam10h_check_enable_mmcfg();
572#endif
573
574 /*
575 * Disable GART TLB Walk Errors on Fam10h. We do this here because this
576 * is always needed when GART is enabled, even in a kernel which has no
577 * MCE support built in. BIOS should disable GartTlbWlk Errors already.
578 * If it doesn't, we do it here as suggested by the BKDG.
579 *
580 * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
581 */
582 msr_set_bit(MSR_AMD64_MCx_MASK(4), 10);
583
584 /*
585 * On family 10h BIOS may not have properly enabled WC+ support, causing
586 * it to be converted to CD memtype. This may result in performance
587 * degradation for certain nested-paging guests. Prevent this conversion
588 * by clearing bit 24 in MSR_AMD64_BU_CFG2.
589 *
590 * NOTE: we want to use the _safe accessors so as not to #GP kvm
591 * guests on older kvm hosts.
592 */
593 msr_clear_bit(MSR_AMD64_BU_CFG2, 24);
594
595 if (cpu_has_amd_erratum(c, amd_erratum_383))
596 set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
597}
598
599static void init_amd_bd(struct cpuinfo_x86 *c)
600{
601 u64 value;
602
603 /* re-enable TopologyExtensions if switched off by BIOS */
604 if ((c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
605 !cpu_has(c, X86_FEATURE_TOPOEXT)) {
606
607 if (msr_set_bit(0xc0011005, 54) > 0) {
608 rdmsrl(0xc0011005, value);
609 if (value & BIT_64(54)) {
610 set_cpu_cap(c, X86_FEATURE_TOPOEXT);
611 pr_info(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
612 }
613 }
614 }
615
616 /*
617 * The way access filter has a performance penalty on some workloads.
618 * Disable it on the affected CPUs.
619 */
620 if ((c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
621 if (!rdmsrl_safe(0xc0011021, &value) && !(value & 0x1E)) {
622 value |= 0x1E;
623 wrmsrl_safe(0xc0011021, value);
624 }
625 }
626}
627
518static void init_amd(struct cpuinfo_x86 *c) 628static void init_amd(struct cpuinfo_x86 *c)
519{ 629{
520 u32 dummy; 630 u32 dummy;
521 unsigned long long value;
522 631
523#ifdef CONFIG_SMP 632#ifdef CONFIG_SMP
524 /* 633 /*
@@ -540,100 +649,29 @@ static void init_amd(struct cpuinfo_x86 *c)
540 */ 649 */
541 clear_cpu_cap(c, 0*32+31); 650 clear_cpu_cap(c, 0*32+31);
542 651
543#ifdef CONFIG_X86_64
544 /* On C+ stepping K8 rep microcode works well for copy/memset */
545 if (c->x86 == 0xf) {
546 u32 level;
547
548 level = cpuid_eax(1);
549 if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
550 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
551
552 /*
553 * Some BIOSes incorrectly force this feature, but only K8
554 * revision D (model = 0x14) and later actually support it.
555 * (AMD Erratum #110, docId: 25759).
556 */
557 if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM)) {
558 clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
559 if (!rdmsrl_amd_safe(0xc001100d, &value)) {
560 value &= ~(1ULL << 32);
561 wrmsrl_amd_safe(0xc001100d, value);
562 }
563 }
564
565 }
566 if (c->x86 >= 0x10) 652 if (c->x86 >= 0x10)
567 set_cpu_cap(c, X86_FEATURE_REP_GOOD); 653 set_cpu_cap(c, X86_FEATURE_REP_GOOD);
568 654
569 /* get apicid instead of initial apic id from cpuid */ 655 /* get apicid instead of initial apic id from cpuid */
570 c->apicid = hard_smp_processor_id(); 656 c->apicid = hard_smp_processor_id();
571#else
572
573 /*
574 * FIXME: We should handle the K5 here. Set up the write
575 * range and also turn on MSR 83 bits 4 and 31 (write alloc,
576 * no bus pipeline)
577 */
578
579 switch (c->x86) {
580 case 4:
581 init_amd_k5(c);
582 break;
583 case 5:
584 init_amd_k6(c);
585 break;
586 case 6: /* An Athlon/Duron */
587 init_amd_k7(c);
588 break;
589 }
590 657
591 /* K6s reports MCEs but don't actually have all the MSRs */ 658 /* K6s reports MCEs but don't actually have all the MSRs */
592 if (c->x86 < 6) 659 if (c->x86 < 6)
593 clear_cpu_cap(c, X86_FEATURE_MCE); 660 clear_cpu_cap(c, X86_FEATURE_MCE);
594#endif 661
662 switch (c->x86) {
663 case 4: init_amd_k5(c); break;
664 case 5: init_amd_k6(c); break;
665 case 6: init_amd_k7(c); break;
666 case 0xf: init_amd_k8(c); break;
667 case 0x10: init_amd_gh(c); break;
668 case 0x15: init_amd_bd(c); break;
669 }
595 670
596 /* Enable workaround for FXSAVE leak */ 671 /* Enable workaround for FXSAVE leak */
597 if (c->x86 >= 6) 672 if (c->x86 >= 6)
598 set_cpu_bug(c, X86_BUG_FXSAVE_LEAK); 673 set_cpu_bug(c, X86_BUG_FXSAVE_LEAK);
599 674
600 if (!c->x86_model_id[0]) {
601 switch (c->x86) {
602 case 0xf:
603 /* Should distinguish Models here, but this is only
604 a fallback anyways. */
605 strcpy(c->x86_model_id, "Hammer");
606 break;
607 }
608 }
609
610 /* re-enable TopologyExtensions if switched off by BIOS */
611 if ((c->x86 == 0x15) &&
612 (c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
613 !cpu_has(c, X86_FEATURE_TOPOEXT)) {
614
615 if (msr_set_bit(0xc0011005, 54) > 0) {
616 rdmsrl(0xc0011005, value);
617 if (value & BIT_64(54)) {
618 set_cpu_cap(c, X86_FEATURE_TOPOEXT);
619 pr_info(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
620 }
621 }
622 }
623
624 /*
625 * The way access filter has a performance penalty on some workloads.
626 * Disable it on the affected CPUs.
627 */
628 if ((c->x86 == 0x15) &&
629 (c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
630
631 if (!rdmsrl_safe(0xc0011021, &value) && !(value & 0x1E)) {
632 value |= 0x1E;
633 wrmsrl_safe(0xc0011021, value);
634 }
635 }
636
637 cpu_detect_cache_sizes(c); 675 cpu_detect_cache_sizes(c);
638 676
639 /* Multi core CPU? */ 677 /* Multi core CPU? */
@@ -656,33 +694,6 @@ static void init_amd(struct cpuinfo_x86 *c)
656 set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); 694 set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
657 } 695 }
658 696
659#ifdef CONFIG_X86_64
660 if (c->x86 == 0x10) {
661 /* do this for boot cpu */
662 if (c == &boot_cpu_data)
663 check_enable_amd_mmconf_dmi();
664
665 fam10h_check_enable_mmcfg();
666 }
667
668 if (c == &boot_cpu_data && c->x86 >= 0xf) {
669 unsigned long long tseg;
670
671 /*
672 * Split up direct mapping around the TSEG SMM area.
673 * Don't do it for gbpages because there seems very little
674 * benefit in doing so.
675 */
676 if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
677 unsigned long pfn = tseg >> PAGE_SHIFT;
678
679 printk(KERN_DEBUG "tseg: %010llx\n", tseg);
680 if (pfn_range_is_mapped(pfn, pfn + 1))
681 set_memory_4k((unsigned long)__va(tseg), 1);
682 }
683 }
684#endif
685
686 /* 697 /*
687 * Family 0x12 and above processors have APIC timer 698 * Family 0x12 and above processors have APIC timer
688 * running in deep C states. 699 * running in deep C states.
@@ -690,34 +701,6 @@ static void init_amd(struct cpuinfo_x86 *c)
690 if (c->x86 > 0x11) 701 if (c->x86 > 0x11)
691 set_cpu_cap(c, X86_FEATURE_ARAT); 702 set_cpu_cap(c, X86_FEATURE_ARAT);
692 703
693 if (c->x86 == 0x10) {
694 /*
695 * Disable GART TLB Walk Errors on Fam10h. We do this here
696 * because this is always needed when GART is enabled, even in a
697 * kernel which has no MCE support built in.
698 * BIOS should disable GartTlbWlk Errors already. If
699 * it doesn't, do it here as suggested by the BKDG.
700 *
701 * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
702 */
703 msr_set_bit(MSR_AMD64_MCx_MASK(4), 10);
704
705 /*
706 * On family 10h BIOS may not have properly enabled WC+ support,
707 * causing it to be converted to CD memtype. This may result in
708 * performance degradation for certain nested-paging guests.
709 * Prevent this conversion by clearing bit 24 in
710 * MSR_AMD64_BU_CFG2.
711 *
712 * NOTE: we want to use the _safe accessors so as not to #GP kvm
713 * guests on older kvm hosts.
714 */
715 msr_clear_bit(MSR_AMD64_BU_CFG2, 24);
716
717 if (cpu_has_amd_erratum(c, amd_erratum_383))
718 set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
719 }
720
721 if (cpu_has_amd_erratum(c, amd_erratum_400)) 704 if (cpu_has_amd_erratum(c, amd_erratum_400))
722 set_cpu_bug(c, X86_BUG_AMD_APIC_C1E); 705 set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
723 706