aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2011-12-13 12:48:13 -0500
committerTony Luck <tony.luck@intel.com>2012-01-03 15:06:45 -0500
commit85f92694affa7dba7f1978666a69552b5dfc628e (patch)
tree613ac35ef99bc2500add551cb5e5c405d4ca1894 /arch
parent7329bbeb92740f35d64a8860ae7837ff4db27fe0 (diff)
x86/mce: Create helper function to save addr/misc when needed
The MCI_STATUS_MISCV and MCI_STATUS_ADDRV bits in the bank status registers define whether the MISC and ADDR registers respectively contain valid data - provide a helper function to check these bits and read the registers when needed. In addition, processors that support software error recovery (as indicated by the MCG_SER_P bit in the MCG_CAP register) may include some undefined bits in the ADDR register - mask these out. Acked-by: Borislav Petkov <bp@amd64.org> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 1a08ce5f345f..2f1c200f05e6 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -492,6 +492,27 @@ static void mce_report_event(struct pt_regs *regs)
492 irq_work_queue(&__get_cpu_var(mce_irq_work)); 492 irq_work_queue(&__get_cpu_var(mce_irq_work));
493} 493}
494 494
495/*
496 * Read ADDR and MISC registers.
497 */
498static void mce_read_aux(struct mce *m, int i)
499{
500 if (m->status & MCI_STATUS_MISCV)
501 m->misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i));
502 if (m->status & MCI_STATUS_ADDRV) {
503 m->addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i));
504
505 /*
506 * Mask the reported address by the reported granularity.
507 */
508 if (mce_ser && (m->status & MCI_STATUS_MISCV)) {
509 u8 shift = MCI_MISC_ADDR_LSB(m->misc);
510 m->addr >>= shift;
511 m->addr <<= shift;
512 }
513 }
514}
515
495DEFINE_PER_CPU(unsigned, mce_poll_count); 516DEFINE_PER_CPU(unsigned, mce_poll_count);
496 517
497/* 518/*
@@ -542,10 +563,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
542 (m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC))) 563 (m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC)))
543 continue; 564 continue;
544 565
545 if (m.status & MCI_STATUS_MISCV) 566 mce_read_aux(&m, i);
546 m.misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i));
547 if (m.status & MCI_STATUS_ADDRV)
548 m.addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i));
549 567
550 if (!(flags & MCP_TIMESTAMP)) 568 if (!(flags & MCP_TIMESTAMP))
551 m.tsc = 0; 569 m.tsc = 0;
@@ -981,10 +999,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
981 if (severity == MCE_AR_SEVERITY) 999 if (severity == MCE_AR_SEVERITY)
982 kill_it = 1; 1000 kill_it = 1;
983 1001
984 if (m.status & MCI_STATUS_MISCV) 1002 mce_read_aux(&m, i);
985 m.misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i));
986 if (m.status & MCI_STATUS_ADDRV)
987 m.addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i));
988 1003
989 /* 1004 /*
990 * Action optional error. Queue address for later processing. 1005 * Action optional error. Queue address for later processing.