[RAMEN9610-14210][COMMON] soc: samsung: re-engineering for exynos_err_parse
authorDonghyeok Choe <d7271.choe@samsung.com>
Mon, 18 Mar 2019 04:04:38 +0000 (13:04 +0900)
committerhskang <hs1218.kang@samsung.com>
Fri, 5 Apr 2019 08:31:47 +0000 (17:31 +0900)
Change-Id: Iafe6c1f2cf6ab92c3ac9086839ae10e7da04bc24
Signed-off-by: Donghyeok Choe <d7271.choe@samsung.com>
drivers/soc/samsung/debug/exynos-helper.c
include/linux/debug-snapshot-helper.h

index 229f67e692ea004cbaa61fe90e18a51f96fd4c52..ca287b3c3cb534cd349466ee132e5ca6fb9bcd63 100644 (file)
 
 extern void (*arm_pm_restart)(enum reboot_mode str, const char *cmd);
 
+static struct err_variant arm64_err_type_1[] = {
+       ERR_VAR("AV", 31, 31),
+       ERR_VAR("Valid", 30, 30),
+       ERR_VAR("UC", 29, 29),
+       ERR_VAR("ER", 28, 28),
+       ERR_VAR("OF", 27, 27),
+       ERR_VAR("MV", 26, 26),
+       ERR_VAR("CE", 25, 24),
+       ERR_VAR("DE", 23, 23),
+       ERR_VAR("PN", 22, 22),
+       ERR_VAR("UET", 21, 20),
+       ERR_VAR("RES0", 19, 16),
+       ERR_VAR("IERR", 15, 8),
+       ERR_VAR("SERR", 7, 0),
+       ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_2[] = {
+       ERR_VAR("Count1", 63, 56),
+       ERR_VAR("Count0", 55, 48),
+       ERR_VAR("RES1", 47, 41),
+       ERR_VAR("Syndrom", 40, 32),
+       ERR_VAR("Stype2", 31, 28),
+       ERR_VAR("SType1", 27, 24),
+       ERR_VAR("SType0", 23, 16),
+       ERR_VAR("Type", 15, 12),
+       ERR_VAR("RES0", 11, 6),
+       ERR_VAR("RE", 5, 5),
+       ERR_VAR("SynValid", 4, 4),
+       ERR_VAR("AddrValid", 3, 3),
+       ERR_VAR("UnContained", 2, 2),
+       ERR_VAR("UC", 1, 1),
+       ERR_VAR("Vaild", 0, 0),
+       ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_3[] = {
+       ERR_VAR("RES0", 63, 32),
+       ERR_VAR("A", 31, 31),
+       ERR_VAR("RES0", 30, 25),
+       ERR_VAR("RES2", 24, 16),
+       ERR_VAR("AEType", 15, 14),
+       ERR_VAR("RES1", 13, 13),
+       ERR_VAR("EXT", 12, 12),
+       ERR_VAR("AET", 11, 10),
+       ERR_VAR("EA", 9, 9),
+       ERR_VAR("EA", 8, 6),
+       ERR_VAR("DFSC", 5, 0),
+       ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_4[] = {
+       ERR_VAR("Fatal", 63, 63),
+       ERR_VAR("RES0", 62, 48),
+       ERR_VAR("Other error count", 47, 40),
+       ERR_VAR("Repeat error count", 39, 32),
+       ERR_VAR("Valid", 31, 31),
+       ERR_VAR("RAMID", 30, 24),
+       ERR_VAR("RES0", 23, 21),
+       ERR_VAR("CPUID", 20, 18),
+       ERR_VAR("RES0", 17, 12),
+       ERR_VAR("RAM address", 11, 0),
+       ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_TCR[] = {
+//     ERR_VAR("HPD1", 42, 42),
+//     ERR_VAR("HPD0", 41, 41),
+//     ERR_VAR("HD", 40, 40),
+//     ERR_VAR("HA", 39, 39),
+       ERR_VAR("TBI1", 38, 38),
+       ERR_VAR("TBI0", 37, 37),
+//     ERR_VAR("AS", 36, 36),
+//     ERR_VAR("IPS", 34, 32),
+//     ERR_VAR("TG1", 31, 30),
+//     ERR_VAR("SH1", 29, 28),
+//     ERR_VAR("ORGN1", 27, 26),
+//     ERR_VAR("IRGN1", 25, 24),
+//     ERR_VAR("EPD1", 23, 23),
+//     ERR_VAR("A1", 22, 22),
+//     ERR_VAR("T1SZ", 21, 16),
+//     ERR_VAR("TG0", 15, 14),
+//     ERR_VAR("SH0", 13, 12),
+//     ERR_VAR("ORGN0", 11, 10),
+//     ERR_VAR("IRGN0", 9, 8),
+//     ERR_VAR("EPD0", 7, 7),
+//     ERR_VAR("T1SZ", 5, 0),
+//     ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_VBAR[] = {
+       ERR_VAR("VBA[63:56]", 63, 56),
+       ERR_VAR("VBA[55]", 55, 55),
+       ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_L2ECTLR[] = {
+       ERR_VAR("L2AsyncErr", 30, 30),
+       ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_L3ECTLR[] = {
+       ERR_VAR("L3IntrnAsyncErr", 30, 30),
+       ERR_VAR("ExtBusAsyncErr", 29, 29),
+       ERR_VAR("EnTmrIncChk", 3, 3),
+       ERR_VAR("ClusterQactiveCtl", 2, 0),
+       ERR_VAR("END", 64, 64),
+};
+
+enum {
+       FEMERR0SR = 0,
+       LSMERR0SR,
+       TBWMERR0SR,
+       L2MERR0SR,
+       L3MERR0SR,
+       DISR_EL1,
+       ERXSTATUS_EL1,
+       CPUMERRSR,
+       L2MERRSR,
+       TCR_EL1,
+       VBAR_EL1,
+       L2ECTLR_EL1,
+       L3ECTLR
+};
+
+static struct err_variant_data exynos_cpu_err_table[] = {
+       ERR_REG(arm64_err_type_2, 0, "FEMERR0SR"),
+       ERR_REG(arm64_err_type_2, 0, "LSMERR0SR"),
+       ERR_REG(arm64_err_type_2, 0, "TBWMERR0SR"),
+       ERR_REG(arm64_err_type_2, 0, "L2MERR0SR"),
+       ERR_REG(arm64_err_type_2, 0, "L3MERR0SR"),
+       ERR_REG(arm64_err_type_3, 31, "DISR_EL1"),
+       ERR_REG(arm64_err_type_1, 30, "ERXSTATUS_EL1"),
+       ERR_REG(arm64_err_type_4, 31, "CPUMERRSR"),
+       ERR_REG(arm64_err_type_4, 31, "L2MERRSR"),
+       ERR_REG(arm64_err_type_TCR, 0xFF, "TCR_EL1"),
+       ERR_REG(arm64_err_type_VBAR, 0xFF, "VBAR_EL1"),
+       ERR_REG(arm64_err_type_L2ECTLR, 30, "L2ECTLR_EL1"),
+       ERR_REG(arm64_err_type_L3ECTLR, 30, "L3ECTLR")
+};
+
+void exynos_err_parse(u32 reg_idx, u64 reg, struct err_variant_data *exynos_cpu_err)
+{
+       u8 i = 0;
+       u8 fld_offset, fld_end;
+       u64 valid;
+       u32 field;
+       const struct err_variant *variant;
+
+
+       if (exynos_cpu_err->valid_bit == 0xFF)
+               goto run_valid;
+
+       valid = reg & BIT(exynos_cpu_err->valid_bit);
+       if (!valid) {
+               pr_emerg("%s valid_bit(%d) is NOT set (0x%lx)\n",
+                               exynos_cpu_err->reg_name, exynos_cpu_err->valid_bit, valid);
+               return;
+       }
+
+run_valid:
+       variant = exynos_cpu_err->variant;
+       while (true) {
+               fld_offset = variant[i].fld_offset;
+               fld_end = variant[i].fld_end;
+
+               if (fld_end > 63)
+                       break;
+
+               field = (reg & GENMASK_ULL(fld_end, fld_offset)) >> fld_offset;
+               if (field != 0)
+                       pr_emerg("%s (%d:%d) %s 0x%lx\n",
+                               exynos_cpu_err->reg_name,
+                               fld_end, fld_offset,
+                               variant[i].fld_name, field);
+               i++;
+       };
+};
+
+static void exynos_cpu_err_parse(u32 reg_idx, u64 reg)
+{
+       if (reg_idx >= ARRAY_SIZE(exynos_cpu_err_table)) {
+               pr_err("%s: there is no parse data\n", __func__);
+               return;
+       }
+
+       exynos_err_parse(reg_idx, reg, &exynos_cpu_err_table[reg_idx]);
+}
+
 static void exynos_early_panic(void *val)
 {
        exynos_bcm_dbg_stop(PANIC_HANDLE);
@@ -94,7 +283,7 @@ static void exynos_save_core(void *val)
 {
        struct pt_regs *core_reg = (struct pt_regs *)val;
 
-       asm("str x0, [%0, #0]\n\t"
+       asm volatile ("str x0, [%0, #0]\n\t"
                "mov x0, %0\n\t"
                "str x1, [x0, #8]\n\t"
                "str x2, [x0, #16]\n\t"
@@ -138,7 +327,7 @@ static void exynos_save_system(void *val)
                        (struct dbg_snapshot_mmu_reg *)val;
 
 #ifdef CONFIG_ARM64
-       asm("mrs x1, SCTLR_EL1\n\t"             /* SCTLR_EL1 */
+       asm volatile ("mrs x1, SCTLR_EL1\n\t"           /* SCTLR_EL1 */
                "str x1, [%0]\n\t"
                "mrs x1, TTBR0_EL1\n\t"         /* TTBR0_EL1 */
                "str x1, [%0,#8]\n\t"
@@ -169,7 +358,7 @@ static void exynos_save_system(void *val)
                : "%x1", "memory"                       /* clobbered register */
        );
 #else
-       asm("mrc    p15, 0, r1, c1, c0, 0\n\t"  /* SCTLR */
+       asm volatile ("mrc    p15, 0, r1, c1, c0, 0\n\t"        /* SCTLR */
            "str r1, [%0]\n\t"
            "mrc    p15, 0, r1, c2, c0, 0\n\t"  /* TTBR0 */
            "str r1, [%0,#4]\n\t"
@@ -208,6 +397,18 @@ static void exynos_save_system(void *val)
 #endif
 }
 
+void exynos_dump_common_cpu_reg(void)
+{
+       unsigned long reg1, reg2;
+
+       asm volatile ("mrs %0, vbar_el1\n\t"
+                       "mrs %1, tcr_el1\n"
+                       : "=r" (reg1), "=r" (reg2));
+
+       exynos_cpu_err_parse(VBAR_EL1, reg1);
+       exynos_cpu_err_parse(TCR_EL1, reg2);
+}
+
 static void exynos_dump_info(void *val)
 {
        /*
@@ -221,53 +422,6 @@ static void exynos_dump_info(void *val)
                switch (read_cpuid_part_number()) {
                case ARM_CPU_PART_MONGOOSE:
                case ARM_CPU_PART_MEERKAT:
-                       asm ("mrs %0, S3_1_c15_c2_0\n\t"
-                                       "mrs %1, S3_1_c15_c2_4\n"
-                                       : "=r" (reg1), "=r" (reg2));
-                       pr_emerg("FEMERR0SR: %016lx, FEMERR1SR: %016lx\n", reg1, reg2);
-                       asm ("mrs %0, S3_1_c15_c2_1\n\t"
-                                       "mrs %1, S3_1_c15_c2_5\n"
-                                       : "=r" (reg1), "=r" (reg2));
-                       pr_emerg("LSMERR0SR: %016lx, LSMERR1SR: %016lx\n", reg1, reg2);
-                       asm ("mrs %0, S3_1_c15_c2_2\n\t"
-                                       "mrs %1, S3_1_c15_c2_6\n"
-                                       : "=r" (reg1), "=r" (reg2));
-                       pr_emerg("TBWMERR0SR: %016lx, TBWMERR1SR: %016lx\n", reg1, reg2);
-                       asm ("mrs %0, S3_1_c15_c2_3\n\t"
-                                       "mrs %1, S3_1_c15_c2_7\n"
-                                       : "=r" (reg1), "=r" (reg2));
-                       pr_emerg("L2MERR0SR: %016lx, L2MERR1SR: %016lx\n", reg1, reg2);
-
-                       /* L3 MERR */
-                       asm ("msr S3_1_c15_c7_1, %0\n\t"
-                                       "isb\n"
-                                       :: "r" (0));
-                       asm ("mrs %0, S3_1_c15_c3_0\n\t"
-                                       "mrs %1, S3_1_c15_c3_4\n"
-                                       : "=r" (reg1), "=r" (reg2));
-                       pr_emerg("BANK0 L3MERR0SR: %016lx, L3MERR1SR: %016lx\n", reg1, reg2);
-                       asm ("msr S3_1_c15_c7_1, %0\n\t"
-                                       "isb\n"
-                                       :: "r" (1));
-                       asm ("mrs %0, S3_1_c15_c3_0\n\t"
-                                       "mrs %1, S3_1_c15_c3_4\n"
-                                       : "=r" (reg1), "=r" (reg2));
-                       pr_emerg("BANK1 L3MERR0SR: %016lx, L3MERR1SR: %016lx\n", reg1, reg2);
-                       asm ("msr S3_1_c15_c7_1, %0\n\t"
-                                       "isb\n"
-                                       :: "r" (2));
-                       asm ("mrs %0, S3_1_c15_c3_0\n\t"
-                                       "mrs %1, S3_1_c15_c3_4\n"
-                                       : "=r" (reg1), "=r" (reg2));
-                       pr_emerg("BANK2 L3MERR0SR: %016lx, L3MERR1SR: %016lx\n", reg1, reg2);
-                       asm ("msr S3_1_c15_c7_1, %0\n\t"
-                                       "isb\n"
-                                       :: "r" (3));
-                       asm ("mrs %0, S3_1_c15_c3_0\n\t"
-                                       "mrs %1, S3_1_c15_c3_4\n"
-                                       : "=r" (reg1), "=r" (reg2));
-                       pr_emerg("BANK3 L3MERR0SR: %016lx, L3MERR1SR: %016lx\n", reg1, reg2);
-
                        break;
                default:
                        break;
@@ -276,38 +430,56 @@ static void exynos_dump_info(void *val)
                switch (read_cpuid_part_number()) {
                case ARM_CPU_PART_CORTEX_A57:
                case ARM_CPU_PART_CORTEX_A53:
-                       asm ("mrs %0, S3_1_c15_c2_2\n\t"
+                       asm volatile ("mrs %0, S3_1_c11_c0_3\n\t"
+                                       : "=r" (reg1));
+                       pr_emerg("L2ECTLR_EL1: %016lx", reg1);
+                       exynos_cpu_err_parse(L2ECTLR_EL1, reg1);
+
+                       asm volatile ("mrs %0, S3_1_c15_c2_2\n\t"
                                        "mrs %1, S3_1_c15_c2_3\n"
                                        : "=r" (reg1), "=r" (reg2));
                        pr_emerg("CPUMERRSR: %016lx, L2MERRSR: %016lx\n", reg1, reg2);
+                       exynos_cpu_err_parse(CPUMERRSR, reg1);
+                       exynos_cpu_err_parse(L2MERRSR, reg2);
                        break;
                case ARM_CPU_PART_ANANKE:
+               case ARM_CPU_PART_CORTEX_A73:
+                       asm volatile ("mrs %0, S3_1_c11_c0_3\n\t"
+                                       "mrs %1, S3_1_c15_c2_3\n"
+                                       : "=r" (reg1), "=r" (reg2));
+                       pr_emerg("L2ECTLR_EL1: %016lx, L2MERRSR: %016lx\n", reg1, reg2);
+                       exynos_cpu_err_parse(L2ECTLR_EL1, reg1);
+                       exynos_cpu_err_parse(L2MERRSR, reg2);
+                       break;
                case ARM_CPU_PART_CORTEX_A75:
-                       asm ("HINT #16");
-                       asm ("mrs %0, S3_0_c12_c1_1\n" : "=r" (reg1)); /* read DISR_EL1 */
+                       asm volatile ("HINT #16");
+                       asm volatile ("mrs %0, S3_0_c12_c1_1\n" : "=r" (reg1)); /* read DISR_EL1 */
                        pr_emerg("DISR_EL1: %016lx\n", reg1);
+                       exynos_cpu_err_parse(DISR_EL1, reg1);
 
-                       asm ("msr S3_0_c5_c3_1, %0\n"
+                       asm volatile ("msr S3_0_c5_c3_1, %0\n"
                                        "isb\n"
-                                       :: "r" (0)); /* set 1st ERRSELR_EL1 */
+                                       :: "r" (0)); /* set CPU ERRSELR_EL1 */
 
-                       asm ("mrs %0, S3_0_c5_c4_2\n"
+                       asm volatile ("mrs %0, S3_0_c5_c4_2\n"
                                        "mrs %1, S3_0_c5_c4_3\n"
                                        "mrs %2, S3_0_c5_c5_0\n"
                                        : "=r" (reg1), "=r" (reg2), "=r" (reg3));
-                       pr_emerg("1st : ERXSTATUS_EL1: %016lx, ERXADDR_EL1: %016lx, "
+                       pr_emerg("CPU : ERXSTATUS_EL1: %016lx, ERXADDR_EL1: %016lx, "
                                        "ERXMISC0_EL1: %016lx\n", reg1, reg2, reg3);
+                       exynos_cpu_err_parse(ERXSTATUS_EL1, reg1);
 
-                       asm ("msr S3_0_c5_c3_1, %0\n"
+                       asm volatile ("msr S3_0_c5_c3_1, %0\n"
                                        "isb\n"
-                                       :: "r" (1)); /* set 2nd ERRSELR_EL1 */
+                                       :: "r" (1)); /* set DSU ERRSELR_EL1 */
 
-                       asm ("mrs %0, S3_0_c5_c4_2\n"
+                       asm volatile ("mrs %0, S3_0_c5_c4_2\n"
                                        "mrs %1, S3_0_c5_c4_3\n"
                                        "mrs %2, S3_0_c5_c5_0\n"
                                        : "=r" (reg1), "=r" (reg2), "=r" (reg3));
-                       pr_emerg("2nd : ERXSTATUS_EL1: %016lx, ERXADDR_EL1: %016lx, "
+                       pr_emerg("DSU : ERXSTATUS_EL1: %016lx, ERXADDR_EL1: %016lx, "
                                        "ERXMISC0_EL1: %016lx\n", reg1, reg2, reg3);
+                       exynos_cpu_err_parse(ERXSTATUS_EL1, reg1);
 
                        break;
                default:
@@ -316,11 +488,11 @@ static void exynos_dump_info(void *val)
        }
 #else
        unsigned long reg0;
-       asm ("mrc p15, 0, %0, c0, c0, 0\n": "=r" (reg0));
+       asm volatile ("mrc p15, 0, %0, c0, c0, 0\n": "=r" (reg0));
        if (((reg0 >> 4) & 0xFFF) == 0xC0F) {
                /*  Only Cortex-A15 */
                unsigned long reg1, reg2, reg3;
-               asm ("mrrc p15, 0, %0, %1, c15\n\t"
+               asm volatile ("mrrc p15, 0, %0, %1, c15\n\t"
                        "mrrc p15, 1, %2, %3, c15\n"
                        : "=r" (reg0), "=r" (reg1),
                        "=r" (reg2), "=r" (reg3));
index be7c43a418c81cb3a10607e43be99f28bf4454fe..136d3a369f457f5d53e4829a492a2ac1a5fa9a17 100644 (file)
@@ -87,4 +87,35 @@ struct dbg_snapshot_mmu_reg {
        int POTPIDR;
 };
 #endif
+
+
+struct err_variant {
+       u8 fld_end;
+       u8 fld_offset;
+       const char *fld_name;
+};
+
+struct err_variant_data {
+       const struct err_variant *variant;
+       u8 valid_bit;
+       const char *reg_name;
+};
+
+#define ERR_REG(variants, valid, reg)  \
+       {                                       \
+               .variant        = variants,     \
+               .valid_bit      = valid,        \
+               .reg_name       = reg,          \
+       }
+
+#define ERR_VAR(name, end, offset)     \
+       {                                       \
+               .fld_end        = end,  \
+               .fld_offset     = offset,       \
+               .fld_name       = name,         \
+       }
+
+
 #endif
+
+extern void exynos_err_parse(u32 reg_idx, u64 reg, struct err_variant_data *exynos_cpu_err);