|
@@ -368,6 +368,31 @@ static void mce_wrmsrl(u32 msr, u64 v)
|
|
|
wrmsrl(msr, v);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Collect all global (w.r.t. this processor) status about this machine
|
|
|
+ * check into our "mce" struct so that we can use it later to assess
|
|
|
+ * the severity of the problem as we read per-bank specific details.
|
|
|
+ */
|
|
|
+static inline void mce_gather_info(struct mce *m, struct pt_regs *regs)
|
|
|
+{
|
|
|
+ mce_setup(m);
|
|
|
+
|
|
|
+ m->mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
|
|
|
+ if (regs) {
|
|
|
+ /*
|
|
|
+ * Get the address of the instruction at the time of
|
|
|
+ * the machine check error.
|
|
|
+ */
|
|
|
+ if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) {
|
|
|
+ m->ip = regs->ip;
|
|
|
+ m->cs = regs->cs;
|
|
|
+ }
|
|
|
+ /* Use accurate RIP reporting if available. */
|
|
|
+ if (rip_msr)
|
|
|
+ m->ip = mce_rdmsrl(rip_msr);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Simple lockless ring to communicate PFNs from the exception handler with the
|
|
|
* process context work function. This is vastly simplified because there's
|
|
@@ -439,24 +464,6 @@ static void mce_schedule_work(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Get the address of the instruction at the time of the machine check
|
|
|
- * error.
|
|
|
- */
|
|
|
-static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
|
|
|
-{
|
|
|
-
|
|
|
- if (regs && (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV))) {
|
|
|
- m->ip = regs->ip;
|
|
|
- m->cs = regs->cs;
|
|
|
- } else {
|
|
|
- m->ip = 0;
|
|
|
- m->cs = 0;
|
|
|
- }
|
|
|
- if (rip_msr)
|
|
|
- m->ip = mce_rdmsrl(rip_msr);
|
|
|
-}
|
|
|
-
|
|
|
DEFINE_PER_CPU(struct irq_work, mce_irq_work);
|
|
|
|
|
|
static 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)
|
|
|
|
|
|
percpu_inc(mce_poll_count);
|
|
|
|
|
|
- mce_setup(&m);
|
|
|
+ mce_gather_info(&m, NULL);
|
|
|
|
|
|
- m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
|
|
|
for (i = 0; i < banks; i++) {
|
|
|
if (!mce_banks[i].ctl || !test_bit(i, *b))
|
|
|
continue;
|
|
@@ -907,9 +913,8 @@ void do_machine_check(struct pt_regs *regs, long error_code)
|
|
|
if (!banks)
|
|
|
goto out;
|
|
|
|
|
|
- mce_setup(&m);
|
|
|
+ mce_gather_info(&m, regs);
|
|
|
|
|
|
- m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
|
|
|
final = &__get_cpu_var(mces_seen);
|
|
|
*final = m;
|
|
|
|
|
@@ -993,7 +998,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
|
|
|
if (severity == MCE_AO_SEVERITY && mce_usable_address(&m))
|
|
|
mce_ring_add(m.addr >> PAGE_SHIFT);
|
|
|
|
|
|
- mce_get_rip(&m, regs);
|
|
|
mce_log(&m);
|
|
|
|
|
|
if (severity > worst) {
|