dect
/
linux-2.6
Archived
13
0
Fork 0

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>
This commit is contained in:
Hidetoshi Seto 2011-06-08 10:57:46 +09:00 committed by Borislav Petkov
parent 2b90e77eae
commit b8325c5b11
1 changed files with 27 additions and 23 deletions

View File

@ -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) {