diff options
author | Balbir Singh <bsingharora@gmail.com> | 2017-09-29 14:26:54 +1000 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2017-10-16 23:12:01 +1100 |
commit | 01eaac2b0591f7114d9de5cc65c88352de0daca6 (patch) | |
tree | ca7ded1770aab2ca424af7d0da1caec909231af0 /arch/powerpc/kernel | |
parent | ba41e1e1ccb9771ce41a3b8e2121f95486e76ac9 (diff) | |
download | op-kernel-dev-01eaac2b0591f7114d9de5cc65c88352de0daca6.zip op-kernel-dev-01eaac2b0591f7114d9de5cc65c88352de0daca6.tar.gz |
powerpc/mce: Hookup ierror (instruction) UE errors
Hookup instruction errors (UE) for memory offling via memory_failure()
in a manner similar to load/store errors (derror). Since we have access
to the NIP, the conversion is a one step process in this case.
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/mce_power.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index e61b80e..82cabfc 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c @@ -488,7 +488,8 @@ static int mce_find_instr_ea_and_pfn(struct pt_regs *regs, uint64_t *addr, static int mce_handle_ierror(struct pt_regs *regs, const struct mce_ierror_table table[], - struct mce_error_info *mce_err, uint64_t *addr) + struct mce_error_info *mce_err, uint64_t *addr, + uint64_t *phys_addr) { uint64_t srr1 = regs->msr; int handled = 0; @@ -540,8 +541,22 @@ static int mce_handle_ierror(struct pt_regs *regs, } mce_err->severity = table[i].severity; mce_err->initiator = table[i].initiator; - if (table[i].nip_valid) + if (table[i].nip_valid) { *addr = regs->nip; + if (mce_err->severity == MCE_SEV_ERROR_SYNC && + table[i].error_type == MCE_ERROR_TYPE_UE) { + unsigned long pfn; + + if (get_paca()->in_mce < MAX_MCE_DEPTH) { + pfn = addr_to_pfn(regs, regs->nip); + if (pfn != ULONG_MAX) { + *phys_addr = + (pfn << PAGE_SHIFT); + handled = 1; + } + } + } + } return handled; } @@ -676,7 +691,8 @@ static long mce_handle_error(struct pt_regs *regs, handled = mce_handle_derror(regs, dtable, &mce_err, &addr, &phys_addr); else - handled = mce_handle_ierror(regs, itable, &mce_err, &addr); + handled = mce_handle_ierror(regs, itable, &mce_err, &addr, + &phys_addr); if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE) handled = mce_handle_ue_error(regs); |