Messages in this thread Patch in this message | | | From | Santosh Sivaraj <> | Subject | [v6 5/6] powerpc/mce: Handle UE event for memcpy_mcsafe | Date | Mon, 29 Jul 2019 09:30:10 +0530 |
| |
If we take a UE on one of the instructions with a fixup entry, set nip to continue execution at the fixup entry. Stop processing the event further or print it.
Based-on-patch-by: Reza Arbab <arbab@linux.ibm.com> Cc: Reza Arbab <arbab@linux.ibm.com> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com> Signed-off-by: Santosh Sivaraj <santosh@fossix.org> --- arch/powerpc/include/asm/mce.h | 4 +++- arch/powerpc/kernel/mce.c | 12 +++++++++++- arch/powerpc/kernel/mce_power.c | 15 +++++++++++++-- 3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index f3a6036b6bc0..e1931c8c2743 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h @@ -122,7 +122,8 @@ struct machine_check_event { enum MCE_UeErrorType ue_error_type:8; u8 effective_address_provided; u8 physical_address_provided; - u8 reserved_1[5]; + u8 ignore_event; + u8 reserved_1[4]; u64 effective_address; u64 physical_address; u8 reserved_2[8]; @@ -193,6 +194,7 @@ struct mce_error_info { enum MCE_Initiator initiator:8; enum MCE_ErrorClass error_class:8; bool sync_error; + bool ignore_event; }; #define MAX_MC_EVT 100 diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index e78c4f18ea0a..2df132fe3354 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c @@ -144,7 +144,9 @@ void save_mce_event(struct pt_regs *regs, long handled, if (phys_addr != ULONG_MAX) { mce->u.ue_error.physical_address_provided = true; mce->u.ue_error.physical_address = phys_addr; - machine_check_ue_event(mce); + mce->u.ue_error.ignore_event = mce_err->ignore_event; + if (!mce->u.ue_error.ignore_event) + machine_check_ue_event(mce); } } return; @@ -230,6 +232,14 @@ void machine_check_queue_event(void) if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) return; + /* + * Don't report this machine check because the caller has a asked us to + * ignore the event, it has a fixup handler which will do the + * appropriate error handling and reporting. + */ + if (evt.error_type == MCE_ERROR_TYPE_UE && evt.u.ue_error.ignore_event) + return; + index = __this_cpu_inc_return(mce_queue_count) - 1; /* If queue is full, just return for now. */ if (index >= MAX_MC_EVT) { diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index bed38a8e2e50..36ca45bbb273 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c @@ -11,6 +11,7 @@ #include <linux/types.h> #include <linux/ptrace.h> +#include <linux/extable.h> #include <asm/mmu.h> #include <asm/mce.h> #include <asm/machdep.h> @@ -18,6 +19,7 @@ #include <asm/pte-walk.h> #include <asm/sstep.h> #include <asm/exception-64s.h> +#include <asm/extable.h> /* * Convert an address related to an mm to a physical address. @@ -558,9 +560,18 @@ static int mce_handle_derror(struct pt_regs *regs, return 0; } -static long mce_handle_ue_error(struct pt_regs *regs) +static long mce_handle_ue_error(struct pt_regs *regs, + struct mce_error_info *mce_err) { long handled = 0; + const struct exception_table_entry *entry; + + entry = search_kernel_exception_table(regs->nip); + if (entry) { + mce_err->ignore_event = true; + regs->nip = extable_fixup(entry); + return 1; + } /* * On specific SCOM read via MMIO we may get a machine check @@ -593,7 +604,7 @@ static long mce_handle_error(struct pt_regs *regs, &phys_addr); if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE) - handled = mce_handle_ue_error(regs); + handled = mce_handle_ue_error(regs, &mce_err); save_mce_event(regs, handled, &mce_err, regs->nip, addr, phys_addr); -- 2.20.1
| |