aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>2011-06-07 21:57:46 -0400
committerBorislav Petkov <borislav.petkov@amd.com>2011-06-16 06:10:10 -0400
commitb8325c5b110d7ff460b79588e7e9afdcc73d5c3c (patch)
tree2ffdea5204b0319f71ad5a7793172c37ee08895f /arch
parent2b90e77eaee8809073db5cf43ac9795cc2054dc0 (diff)
x86, mce: Introduce mce_gather_info()
This patch introduces mce_gather_info() which is to be called at the beginning of error handling and gathers minimum error information from proper error registers (and saved registers). As the result of mce_get_rip() is integrated, unnecessary zeroing is removed. This also takes care of saving RIP which is required to make some decision about error severity for SRAR errors, instead of retrieving it later in the handler. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Acked-by: Tony Luck <tony.luck@intel.com> Link: http://lkml.kernel.org/r/4DEED71A.1060906@jp.fujitsu.com Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index e80750802d7f..a18287567865 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -369,6 +369,31 @@ static void mce_wrmsrl(u32 msr, u64 v)
369} 369}
370 370
371/* 371/*
372 * Collect all global (w.r.t. this processor) status about this machine
373 * check into our "mce" struct so that we can use it later to assess
374 * the severity of the problem as we read per-bank specific details.
375 */
376static inline void mce_gather_info(struct mce *m, struct pt_regs *regs)
377{
378 mce_setup(m);
379
380 m->mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
381 if (regs) {
382 /*
383 * Get the address of the instruction at the time of
384 * the machine check error.
385 */
386 if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) {
387 m->ip = regs->ip;
388 m->cs = regs->cs;
389 }
390 /* Use accurate RIP reporting if available. */
391 if (rip_msr)
392 m->ip = mce_rdmsrl(rip_msr);
393 }
394}
395
396/*
372 * Simple lockless ring to communicate PFNs from the exception handler with the 397 * Simple lockless ring to communicate PFNs from the exception handler with the
373 * process context work function. This is vastly simplified because there's 398 * process context work function. This is vastly simplified because there's
374 * only a single reader and a single writer. 399 * only a single reader and a single writer.
@@ -439,24 +464,6 @@ static void mce_schedule_work(void)
439 } 464 }
440} 465}
441 466
442/*
443 * Get the address of the instruction at the time of the machine check
444 * error.
445 */
446static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
447{
448
449 if (regs && (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV))) {
450 m->ip = regs->ip;
451 m->cs = regs->cs;
452 } else {
453 m->ip = 0;
454 m->cs = 0;
455 }
456 if (rip_msr)
457 m->ip = mce_rdmsrl(rip_msr);
458}
459
460DEFINE_PER_CPU(struct irq_work, mce_irq_work); 467DEFINE_PER_CPU(struct irq_work, mce_irq_work);
461 468
462static void mce_irq_work_cb(struct irq_work *entry) 469static void mce_irq_work_cb(struct irq_work *entry)
@@ -506,9 +513,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
506 513
507 percpu_inc(mce_poll_count); 514 percpu_inc(mce_poll_count);
508 515
509 mce_setup(&m); 516 mce_gather_info(&m, NULL);
510 517
511 m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
512 for (i = 0; i < banks; i++) { 518 for (i = 0; i < banks; i++) {
513 if (!mce_banks[i].ctl || !test_bit(i, *b)) 519 if (!mce_banks[i].ctl || !test_bit(i, *b))
514 continue; 520 continue;
@@ -907,9 +913,8 @@ void do_machine_check(struct pt_regs *regs, long error_code)
907 if (!banks) 913 if (!banks)
908 goto out; 914 goto out;
909 915
910 mce_setup(&m); 916 mce_gather_info(&m, regs);
911 917
912 m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
913 final = &__get_cpu_var(mces_seen); 918 final = &__get_cpu_var(mces_seen);
914 *final = m; 919 *final = m;
915 920
@@ -993,7 +998,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
993 if (severity == MCE_AO_SEVERITY && mce_usable_address(&m)) 998 if (severity == MCE_AO_SEVERITY && mce_usable_address(&m))
994 mce_ring_add(m.addr >> PAGE_SHIFT); 999 mce_ring_add(m.addr >> PAGE_SHIFT);
995 1000
996 mce_get_rip(&m, regs);
997 mce_log(&m); 1001 mce_log(&m);
998 1002
999 if (severity > worst) { 1003 if (severity > worst) {