diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck/mce.c')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 2f5aab26320..4b2af86e3e8 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -305,13 +305,25 @@ static int msr_to_offset(u32 msr) | |||
305 | static u64 mce_rdmsrl(u32 msr) | 305 | static u64 mce_rdmsrl(u32 msr) |
306 | { | 306 | { |
307 | u64 v; | 307 | u64 v; |
308 | |||
308 | if (__get_cpu_var(injectm).finished) { | 309 | if (__get_cpu_var(injectm).finished) { |
309 | int offset = msr_to_offset(msr); | 310 | int offset = msr_to_offset(msr); |
311 | |||
310 | if (offset < 0) | 312 | if (offset < 0) |
311 | return 0; | 313 | return 0; |
312 | return *(u64 *)((char *)&__get_cpu_var(injectm) + offset); | 314 | return *(u64 *)((char *)&__get_cpu_var(injectm) + offset); |
313 | } | 315 | } |
314 | rdmsrl(msr, v); | 316 | |
317 | if (rdmsrl_safe(msr, &v)) { | ||
318 | WARN_ONCE(1, "mce: Unable to read msr %d!\n", msr); | ||
319 | /* | ||
320 | * Return zero in case the access faulted. This should | ||
321 | * not happen normally but can happen if the CPU does | ||
322 | * something weird, or if the code is buggy. | ||
323 | */ | ||
324 | v = 0; | ||
325 | } | ||
326 | |||
315 | return v; | 327 | return v; |
316 | } | 328 | } |
317 | 329 | ||
@@ -319,6 +331,7 @@ static void mce_wrmsrl(u32 msr, u64 v) | |||
319 | { | 331 | { |
320 | if (__get_cpu_var(injectm).finished) { | 332 | if (__get_cpu_var(injectm).finished) { |
321 | int offset = msr_to_offset(msr); | 333 | int offset = msr_to_offset(msr); |
334 | |||
322 | if (offset >= 0) | 335 | if (offset >= 0) |
323 | *(u64 *)((char *)&__get_cpu_var(injectm) + offset) = v; | 336 | *(u64 *)((char *)&__get_cpu_var(injectm) + offset) = v; |
324 | return; | 337 | return; |
@@ -415,7 +428,7 @@ static inline void mce_get_rip(struct mce *m, struct pt_regs *regs) | |||
415 | m->ip = mce_rdmsrl(rip_msr); | 428 | m->ip = mce_rdmsrl(rip_msr); |
416 | } | 429 | } |
417 | 430 | ||
418 | #ifdef CONFIG_X86_LOCAL_APIC | 431 | #ifdef CONFIG_X86_LOCAL_APIC |
419 | /* | 432 | /* |
420 | * Called after interrupts have been reenabled again | 433 | * Called after interrupts have been reenabled again |
421 | * when a MCE happened during an interrupts off region | 434 | * when a MCE happened during an interrupts off region |
@@ -1172,6 +1185,7 @@ static int mce_banks_init(void) | |||
1172 | return -ENOMEM; | 1185 | return -ENOMEM; |
1173 | for (i = 0; i < banks; i++) { | 1186 | for (i = 0; i < banks; i++) { |
1174 | struct mce_bank *b = &mce_banks[i]; | 1187 | struct mce_bank *b = &mce_banks[i]; |
1188 | |||
1175 | b->ctl = -1ULL; | 1189 | b->ctl = -1ULL; |
1176 | b->init = 1; | 1190 | b->init = 1; |
1177 | } | 1191 | } |
@@ -1203,6 +1217,7 @@ static int __cpuinit mce_cap_init(void) | |||
1203 | banks = b; | 1217 | banks = b; |
1204 | if (!mce_banks) { | 1218 | if (!mce_banks) { |
1205 | int err = mce_banks_init(); | 1219 | int err = mce_banks_init(); |
1220 | |||
1206 | if (err) | 1221 | if (err) |
1207 | return err; | 1222 | return err; |
1208 | } | 1223 | } |
@@ -1237,6 +1252,7 @@ static void mce_init(void) | |||
1237 | 1252 | ||
1238 | for (i = 0; i < banks; i++) { | 1253 | for (i = 0; i < banks; i++) { |
1239 | struct mce_bank *b = &mce_banks[i]; | 1254 | struct mce_bank *b = &mce_banks[i]; |
1255 | |||
1240 | if (!b->init) | 1256 | if (!b->init) |
1241 | continue; | 1257 | continue; |
1242 | wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl); | 1258 | wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl); |
@@ -1626,6 +1642,7 @@ static int mce_disable(void) | |||
1626 | 1642 | ||
1627 | for (i = 0; i < banks; i++) { | 1643 | for (i = 0; i < banks; i++) { |
1628 | struct mce_bank *b = &mce_banks[i]; | 1644 | struct mce_bank *b = &mce_banks[i]; |
1645 | |||
1629 | if (b->init) | 1646 | if (b->init) |
1630 | wrmsrl(MSR_IA32_MCx_CTL(i), 0); | 1647 | wrmsrl(MSR_IA32_MCx_CTL(i), 0); |
1631 | } | 1648 | } |
@@ -1911,6 +1928,7 @@ static void mce_disable_cpu(void *h) | |||
1911 | cmci_clear(); | 1928 | cmci_clear(); |
1912 | for (i = 0; i < banks; i++) { | 1929 | for (i = 0; i < banks; i++) { |
1913 | struct mce_bank *b = &mce_banks[i]; | 1930 | struct mce_bank *b = &mce_banks[i]; |
1931 | |||
1914 | if (b->init) | 1932 | if (b->init) |
1915 | wrmsrl(MSR_IA32_MCx_CTL(i), 0); | 1933 | wrmsrl(MSR_IA32_MCx_CTL(i), 0); |
1916 | } | 1934 | } |
@@ -1928,6 +1946,7 @@ static void mce_reenable_cpu(void *h) | |||
1928 | cmci_reenable(); | 1946 | cmci_reenable(); |
1929 | for (i = 0; i < banks; i++) { | 1947 | for (i = 0; i < banks; i++) { |
1930 | struct mce_bank *b = &mce_banks[i]; | 1948 | struct mce_bank *b = &mce_banks[i]; |
1949 | |||
1931 | if (b->init) | 1950 | if (b->init) |
1932 | wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl); | 1951 | wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl); |
1933 | } | 1952 | } |