diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck/p6.c')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/p6.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/p6.c b/arch/x86/kernel/cpu/mcheck/p6.c index 2ac52d7b434b..01e4f8178183 100644 --- a/arch/x86/kernel/cpu/mcheck/p6.c +++ b/arch/x86/kernel/cpu/mcheck/p6.c | |||
@@ -2,25 +2,23 @@ | |||
2 | * P6 specific Machine Check Exception Reporting | 2 | * P6 specific Machine Check Exception Reporting |
3 | * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk> | 3 | * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk> |
4 | */ | 4 | */ |
5 | |||
6 | #include <linux/init.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/init.h> | ||
10 | #include <linux/smp.h> | 9 | #include <linux/smp.h> |
11 | 10 | ||
12 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
13 | #include <asm/system.h> | 12 | #include <asm/system.h> |
13 | #include <asm/mce.h> | ||
14 | #include <asm/msr.h> | 14 | #include <asm/msr.h> |
15 | 15 | ||
16 | #include "mce.h" | ||
17 | |||
18 | /* Machine Check Handler For PII/PIII */ | 16 | /* Machine Check Handler For PII/PIII */ |
19 | static void intel_machine_check(struct pt_regs *regs, long error_code) | 17 | static void intel_machine_check(struct pt_regs *regs, long error_code) |
20 | { | 18 | { |
21 | int recover = 1; | ||
22 | u32 alow, ahigh, high, low; | 19 | u32 alow, ahigh, high, low; |
23 | u32 mcgstl, mcgsth; | 20 | u32 mcgstl, mcgsth; |
21 | int recover = 1; | ||
24 | int i; | 22 | int i; |
25 | 23 | ||
26 | rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); | 24 | rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
@@ -35,12 +33,16 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
35 | if (high & (1<<31)) { | 33 | if (high & (1<<31)) { |
36 | char misc[20]; | 34 | char misc[20]; |
37 | char addr[24]; | 35 | char addr[24]; |
38 | misc[0] = addr[0] = '\0'; | 36 | |
37 | misc[0] = '\0'; | ||
38 | addr[0] = '\0'; | ||
39 | |||
39 | if (high & (1<<29)) | 40 | if (high & (1<<29)) |
40 | recover |= 1; | 41 | recover |= 1; |
41 | if (high & (1<<25)) | 42 | if (high & (1<<25)) |
42 | recover |= 2; | 43 | recover |= 2; |
43 | high &= ~(1<<31); | 44 | high &= ~(1<<31); |
45 | |||
44 | if (high & (1<<27)) { | 46 | if (high & (1<<27)) { |
45 | rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh); | 47 | rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh); |
46 | snprintf(misc, 20, "[%08x%08x]", ahigh, alow); | 48 | snprintf(misc, 20, "[%08x%08x]", ahigh, alow); |
@@ -49,6 +51,7 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
49 | rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh); | 51 | rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh); |
50 | snprintf(addr, 24, " at %08x%08x", ahigh, alow); | 52 | snprintf(addr, 24, " at %08x%08x", ahigh, alow); |
51 | } | 53 | } |
54 | |||
52 | printk(KERN_EMERG "CPU %d: Bank %d: %08x%08x%s%s\n", | 55 | printk(KERN_EMERG "CPU %d: Bank %d: %08x%08x%s%s\n", |
53 | smp_processor_id(), i, high, low, misc, addr); | 56 | smp_processor_id(), i, high, low, misc, addr); |
54 | } | 57 | } |
@@ -63,16 +66,17 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
63 | /* | 66 | /* |
64 | * Do not clear the MSR_IA32_MCi_STATUS if the error is not | 67 | * Do not clear the MSR_IA32_MCi_STATUS if the error is not |
65 | * recoverable/continuable.This will allow BIOS to look at the MSRs | 68 | * recoverable/continuable.This will allow BIOS to look at the MSRs |
66 | * for errors if the OS could not log the error. | 69 | * for errors if the OS could not log the error: |
67 | */ | 70 | */ |
68 | for (i = 0; i < nr_mce_banks; i++) { | 71 | for (i = 0; i < nr_mce_banks; i++) { |
69 | unsigned int msr; | 72 | unsigned int msr; |
73 | |||
70 | msr = MSR_IA32_MC0_STATUS+i*4; | 74 | msr = MSR_IA32_MC0_STATUS+i*4; |
71 | rdmsr(msr, low, high); | 75 | rdmsr(msr, low, high); |
72 | if (high & (1<<31)) { | 76 | if (high & (1<<31)) { |
73 | /* Clear it */ | 77 | /* Clear it: */ |
74 | wrmsr(msr, 0UL, 0UL); | 78 | wrmsr(msr, 0UL, 0UL); |
75 | /* Serialize */ | 79 | /* Serialize: */ |
76 | wmb(); | 80 | wmb(); |
77 | add_taint(TAINT_MACHINE_CHECK); | 81 | add_taint(TAINT_MACHINE_CHECK); |
78 | } | 82 | } |
@@ -81,7 +85,7 @@ static void intel_machine_check(struct pt_regs *regs, long error_code) | |||
81 | wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); | 85 | wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
82 | } | 86 | } |
83 | 87 | ||
84 | /* Set up machine check reporting for processors with Intel style MCE */ | 88 | /* Set up machine check reporting for processors with Intel style MCE: */ |
85 | void intel_p6_mcheck_init(struct cpuinfo_x86 *c) | 89 | void intel_p6_mcheck_init(struct cpuinfo_x86 *c) |
86 | { | 90 | { |
87 | u32 l, h; | 91 | u32 l, h; |
@@ -97,6 +101,7 @@ void intel_p6_mcheck_init(struct cpuinfo_x86 *c) | |||
97 | 101 | ||
98 | /* Ok machine check is available */ | 102 | /* Ok machine check is available */ |
99 | machine_check_vector = intel_machine_check; | 103 | machine_check_vector = intel_machine_check; |
104 | /* Make sure the vector pointer is visible before we enable MCEs: */ | ||
100 | wmb(); | 105 | wmb(); |
101 | 106 | ||
102 | printk(KERN_INFO "Intel machine check architecture supported.\n"); | 107 | printk(KERN_INFO "Intel machine check architecture supported.\n"); |