diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-17 18:41:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-17 18:41:04 -0400 |
commit | bc5e8fdfc622b03acf5ac974a1b8b26da6511c99 (patch) | |
tree | 912dbeaadd246bd053a9650c79d1bd98bbc71556 | |
parent | 61ffcafafb3d985e1ab8463be0187b421614775c (diff) |
x86-64/smp: fix random SIGSEGV issues
They seem to have been due to AMD errata 63/122; the fix is to disable
TLB flush filtering in SMP configurations.
Confirmed to fix the problem by Andrew Walrond <andrew@walrond.org>
[ Let's see if we'll have a better fix eventually, this is the Q&D
"let's get this fixed and out there" version ]
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/x86_64/kernel/setup.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 351d8d64c2fb..238f73e1a834 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
@@ -831,11 +831,26 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
831 | #endif | 831 | #endif |
832 | } | 832 | } |
833 | 833 | ||
834 | #define HWCR 0xc0010015 | ||
835 | |||
834 | static int __init init_amd(struct cpuinfo_x86 *c) | 836 | static int __init init_amd(struct cpuinfo_x86 *c) |
835 | { | 837 | { |
836 | int r; | 838 | int r; |
837 | int level; | 839 | int level; |
838 | 840 | ||
841 | #ifdef CONFIG_SMP | ||
842 | unsigned long value; | ||
843 | |||
844 | // Disable TLB flush filter by setting HWCR.FFDIS: | ||
845 | // bit 6 of msr C001_0015 | ||
846 | // | ||
847 | // Errata 63 for SH-B3 steppings | ||
848 | // Errata 122 for all(?) steppings | ||
849 | rdmsrl(HWCR, value); | ||
850 | value |= 1 << 6; | ||
851 | wrmsrl(HWCR, value); | ||
852 | #endif | ||
853 | |||
839 | /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; | 854 | /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; |
840 | 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ | 855 | 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ |
841 | clear_bit(0*32+31, &c->x86_capability); | 856 | clear_bit(0*32+31, &c->x86_capability); |