diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h
index f97d8cb..36db6b0 100644
--- a/arch/powerpc/include/asm/mce.h
+++ b/arch/powerpc/include/asm/mce.h
@@ -23,6 +23,7 @@
#define __ASM_PPC64_MCE_H__
#include <linux/bitops.h>
+#include <asm/opal.h>
/*
* Machine Check bits on power7 and power8
@@ -66,109 +67,6 @@
#define P8_DSISR_MC_SLB_ERRORS (P7_DSISR_MC_SLB_ERRORS | \
P8_DSISR_MC_ERAT_MULTIHIT_SEC)
-enum MCE_Version {
- MCE_V1 = 1,
-};
-
-enum MCE_Severity {
- MCE_SEV_NO_ERROR = 0,
- MCE_SEV_WARNING = 1,
- MCE_SEV_ERROR_SYNC = 2,
- MCE_SEV_FATAL = 3,
-};
-
-enum MCE_Disposition {
- MCE_DISPOSITION_RECOVERED = 0,
- MCE_DISPOSITION_NOT_RECOVERED = 1,
-};
-
-enum MCE_Initiator {
- MCE_INITIATOR_UNKNOWN = 0,
- MCE_INITIATOR_CPU = 1,
-};
-
-enum MCE_ErrorType {
- MCE_ERROR_TYPE_UNKNOWN = 0,
- MCE_ERROR_TYPE_UE = 1,
- MCE_ERROR_TYPE_SLB = 2,
- MCE_ERROR_TYPE_ERAT = 3,
- MCE_ERROR_TYPE_TLB = 4,
-};
-
-enum MCE_UeErrorType {
- MCE_UE_ERROR_INDETERMINATE = 0,
- MCE_UE_ERROR_IFETCH = 1,
- MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
- MCE_UE_ERROR_LOAD_STORE = 3,
- MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
-};
-
-enum MCE_SlbErrorType {
- MCE_SLB_ERROR_INDETERMINATE = 0,
- MCE_SLB_ERROR_PARITY = 1,
- MCE_SLB_ERROR_MULTIHIT = 2,
-};
-
-enum MCE_EratErrorType {
- MCE_ERAT_ERROR_INDETERMINATE = 0,
- MCE_ERAT_ERROR_PARITY = 1,
- MCE_ERAT_ERROR_MULTIHIT = 2,
-};
-
-enum MCE_TlbErrorType {
- MCE_TLB_ERROR_INDETERMINATE = 0,
- MCE_TLB_ERROR_PARITY = 1,
- MCE_TLB_ERROR_MULTIHIT = 2,
-};
-
-struct machine_check_event {
- enum MCE_Version version:8; /* 0x00 */
- uint8_t in_use; /* 0x01 */
- enum MCE_Severity severity:8; /* 0x02 */
- enum MCE_Initiator initiator:8; /* 0x03 */
- enum MCE_ErrorType error_type:8; /* 0x04 */
- enum MCE_Disposition disposition:8; /* 0x05 */
- uint8_t reserved_1[2]; /* 0x06 */
- uint64_t gpr3; /* 0x08 */
- uint64_t srr0; /* 0x10 */
- uint64_t srr1; /* 0x18 */
- union { /* 0x20 */
- struct {
- enum MCE_UeErrorType ue_error_type:8;
- uint8_t effective_address_provided;
- uint8_t physical_address_provided;
- uint8_t reserved_1[5];
- uint64_t effective_address;
- uint64_t physical_address;
- uint8_t reserved_2[8];
- } ue_error;
-
- struct {
- enum MCE_SlbErrorType slb_error_type:8;
- uint8_t effective_address_provided;
- uint8_t reserved_1[6];
- uint64_t effective_address;
- uint8_t reserved_2[16];
- } slb_error;
-
- struct {
- enum MCE_EratErrorType erat_error_type:8;
- uint8_t effective_address_provided;
- uint8_t reserved_1[6];
- uint64_t effective_address;
- uint8_t reserved_2[16];
- } erat_error;
-
- struct {
- enum MCE_TlbErrorType tlb_error_type:8;
- uint8_t effective_address_provided;
- uint8_t reserved_1[6];
- uint64_t effective_address;
- uint8_t reserved_2[16];
- } tlb_error;
- } u;
-};
-
struct mce_error_info {
enum MCE_ErrorType error_type:8;
union {@@ -189,10 +87,10 @@ struct mce_error_info {
extern void save_mce_event(struct pt_regs *regs, long handled,
struct mce_error_info *mce_err, uint64_t nip,
uint64_t addr);
-extern int get_mce_event(struct machine_check_event *mce, bool release);
+extern int get_mce_event(struct OpalMachineCheckEvent *mce, bool release);
extern void release_mce_event(void);
extern void machine_check_queue_event(void);
-extern void machine_check_print_event_info(struct machine_check_event *evt);
-extern uint64_t get_mce_fault_addr(struct machine_check_event *evt);
+extern void machine_check_print_event_info(struct OpalMachineCheckEvent *evt);
+extern uint64_t get_mce_fault_addr(struct OpalMachineCheckEvent *evt);
#endif /* __ASM_PPC64_MCE_H__ */diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 0e2e57b..6851be6 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -585,6 +585,182 @@ struct OpalHMIEvent {
} u;
};
+/* Machine Check event */
+enum MCE_Version {
+ MCE_V1 = 1,
+};
+
+enum MCE_Severity {
+ MCE_SEV_NO_ERROR = 0,
+ MCE_SEV_WARNING = 1,
+ MCE_SEV_ERROR_SYNC = 2,
+ MCE_SEV_FATAL = 3,
+ MCE_SEV_ERROR_ASYNC = 4,
+};
+
+enum MCE_Disposition {
+ MCE_DISPOSITION_RECOVERED = 0,
+ MCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum MCE_Initiator {
+ MCE_INITIATOR_UNKNOWN = 0,
+ MCE_INITIATOR_CPU = 1,
+};
+
+enum MCE_ErrorType {
+ MCE_ERROR_TYPE_UNKNOWN = 0,
+ MCE_ERROR_TYPE_UE = 1,
+ MCE_ERROR_TYPE_SLB = 2,
+ MCE_ERROR_TYPE_ERAT = 3,
+ MCE_ERROR_TYPE_TLB = 4,
+ MCE_ERROR_TYPE_NEST = 5,
+ MCE_ERROR_TYPE_CRESP = 6,
+ MCE_ERROR_TYPE_FSPACE = 7,
+ MCE_ERROR_TYPE_ASYNC = 8,
+};
+
+enum MCE_UeErrorType {
+ MCE_UE_ERROR_INDETERMINATE = 0,
+ MCE_UE_ERROR_IFETCH = 1,
+ MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+ MCE_UE_ERROR_LOAD_STORE = 3,
+ MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum MCE_SlbErrorType {
+ MCE_SLB_ERROR_INDETERMINATE = 0,
+ MCE_SLB_ERROR_PARITY = 1,
+ MCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum MCE_EratErrorType {
+ MCE_ERAT_ERROR_INDETERMINATE = 0,
+ MCE_ERAT_ERROR_PARITY = 1,
+ MCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum MCE_TlbErrorType {
+ MCE_TLB_ERROR_INDETERMINATE = 0,
+ MCE_TLB_ERROR_PARITY = 1,
+ MCE_TLB_ERROR_MULTIHIT = 2,
+ MCE_TLB_ERROR_TLBIEL_PROG_ERROR = 3,
+};
+
+enum MCE_NestErrorType {
+ MCE_NEST_ERROR_ABRT_IFETCH = 0,
+ MCE_NEST_ERROR_ABRT_IFETCH_TABLEWALK = 1,
+ MCE_NEST_ERROR_ABRT_LOAD = 2,
+ MCE_NEST_ERROR_ABRT_LOAD_TABLEWALK = 3,
+};
+
+enum MCE_CrespErrorType {
+ MCE_CRESP_ERROR_BAD_RADDR_IFETCH = 0,
+ MCE_CRESP_ERROR_BAD_RADDR_IFETCH_TABLEWALK = 1,
+ MCE_CRESP_ERROR_BAD_RADDR_LOAD = 2,
+ MCE_CRESP_ERROR_BAD_RADDR_LOAD_TABLEWALK = 3,
+};
+
+enum MCE_FspaceErrorType {
+ MCE_FSPACE_ERROR_IFETCH = 0,
+ MCE_FSPACE_ERROR_IFETCH_TABLEWALK = 1,
+ MCE_FSPACE_ERROR_RADDR_TRANSLATION = 2,
+ MCE_FSPACE_ERROR_RADDR_LOAD = 3,
+};
+
+enum MCE_AsyncErrorType {
+ MCE_ASYNC_ERROR_REAL_ADDR_STORE = 0,
+ MCE_ASYNC_ERROR_NEST_ABRT_STORE = 1,
+};
+
+struct OpalMachineCheckEvent {
+ uint8_t version; /* 0x00 */
+ uint8_t in_use; /* 0x01 */
+ uint8_t severity; /* 0x02 */
+ uint8_t initiator; /* 0x03 */
+ uint8_t error_type; /* 0x04 */
+ uint8_t disposition; /* 0x05 */
+ uint8_t reserved_1[2]; /* 0x06 */
+ uint64_t gpr3; /* 0x08 */
+ uint64_t srr0; /* 0x10 */
+ uint64_t srr1; /* 0x18 */
+
+ union { /* 0x20 */
+ /* Next 32 bytes contains specific information of MCE error. */
+ struct {
+ /* enum MCE_UeErrorType */
+ uint8_t ue_error_type;
+ uint8_t effective_address_provided;
+ uint8_t physical_address_provided;
+ uint8_t reserved_1[5];
+ uint64_t effective_address;
+ uint64_t physical_address;
+ uint8_t reserved_2[8];
+ } ue_error;
+
+ struct {
+ /* enum MCE_SlbErrorType */
+ uint8_t slb_error_type;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } slb_error;
+
+ struct {
+ /* enum MCE_EratErrorType */
+ uint8_t erat_error_type;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } erat_error;
+
+ struct {
+ /* enum MCE_TlbErrorType */
+ uint8_t tlb_error_type;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } tlb_error;
+
+ struct {
+ /* enum MCE_NestErrorType */
+ uint8_t nest_error_type;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } nest_error;
+
+ struct {
+ /* enum MCE_CrespErrorType */
+ uint8_t cresp_error_type;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } cresp_error;
+
+ struct {
+ /* enum MCE_FspaceErrorType */
+ uint8_t fspace_error_type;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } fspace_error;
+
+ struct {
+ /* enum MCE_AsyncErrorType */
+ uint8_t async_error_type;
+ uint8_t reserved_1[7];
+ uint8_t reserved_2[24];
+ } async_error;
+ } u;
+};
+
enum {
OPAL_P7IOC_DIAG_TYPE_NONE = 0,
OPAL_P7IOC_DIAG_TYPE_RGC = 1,diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index c6923ff..51a7c64 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -30,18 +30,18 @@
#include <asm/mce.h>
static DEFINE_PER_CPU(int, mce_nest_count);
-static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event);
+static DEFINE_PER_CPU(struct OpalMachineCheckEvent[MAX_MC_EVT], mce_event);
/* Queue for delayed MCE events. */
static DEFINE_PER_CPU(int, mce_queue_count);
-static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue);
+static DEFINE_PER_CPU(struct OpalMachineCheckEvent[MAX_MC_EVT], mce_event_queue);
static void machine_check_process_queued_event(struct irq_work *work);
static struct irq_work mce_event_process_work = {
.func = machine_check_process_queued_event,
};
-static void mce_set_error_info(struct machine_check_event *mce,
+static void mce_set_error_info(struct OpalMachineCheckEvent *mce,
struct mce_error_info *mce_err)
{
mce->error_type = mce_err->error_type;@@ -73,7 +73,7 @@ void save_mce_event(struct pt_regs *regs, long handled,
uint64_t nip, uint64_t addr)
{
int index = __this_cpu_inc_return(mce_nest_count) - 1;
- struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]);
+ struct OpalMachineCheckEvent *mce = this_cpu_ptr(&mce_event[index]);
/*
* Return if we don't have enough space to log mce event.@@ -139,10 +139,10 @@ void save_mce_event(struct pt_regs *regs, long handled,
* preemption will not be scheduled until ret_from_expect() routine
* is called.
*/
-int get_mce_event(struct machine_check_event *mce, bool release)
+int get_mce_event(struct OpalMachineCheckEvent *mce, bool release)
{
int index = __this_cpu_read(mce_nest_count) - 1;
- struct machine_check_event *mc_evt;
+ struct OpalMachineCheckEvent *mc_evt;
int ret = 0;
/* Sanity check */@@ -177,7 +177,7 @@ void release_mce_event(void)
void machine_check_queue_event(void)
{
int index;
- struct machine_check_event evt;
+ struct OpalMachineCheckEvent evt;
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
return;@@ -214,7 +214,7 @@ static void machine_check_process_queued_event(struct irq_work *work)
}
}
-void machine_check_print_event_info(struct machine_check_event *evt)
+void machine_check_print_event_info(struct OpalMachineCheckEvent *evt)
{
const char *level, *sevstr, *subtype;
static const char *mc_ue_types[] = {@@ -322,7 +322,7 @@ void machine_check_print_event_info(struct machine_check_event *evt)
}
}
-uint64_t get_mce_fault_addr(struct machine_check_event *evt)
+uint64_t get_mce_fault_addr(struct OpalMachineCheckEvent *evt)
{
switch (evt->error_type) {
case MCE_ERROR_TYPE_UE:diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 2822935..3eb0e94 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -392,7 +392,7 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
}
static int opal_recover_mce(struct pt_regs *regs,
- struct machine_check_event *evt)
+ struct OpalMachineCheckEvent *evt)
{
int recovered = 0;
uint64_t ea = get_mce_fault_addr(evt);@@ -432,7 +432,7 @@ static int opal_recover_mce(struct pt_regs *regs,
int opal_machine_check(struct pt_regs *regs)
{
- struct machine_check_event evt;
+ struct OpalMachineCheckEvent evt;
int ret;
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))