|
|
|
@ -112,6 +112,22 @@ static const char * const f15h_cu_mce_desc[] = { |
|
|
|
|
"PRB address parity error" |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const char * const fr_ex_mce_desc[] = { |
|
|
|
|
"CPU Watchdog timer expire", |
|
|
|
|
"Wakeup array dest tag", |
|
|
|
|
"AG payload array", |
|
|
|
|
"EX payload array", |
|
|
|
|
"IDRF array", |
|
|
|
|
"Retire dispatch queue", |
|
|
|
|
"Mapper checkpoint array", |
|
|
|
|
"Physical register file EX0 port", |
|
|
|
|
"Physical register file EX1 port", |
|
|
|
|
"Physical register file AG0 port", |
|
|
|
|
"Physical register file AG1 port", |
|
|
|
|
"Flag register file", |
|
|
|
|
"DE correctable error could not be corrected" |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static bool f12h_dc_mce(u16 ec, u8 xec) |
|
|
|
|
{ |
|
|
|
|
bool ret = false; |
|
|
|
@ -651,15 +667,26 @@ EXPORT_SYMBOL_GPL(amd_decode_nb_mce); |
|
|
|
|
|
|
|
|
|
static void amd_decode_fr_mce(struct mce *m) |
|
|
|
|
{ |
|
|
|
|
if (boot_cpu_data.x86 == 0xf || |
|
|
|
|
boot_cpu_data.x86 == 0x11) |
|
|
|
|
struct cpuinfo_x86 *c = &boot_cpu_data; |
|
|
|
|
u8 xec = (m->status >> 16) & xec_mask; |
|
|
|
|
|
|
|
|
|
if (c->x86 == 0xf || c->x86 == 0x11) |
|
|
|
|
goto wrong_fr_mce; |
|
|
|
|
|
|
|
|
|
/* we have only one error signature so match all fields at once. */ |
|
|
|
|
if ((m->status & 0xffff) == 0x0f0f) { |
|
|
|
|
pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (c->x86 != 0x15 && xec != 0x0) |
|
|
|
|
goto wrong_fr_mce; |
|
|
|
|
|
|
|
|
|
pr_emerg(HW_ERR "%s Error: ", |
|
|
|
|
(c->x86 == 0x15 ? "Execution Unit" : "FIROB")); |
|
|
|
|
|
|
|
|
|
if (xec == 0x0 || xec == 0xc) |
|
|
|
|
pr_cont("%s.\n", fr_ex_mce_desc[xec]); |
|
|
|
|
else if (xec < 0xd) |
|
|
|
|
pr_cont("%s parity error.\n", fr_ex_mce_desc[xec]); |
|
|
|
|
else |
|
|
|
|
goto wrong_fr_mce; |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
wrong_fr_mce: |
|
|
|
|
pr_emerg(HW_ERR "Corrupted FR MCE info?\n"); |
|
|
|
|