Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 292752
b: refs/heads/master
c: a8c321f
h: refs/heads/master
v: v3
  • Loading branch information
Tony Luck committed Jan 3, 2012
1 parent 5ba3dbd commit 85881de
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 43 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: af104e394e17e328df85c25a9e21448539725b67
refs/heads/master: a8c321fbf9aeced45519248e5901af8cbc240510
95 changes: 53 additions & 42 deletions trunk/arch/x86/kernel/cpu/mcheck/mce.c
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,9 @@ void do_machine_check(struct pt_regs *regs, long error_code)
barrier();

/*
* When no restart IP must always kill or panic.
* When no restart IP might need to kill or panic.
* Assume the worst for now, but if we find the
* severity is MCE_AR_SEVERITY we have other options.
*/
if (!(m.mcgstatus & MCG_STATUS_RIPV))
kill_it = 1;
Expand Down Expand Up @@ -1036,12 +1038,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
continue;
}

/*
* Kill on action required.
*/
if (severity == MCE_AR_SEVERITY)
kill_it = 1;

mce_read_aux(&m, i);

/*
Expand All @@ -1062,6 +1058,9 @@ void do_machine_check(struct pt_regs *regs, long error_code)
}
}

/* mce_clear_state will clear *final, save locally for use later */
m = *final;

if (!no_way_out)
mce_clear_state(toclear);

Expand All @@ -1073,27 +1072,22 @@ void do_machine_check(struct pt_regs *regs, long error_code)
no_way_out = worst >= MCE_PANIC_SEVERITY;

/*
* If we have decided that we just CAN'T continue, and the user
* has not set tolerant to an insane level, give up and die.
*
* This is mainly used in the case when the system doesn't
* support MCE broadcasting or it has been disabled.
* At insane "tolerant" levels we take no action. Otherwise
* we only die if we have no other choice. For less serious
* issues we try to recover, or limit damage to the current
* process.
*/
if (no_way_out && tolerant < 3)
mce_panic("Fatal machine check on current CPU", final, msg);

/*
* If the error seems to be unrecoverable, something should be
* done. Try to kill as little as possible. If we can kill just
* one task, do that. If the user has set the tolerance very
* high, don't try to do anything at all.
*/

if (kill_it && tolerant < 3)
force_sig(SIGBUS, current);

/* notify userspace ASAP */
set_thread_flag(TIF_MCE_NOTIFY);
if (tolerant < 3) {
if (no_way_out)
mce_panic("Fatal machine check on current CPU", &m, msg);
if (worst == MCE_AR_SEVERITY) {
/* schedule action before return to userland */
mce_save_info(m.addr);
set_thread_flag(TIF_MCE_NOTIFY);
} else if (kill_it) {
force_sig(SIGBUS, current);
}
}

if (worst > 0)
mce_report_event(regs);
Expand All @@ -1107,6 +1101,8 @@ EXPORT_SYMBOL_GPL(do_machine_check);
#ifndef CONFIG_MEMORY_FAILURE
int memory_failure(unsigned long pfn, int vector, int flags)
{
/* mce_severity() should not hand us an ACTION_REQUIRED error */
BUG_ON(flags & MF_ACTION_REQUIRED);
printk(KERN_ERR "Uncorrected memory error in page 0x%lx ignored\n"
"Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n", pfn);

Expand All @@ -1115,27 +1111,44 @@ int memory_failure(unsigned long pfn, int vector, int flags)
#endif

/*
* Called after mce notification in process context. This code
* is allowed to sleep. Call the high level VM handler to process
* any corrupted pages.
* Assume that the work queue code only calls this one at a time
* per CPU.
* Note we don't disable preemption, so this code might run on the wrong
* CPU. In this case the event is picked up by the scheduled work queue.
* This is merely a fast path to expedite processing in some common
* cases.
* Called in process context that interrupted by MCE and marked with
* TIF_MCE_NOTIFY, just before returning to erroneous userland.
* This code is allowed to sleep.
* Attempt possible recovery such as calling the high level VM handler to
* process any corrupted pages, and kill/signal current process if required.
* Action required errors are handled here.
*/
void mce_notify_process(void)
{
unsigned long pfn;
mce_notify_irq();
while (mce_ring_get(&pfn))
memory_failure(pfn, MCE_VECTOR, 0);
struct mce_info *mi = mce_find_info();

if (!mi)
mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL);
pfn = mi->paddr >> PAGE_SHIFT;

clear_thread_flag(TIF_MCE_NOTIFY);

pr_err("Uncorrected hardware memory error in user-access at %llx",
mi->paddr);
if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0) {
pr_err("Memory error not recovered");
force_sig(SIGBUS, current);
}
mce_clear_info(mi);
}

/*
* Action optional processing happens here (picking up
* from the list of faulting pages that do_machine_check()
* placed into the "ring").
*/
static void mce_process_work(struct work_struct *dummy)
{
mce_notify_process();
unsigned long pfn;

while (mce_ring_get(&pfn))
memory_failure(pfn, MCE_VECTOR, 0);
}

#ifdef CONFIG_X86_MCE_INTEL
Expand Down Expand Up @@ -1225,8 +1238,6 @@ int mce_notify_irq(void)
/* Not more than two messages every minute */
static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2);

clear_thread_flag(TIF_MCE_NOTIFY);

if (test_and_clear_bit(0, &mce_need_notify)) {
/* wake processes polling /dev/mcelog */
wake_up_interruptible(&mce_chrdev_wait);
Expand Down

0 comments on commit 85881de

Please sign in to comment.