1 | /* |
---|
2 | * Athlon/Hammer specific Machine Check Exception Reporting |
---|
3 | * (C) Copyright 2002 Dave Jones <davej@codemonkey.org.uk> |
---|
4 | */ |
---|
5 | |
---|
6 | #include <xen/init.h> |
---|
7 | #include <xen/types.h> |
---|
8 | #include <xen/kernel.h> |
---|
9 | #include <xen/config.h> |
---|
10 | #include <xen/smp.h> |
---|
11 | |
---|
12 | #include <asm/processor.h> |
---|
13 | #include <asm/system.h> |
---|
14 | #include <asm/msr.h> |
---|
15 | |
---|
16 | #include "mce.h" |
---|
17 | |
---|
18 | /* Machine Check Handler For AMD Athlon/Duron */ |
---|
19 | static fastcall void k7_machine_check(struct cpu_user_regs * regs, long error_code) |
---|
20 | { |
---|
21 | int recover=1; |
---|
22 | u32 alow, ahigh, high, low; |
---|
23 | u32 mcgstl, mcgsth; |
---|
24 | int i; |
---|
25 | |
---|
26 | rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth); |
---|
27 | if (mcgstl & (1<<0)) /* Recoverable ? */ |
---|
28 | recover=0; |
---|
29 | |
---|
30 | printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", |
---|
31 | smp_processor_id(), mcgsth, mcgstl); |
---|
32 | |
---|
33 | for (i=1; i<nr_mce_banks; i++) { |
---|
34 | rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high); |
---|
35 | if (high&(1<<31)) { |
---|
36 | if (high & (1<<29)) |
---|
37 | recover |= 1; |
---|
38 | if (high & (1<<25)) |
---|
39 | recover |= 2; |
---|
40 | printk (KERN_EMERG "Bank %d: %08x%08x", i, high, low); |
---|
41 | high &= ~(1<<31); |
---|
42 | if (high & (1<<27)) { |
---|
43 | rdmsr (MSR_IA32_MC0_MISC+i*4, alow, ahigh); |
---|
44 | printk ("[%08x%08x]", ahigh, alow); |
---|
45 | } |
---|
46 | if (high & (1<<26)) { |
---|
47 | rdmsr (MSR_IA32_MC0_ADDR+i*4, alow, ahigh); |
---|
48 | printk (" at %08x%08x", ahigh, alow); |
---|
49 | } |
---|
50 | printk ("\n"); |
---|
51 | /* Clear it */ |
---|
52 | wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL); |
---|
53 | /* Serialize */ |
---|
54 | wmb(); |
---|
55 | add_taint(TAINT_MACHINE_CHECK); |
---|
56 | } |
---|
57 | } |
---|
58 | |
---|
59 | if (recover&2) |
---|
60 | panic ("CPU context corrupt"); |
---|
61 | if (recover&1) |
---|
62 | panic ("Unable to continue"); |
---|
63 | printk (KERN_EMERG "Attempting to continue.\n"); |
---|
64 | mcgstl &= ~(1<<2); |
---|
65 | wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth); |
---|
66 | } |
---|
67 | |
---|
68 | |
---|
69 | /* AMD K7 machine check is Intel like */ |
---|
70 | void amd_mcheck_init(struct cpuinfo_x86 *c) |
---|
71 | { |
---|
72 | u32 l, h; |
---|
73 | int i; |
---|
74 | |
---|
75 | machine_check_vector = k7_machine_check; |
---|
76 | wmb(); |
---|
77 | |
---|
78 | printk (KERN_INFO "Intel machine check architecture supported.\n"); |
---|
79 | rdmsr (MSR_IA32_MCG_CAP, l, h); |
---|
80 | if (l & (1<<8)) /* Control register present ? */ |
---|
81 | wrmsr (MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); |
---|
82 | nr_mce_banks = l & 0xff; |
---|
83 | |
---|
84 | /* Clear status for MC index 0 separately, we don't touch CTL, |
---|
85 | * as some Athlons cause spurious MCEs when its enabled. */ |
---|
86 | wrmsr (MSR_IA32_MC0_STATUS, 0x0, 0x0); |
---|
87 | for (i=1; i<nr_mce_banks; i++) { |
---|
88 | wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff); |
---|
89 | wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0); |
---|
90 | } |
---|
91 | |
---|
92 | set_in_cr4 (X86_CR4_MCE); |
---|
93 | printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", |
---|
94 | smp_processor_id()); |
---|
95 | } |
---|