Skip to content

Commit

Permalink
powerpc/mce: Handle UE event for memcpy_mcsafe
Browse files Browse the repository at this point in the history
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.

Co-developed-by: Reza Arbab <arbab@linux.ibm.com>
Signed-off-by: Reza Arbab <arbab@linux.ibm.com>
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
Reviewed-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190820081352.8641-6-santosh@fossix.org
  • Loading branch information
Balbir Singh authored and Michael Ellerman committed Aug 21, 2019
1 parent 49ec917 commit 895e3dc
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 deletions.
4 changes: 3 additions & 1 deletion arch/powerpc/include/asm/mce.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions arch/powerpc/kernel/mce.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ 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;
mce->u.ue_error.ignore_event = mce_err->ignore_event;
machine_check_ue_event(mce);
}
}
Expand Down Expand Up @@ -266,8 +267,17 @@ static void machine_process_ue_event(struct work_struct *work)
/*
* This should probably queued elsewhere, but
* oh! well
*
* 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) {
if (evt->u.ue_error.ignore_event) {
__this_cpu_dec(mce_ue_count);
continue;
}

if (evt->u.ue_error.physical_address_provided) {
unsigned long pfn;

Expand Down Expand Up @@ -301,6 +311,12 @@ static void machine_check_process_queued_event(struct irq_work *work)
while (__this_cpu_read(mce_queue_count) > 0) {
index = __this_cpu_read(mce_queue_count) - 1;
evt = this_cpu_ptr(&mce_event_queue[index]);

if (evt->error_type == MCE_ERROR_TYPE_UE &&
evt->u.ue_error.ignore_event) {
__this_cpu_dec(mce_queue_count);
continue;
}
machine_check_print_event_info(evt, false, false);
__this_cpu_dec(mce_queue_count);
}
Expand Down
15 changes: 13 additions & 2 deletions arch/powerpc/kernel/mce_power.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@

#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/extable.h>
#include <asm/mmu.h>
#include <asm/mce.h>
#include <asm/machdep.h>
#include <asm/pgtable.h>
#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 PFN. NOTE: we are in real
Expand Down Expand Up @@ -565,9 +567,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
Expand Down Expand Up @@ -600,7 +611,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);

Expand Down

0 comments on commit 895e3dc

Please sign in to comment.