Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab503cec authored by Patrick Daly's avatar Patrick Daly
Browse files

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: default avatarPatrick Daly <pdaly@codeaurora.org>
parent 974367a3
Loading
Loading
Loading
Loading
+59 −11
Original line number Diff line number Diff line
@@ -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);
	}
}