Commit 1363875b authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

powerpc/64s: fix handling of non-synchronous machine checks

A synchronous machine check is an exception raised by the attempt to
execute the current instruction. If the error can't be corrected, it
can make sense to SIGBUS the currently running process.

In other cases, the error condition is not related to the current
instruction, so killing the current process is not the right thing to
do.

Today, all machine checks are MCE_SEV_ERROR_SYNC, so this has no
practical change. It will be used to handle POWER9 asynchronous
machine checks.
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 46f401c4
...@@ -395,7 +395,6 @@ static int opal_recover_mce(struct pt_regs *regs, ...@@ -395,7 +395,6 @@ static int opal_recover_mce(struct pt_regs *regs,
struct machine_check_event *evt) struct machine_check_event *evt)
{ {
int recovered = 0; int recovered = 0;
uint64_t ea = get_mce_fault_addr(evt);
if (!(regs->msr & MSR_RI)) { if (!(regs->msr & MSR_RI)) {
/* If MSR_RI isn't set, we cannot recover */ /* If MSR_RI isn't set, we cannot recover */
...@@ -404,26 +403,18 @@ static int opal_recover_mce(struct pt_regs *regs, ...@@ -404,26 +403,18 @@ static int opal_recover_mce(struct pt_regs *regs,
} else if (evt->disposition == MCE_DISPOSITION_RECOVERED) { } else if (evt->disposition == MCE_DISPOSITION_RECOVERED) {
/* Platform corrected itself */ /* Platform corrected itself */
recovered = 1; recovered = 1;
} else if (ea && !is_kernel_addr(ea)) { } else if (evt->severity == MCE_SEV_FATAL) {
/* Fatal machine check */
pr_err("Machine check interrupt is fatal\n");
recovered = 0;
} else if ((evt->severity == MCE_SEV_ERROR_SYNC) &&
(user_mode(regs) && !is_global_init(current))) {
/* /*
* Faulting address is not in kernel text. We should be fine.
* We need to find which process uses this address.
* For now, kill the task if we have received exception when * For now, kill the task if we have received exception when
* in userspace. * in userspace.
* *
* TODO: Queue up this address for hwpoisioning later. * TODO: Queue up this address for hwpoisioning later.
*/ */
if (user_mode(regs) && !is_global_init(current)) {
_exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
recovered = 1;
} else
recovered = 0;
} else if (user_mode(regs) && !is_global_init(current) &&
evt->severity == MCE_SEV_ERROR_SYNC) {
/*
* If we have received a synchronous error when in userspace
* kill the task.
*/
_exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip); _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
recovered = 1; recovered = 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment