diff options
| author | Borislav Petkov <bp@suse.de> | 2014-06-24 07:25:04 -0400 |
|---|---|---|
| committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-07-14 15:21:40 -0400 |
| commit | 26bfa5f89486a8926cd4d4ca81a04d3f0f174934 (patch) | |
| tree | 5a51e1be2db950be44ffb3fb05f2df00811bda0f | |
| parent | 80a208bd3948aceddf0429bd9f9b4cd858d526df (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.c | 339 |
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 | ||
| 71 | static void init_amd_k5(struct cpuinfo_x86 *c) | 71 | static 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 | |||
| 89 | static void init_amd_k6(struct cpuinfo_x86 *c) | 90 | static 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 | ||
| 181 | static void amd_k7_smp_check(struct cpuinfo_x86 *c) | 184 | static 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 | |||
| 224 | static 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 | ||
| 447 | static void bsp_init_amd(struct cpuinfo_x86 *c) | 446 | static 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[]; | |||
| 515 | static const int amd_erratum_400[]; | 534 | static const int amd_erratum_400[]; |
| 516 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); | 535 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); |
| 517 | |||
