edac: cortex_arm64: Print esr register information

Cortex A53 & A57 processors store information about the type of parity
error in esr_el1 for certain types of errors. Print out this information
in the interrupt handler.

Print the cpumerrsr, l2merrsr, and esr register in all cases.

Change-Id: I508560740ee4f6937b5137cb33ad21216f86649f
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
This commit is contained in:
Patrick Daly 2014-11-05 19:33:40 -08:00
parent 974367a37a
commit ab503cecbe
1 changed files with 59 additions and 11 deletions

View File

@ -25,12 +25,14 @@
#include <linux/workqueue.h>
#include <linux/percpu.h>
#include <soc/qcom/cti-pmu-irq.h>
#include <linux/msm_rtb.h>
#include <asm/cputype.h>
#include <asm/esr.h>
#include "edac_core.h"
#define A53_CPMUERRSR_FATAL(a) ((a) & (1 << 63))
#define A53_CPUMERRSR_FATAL(a) ((a) & (1LL << 63))
#define A53_CPUMERRSR_OTHER(a) (((a) >> 40) & 0xff)
#define A53_CPUMERRSR_REPT(a) (((a) >> 32) & 0xff)
#define A53_CPUMERRSR_VALID(a) ((a) & (1 << 31))
@ -38,7 +40,7 @@
#define A53_CPUMERRSR_CPUID(a) (((a) >> 18) & 0x07)
#define A53_CPUMERRSR_ADDR(a) ((a) & 0xfff)
#define A53_L2MERRSR_FATAL(a) ((a) & (1 << 63))
#define A53_L2MERRSR_FATAL(a) ((a) & (1LL << 63))
#define A53_L2MERRSR_OTHER(a) (((a) >> 40) & 0xff)
#define A53_L2MERRSR_REPT(a) (((a) >> 32) & 0xff)
#define A53_L2MERRSR_VALID(a) ((a) & (1 << 31))
@ -46,7 +48,7 @@
#define A53_L2MERRSR_CPUID(a) (((a) >> 18) & 0x0f)
#define A53_L2MERRSR_INDEX(a) (((a) >> 3) & 0x3fff)
#define A57_CPMUERRSR_FATAL(a) ((a) & (1 << 63))
#define A57_CPUMERRSR_FATAL(a) ((a) & (1LL << 63))
#define A57_CPUMERRSR_OTHER(a) (((a) >> 40) & 0xff)
#define A57_CPUMERRSR_REPT(a) (((a) >> 32) & 0xff)
#define A57_CPUMERRSR_VALID(a) ((a) & (1 << 31))
@ -54,7 +56,7 @@
#define A57_CPUMERRSR_BANK(a) (((a) >> 18) & 0x1f)
#define A57_CPUMERRSR_INDEX(a) ((a) & 0x1ffff)
#define A57_L2MERRSR_FATAL(a) ((a) & (1 << 63))
#define A57_L2MERRSR_FATAL(a) ((a) & (1LL << 63))
#define A57_L2MERRSR_OTHER(a) (((a) >> 40) & 0xff)
#define A57_L2MERRSR_REPT(a) (((a) >> 32) & 0xff)
#define A57_L2MERRSR_VALID(a) ((a) & (1 << 31))
@ -65,6 +67,11 @@
#define L2ECTLR_INT_ERR (1 << 30)
#define L2ECTLR_EXT_ERR (1 << 29)
#define ESR_SERROR(a) ((a) >> ESR_EL1_EC_SHIFT == ESR_EL1_EC_SERROR)
#define ESR_VALID(a) ((a) & BIT(24))
#define ESR_L2_DBE(a) (ESR_SERROR(a) && ESR_VALID(a) && \
(((a) & 0x00C00003) == 0x1))
#define CCI_IMPRECISEERROR_REG 0x10
#define L1_CACHE 0
@ -172,6 +179,12 @@ static const struct errors_edac errors[] = {
__val; \
})
#define read_esr_el1 ({ \
u64 __val; \
asm("mrs %0, esr_el1" : "=r" (__val)); \
__val; \
})
#define write_l2merrsr_el1(val) ({ \
asm("msr s3_1_c15_c2_3, %0" : : "r" (val)); \
})
@ -184,6 +197,34 @@ static const struct errors_edac errors[] = {
asm("msr s3_1_c15_c2_2, %0" : : "r" (val)); \
})
static void ca53_ca57_print_error_state_regs(void)
{
u64 l2merrsr;
u64 cpumerrsr;
u32 esr_el1;
cpumerrsr = read_cpumerrsr_el1;
l2merrsr = read_l2merrsr_el1;
esr_el1 = read_esr_el1;
/* store data in uncached rtb logs */
uncached_logk_pc(LOGK_READL, __builtin_return_address(0),
(void *)cpumerrsr);
uncached_logk_pc(LOGK_READL, __builtin_return_address(0),
(void *)l2merrsr);
uncached_logk_pc(LOGK_READL, __builtin_return_address(0),
(void *)((u64)esr_el1));
edac_printk(KERN_CRIT, EDAC_CPU, "CPUMERRSR value = %#llx\n",
cpumerrsr);
edac_printk(KERN_CRIT, EDAC_CPU, "L2MERRSR value = %#llx\n", l2merrsr);
edac_printk(KERN_CRIT, EDAC_CPU, "ESR value = %#x\n", esr_el1);
if (ESR_L2_DBE(esr_el1))
edac_printk(KERN_CRIT, EDAC_CPU,
"Double bit error on dirty L2 cacheline\n");
}
static void ca53_parse_cpumerrsr(struct erp_local_data *ed)
{
u64 cpumerrsr;
@ -196,8 +237,10 @@ static void ca53_parse_cpumerrsr(struct erp_local_data *ed)
edac_printk(KERN_CRIT, EDAC_CPU, "Cortex A53 CPU%d L1 %s Error detected\n",
smp_processor_id(), err_name[ed->err]);
edac_printk(KERN_CRIT, EDAC_CPU, "CPUMERRSR value = %#llx\n",
cpumerrsr);
ca53_ca57_print_error_state_regs();
if (A53_CPUMERRSR_FATAL(cpumerrsr))
edac_printk(KERN_CRIT, EDAC_CPU, "Fatal error\n");
cpuid = A53_CPUMERRSR_CPUID(cpumerrsr);
@ -263,7 +306,9 @@ static void ca53_parse_l2merrsr(struct erp_local_data *ed)
edac_printk(KERN_CRIT, EDAC_CPU, "CortexA53 L2 %s Error detected\n",
err_name[ed->err]);
edac_printk(KERN_CRIT, EDAC_CPU, "L2MERRSR value = %#llx\n", l2merrsr);
ca53_ca57_print_error_state_regs();
if (A53_L2MERRSR_FATAL(l2merrsr))
edac_printk(KERN_CRIT, EDAC_CPU, "Fatal error\n");
cpuid = A53_L2MERRSR_CPUID(l2merrsr);
@ -315,8 +360,9 @@ static void ca57_parse_cpumerrsr(struct erp_local_data *ed)
edac_printk(KERN_CRIT, EDAC_CPU, "Cortex A57 CPU%d L1 %s Error detected\n",
smp_processor_id(), err_name[ed->err]);
edac_printk(KERN_CRIT, EDAC_CPU, "CPUMERRSR value = %#llx\n",
cpumerrsr);
ca53_ca57_print_error_state_regs();
if (A57_CPUMERRSR_FATAL(cpumerrsr))
edac_printk(KERN_CRIT, EDAC_CPU, "Fatal error\n");
bank = A57_CPUMERRSR_BANK(cpumerrsr);
@ -376,7 +422,9 @@ static void ca57_parse_l2merrsr(struct erp_local_data *ed)
edac_printk(KERN_CRIT, EDAC_CPU, "CortexA57 L2 %s Error detected\n",
err_name[ed->err]);
edac_printk(KERN_CRIT, EDAC_CPU, "L2MERRSR value = %#llx\n", l2merrsr);
ca53_ca57_print_error_state_regs();
if (A57_L2MERRSR_FATAL(l2merrsr))
edac_printk(KERN_CRIT, EDAC_CPU, "Fatal error\n");
cpuid = A57_L2MERRSR_CPUID(l2merrsr);
@ -557,7 +605,7 @@ void arm64_erp_local_dbe_handler(void)
struct erp_local_data errdata;
errdata.err = DBE;
errdata.drv = abort_handler_drvdata;
arm64_erp_local_handler(abort_handler_drvdata);
arm64_erp_local_handler(&errdata);
}
}