[RFC PATCH 1/7] powerpc/book3s: Move machine check event structure to opal-api.h
Mahesh J Salgaonkar
mahesh at linux.vnet.ibm.com
Tue Feb 21 12:51:56 AEDT 2017
From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Going forward from Power9, linux would take firmware's (OPAL) help to
exract MCE error reason. OPAL will now handle all chip specific processing
to extract the error reason and send high level information through this
machine check event structure. Hence this structure is now an ABI.
No functionality change.
Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
arch/powerpc/include/asm/mce.h | 110 +--------------------
arch/powerpc/include/asm/opal-api.h | 176 +++++++++++++++++++++++++++++++++
arch/powerpc/kernel/mce.c | 18 ++-
arch/powerpc/platforms/powernv/opal.c | 4 -
4 files changed, 191 insertions(+), 117 deletions(-)
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))
More information about the Linuxppc-dev
mailing list