aboutsummaryrefslogtreecommitdiff
path: root/core/mce.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/mce.c')
-rw-r--r--core/mce.c129
1 files changed, 119 insertions, 10 deletions
diff --git a/core/mce.c b/core/mce.c
index 3f50916..47674ab 100644
--- a/core/mce.c
+++ b/core/mce.c
@@ -65,6 +65,42 @@ static const struct mce_ierror_table mce_p9_ierror_table[] = {
"instruction fetch page table access to foreign address", },
{ 0 } };
+static const struct mce_ierror_table mce_p10_ierror_table[] = {
+{ 0x00000000081c0000, 0x0000000000040000,
+ MCE_INSNFETCH | MCE_MEMORY_ERROR | MCE_INVOLVED_EA,
+ "instruction fetch memory uncorrectable error", },
+{ 0x00000000081c0000, 0x0000000000080000,
+ MCE_INSNFETCH | MCE_SLB_ERROR | MCE_INVOLVED_EA,
+ "instruction fetch SLB parity error", },
+{ 0x00000000081c0000, 0x00000000000c0000,
+ MCE_INSNFETCH | MCE_SLB_ERROR | MCE_INVOLVED_EA,
+ "instruction fetch SLB multi-hit error", },
+{ 0x00000000081c0000, 0x0000000000100000,
+ MCE_INSNFETCH | MCE_INVOLVED_EA | MCE_ERAT_ERROR,
+ "instruction fetch ERAT multi-hit error", },
+{ 0x00000000081c0000, 0x0000000000140000,
+ MCE_INSNFETCH | MCE_INVOLVED_EA | MCE_TLB_ERROR,
+ "instruction fetch TLB multi-hit error", },
+{ 0x00000000081c0000, 0x0000000000180000,
+ MCE_INSNFETCH | MCE_MEMORY_ERROR | MCE_TABLE_WALK | MCE_INVOLVED_EA,
+ "instruction fetch page table access memory uncorrectable error", },
+{ 0x00000000081c0000, 0x00000000001c0000,
+ MCE_INSNFETCH | MCE_INVOLVED_EA,
+ "instruction fetch to control real address", },
+{ 0x00000000081c0000, 0x00000000080c0000,
+ MCE_INSNFETCH | MCE_INVOLVED_EA,
+ "instruction fetch real address error", },
+{ 0x00000000081c0000, 0x0000000008100000,
+ MCE_INSNFETCH | MCE_TABLE_WALK | MCE_INVOLVED_EA,
+ "instruction fetch page table access real address error", },
+{ 0x00000000081c0000, 0x0000000008140000,
+ MCE_LOADSTORE | MCE_IMPRECISE,
+ "store real address asynchronous error", },
+{ 0x00000000081c0000, 0x00000000081c0000,
+ MCE_INSNFETCH | MCE_TABLE_WALK | MCE_INVOLVED_EA,
+ "instruction fetch page table access to control real address", },
+{ 0 } };
+
struct mce_derror_table {
unsigned long dsisr_value;
uint64_t type;
@@ -113,6 +149,42 @@ static const struct mce_derror_table mce_p9_derror_table[] = {
"load/store to foreign address", },
{ 0 } };
+static const struct mce_derror_table mce_p10_derror_table[] = {
+{ 0x00008000,
+ MCE_LOADSTORE | MCE_MEMORY_ERROR,
+ "load/store memory uncorrectable error", },
+{ 0x00004000,
+ MCE_LOADSTORE | MCE_MEMORY_ERROR | MCE_TABLE_WALK | MCE_INVOLVED_EA,
+ "load/store page table access memory uncorrectable error", },
+{ 0x00000800,
+ MCE_LOADSTORE | MCE_INVOLVED_EA | MCE_ERAT_ERROR,
+ "load/store ERAT multi-hit error", },
+{ 0x00000400,
+ MCE_LOADSTORE | MCE_INVOLVED_EA | MCE_TLB_ERROR,
+ "load/store TLB multi-hit error", },
+{ 0x00000200,
+ MCE_TLBIE_ERROR,
+ "TLBIE or TLBIEL instruction programming error", },
+{ 0x00000100,
+ MCE_LOADSTORE | MCE_INVOLVED_EA | MCE_SLB_ERROR,
+ "load/store SLB parity error", },
+{ 0x00000080,
+ MCE_LOADSTORE | MCE_INVOLVED_EA | MCE_SLB_ERROR,
+ "load/store SLB multi-hit error", },
+{ 0x00000040,
+ MCE_LOADSTORE | MCE_INVOLVED_EA,
+ "load real address error", },
+{ 0x00000020,
+ MCE_LOADSTORE | MCE_TABLE_WALK,
+ "load/store page table access real address error", },
+{ 0x00000010,
+ MCE_LOADSTORE | MCE_TABLE_WALK,
+ "load/store page table access to control real address", },
+{ 0x00000008,
+ MCE_LOADSTORE,
+ "load/store to control real address", },
+{ 0 } };
+
static void decode_ierror(const struct mce_ierror_table table[],
uint64_t srr1,
uint64_t *type,
@@ -145,20 +217,11 @@ static void decode_derror(const struct mce_derror_table table[],
}
}
-void decode_mce(uint64_t srr0, uint64_t srr1,
+static void decode_mce_p9(uint64_t srr0, uint64_t srr1,
uint32_t dsisr, uint64_t dar,
uint64_t *type, const char **error_str,
uint64_t *address)
{
- *type = MCE_UNKNOWN;
- *error_str = "unknown error";
- *address = 0;
-
- if (proc_gen != proc_gen_p9) {
- *error_str = "unknown error (processor not supported)";
- return;
- }
-
/*
* On POWER9 DD2.1 and below, it's possible to get a machine check
* caused by a paste instruction where only DSISR bit 25 is set. This
@@ -198,3 +261,49 @@ void decode_mce(uint64_t srr0, uint64_t srr1,
*address = srr0;
}
}
+
+static void decode_mce_p10(uint64_t srr0, uint64_t srr1,
+ uint32_t dsisr, uint64_t dar,
+ uint64_t *type, const char **error_str,
+ uint64_t *address)
+{
+ /*
+ * Async machine check due to bad real address from store or foreign
+ * link time out comes with the load/store bit (PPC bit 42) set in
+ * SRR1, but the cause comes in SRR1 not DSISR. Clear bit 42 so we're
+ * directed to the ierror table so it will find the cause (which
+ * describes it correctly as a store error).
+ */
+ if (SRR1_MC_LOADSTORE(srr1) &&
+ (srr1 & 0x081c0000) == 0x08140000) {
+ srr1 &= ~PPC_BIT(42);
+ }
+
+ if (SRR1_MC_LOADSTORE(srr1)) {
+ decode_derror(mce_p10_derror_table, dsisr, type, error_str);
+ if (*type & MCE_INVOLVED_EA)
+ *address = dar;
+ } else {
+ decode_ierror(mce_p10_ierror_table, srr1, type, error_str);
+ if (*type & MCE_INVOLVED_EA)
+ *address = srr0;
+ }
+}
+
+void decode_mce(uint64_t srr0, uint64_t srr1,
+ uint32_t dsisr, uint64_t dar,
+ uint64_t *type, const char **error_str,
+ uint64_t *address)
+{
+ *type = MCE_UNKNOWN;
+ *error_str = "unknown error";
+ *address = 0;
+
+ if (proc_gen == proc_gen_p9) {
+ decode_mce_p9(srr0, srr1, dsisr, dar, type, error_str, address);
+ } else if (proc_gen == proc_gen_p10) {
+ decode_mce_p10(srr0, srr1, dsisr, dar, type, error_str, address);
+ } else {
+ *error_str = "unknown error (processor not supported)";
+ }
+}