]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
arm64: Decode information from ESR upon mem faults
authorJulien Thierry <julien.thierry@arm.com>
Fri, 4 Aug 2017 08:31:42 +0000 (09:31 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Mon, 7 Aug 2017 08:58:33 +0000 (09:58 +0100)
When receiving unhandled faults from the CPU, description is very sparse.
Adding information about faults decoded from ESR.

Added defines to esr.h corresponding ESR fields. Values are based on ARM
Archtecture Reference Manual (DDI 0487B.a), section D7.2.28 ESR_ELx, Exception
Syndrome Register (ELx) (pages D7-2275 to D7-2280).

New output is of the form:
[   77.818059] Mem abort info:
[   77.820826]   Exception class = DABT (current EL), IL = 32 bits
[   77.826706]   SET = 0, FnV = 0
[   77.829742]   EA = 0, S1PTW = 0
[   77.832849] Data abort info:
[   77.835713]   ISV = 0, ISS = 0x00000070
[   77.839522]   CM = 0, WnR = 1

Signed-off-by: Julien Thierry <julien.thierry@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
[catalin.marinas@arm.com: fix "%lu" in a pr_alert() call]
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/esr.h
arch/arm64/mm/fault.c

index 8cabd57b634832ca7c4df7d8fee39549233167dd..130b5343ba6df189c8a7aa12cc387a9e738a6a21 100644 (file)
 #define ESR_ELx_EC_MASK                (UL(0x3F) << ESR_ELx_EC_SHIFT)
 #define ESR_ELx_EC(esr)                (((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT)
 
-#define ESR_ELx_IL             (UL(1) << 25)
+#define ESR_ELx_IL_SHIFT       (25)
+#define ESR_ELx_IL             (UL(1) << ESR_ELx_IL_SHIFT)
 #define ESR_ELx_ISS_MASK       (ESR_ELx_IL - 1)
 
 /* ISS field definitions shared by different classes */
-#define ESR_ELx_WNR            (UL(1) << 6)
+#define ESR_ELx_WNR_SHIFT      (6)
+#define ESR_ELx_WNR            (UL(1) << ESR_ELx_WNR_SHIFT)
 
 /* Shared ISS field definitions for Data/Instruction aborts */
-#define ESR_ELx_FnV            (UL(1) << 10)
-#define ESR_ELx_EA             (UL(1) << 9)
-#define ESR_ELx_S1PTW          (UL(1) << 7)
+#define ESR_ELx_SET_SHIFT      (11)
+#define ESR_ELx_SET_MASK       (UL(3) << ESR_ELx_SET_SHIFT)
+#define ESR_ELx_FnV_SHIFT      (10)
+#define ESR_ELx_FnV            (UL(1) << ESR_ELx_FnV_SHIFT)
+#define ESR_ELx_EA_SHIFT       (9)
+#define ESR_ELx_EA             (UL(1) << ESR_ELx_EA_SHIFT)
+#define ESR_ELx_S1PTW_SHIFT    (7)
+#define ESR_ELx_S1PTW          (UL(1) << ESR_ELx_S1PTW_SHIFT)
 
 /* Shared ISS fault status code(IFSC/DFSC) for Data/Instruction aborts */
 #define ESR_ELx_FSC            (0x3F)
 #define ESR_ELx_FSC_PERM       (0x0C)
 
 /* ISS field definitions for Data Aborts */
-#define ESR_ELx_ISV            (UL(1) << 24)
+#define ESR_ELx_ISV_SHIFT      (24)
+#define ESR_ELx_ISV            (UL(1) << ESR_ELx_ISV_SHIFT)
 #define ESR_ELx_SAS_SHIFT      (22)
 #define ESR_ELx_SAS            (UL(3) << ESR_ELx_SAS_SHIFT)
-#define ESR_ELx_SSE            (UL(1) << 21)
+#define ESR_ELx_SSE_SHIFT      (21)
+#define ESR_ELx_SSE            (UL(1) << ESR_ELx_SSE_SHIFT)
 #define ESR_ELx_SRT_SHIFT      (16)
 #define ESR_ELx_SRT_MASK       (UL(0x1F) << ESR_ELx_SRT_SHIFT)
-#define ESR_ELx_SF             (UL(1) << 15)
-#define ESR_ELx_AR             (UL(1) << 14)
-#define ESR_ELx_CM             (UL(1) << 8)
+#define ESR_ELx_SF_SHIFT       (15)
+#define ESR_ELx_SF             (UL(1) << ESR_ELx_SF_SHIFT)
+#define ESR_ELx_AR_SHIFT       (14)
+#define ESR_ELx_AR             (UL(1) << ESR_ELx_AR_SHIFT)
+#define ESR_ELx_CM_SHIFT       (8)
+#define ESR_ELx_CM             (UL(1) << ESR_ELx_CM_SHIFT)
 
 /* ISS field definitions for exceptions taken in to Hyp */
 #define ESR_ELx_CV             (UL(1) << 24)
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 
+static inline bool esr_is_data_abort(u32 esr)
+{
+       const u32 ec = ESR_ELx_EC(esr);
+
+       return ec == ESR_ELx_EC_DABT_LOW || ec == ESR_ELx_EC_DABT_CUR;
+}
+
 const char *esr_get_class_string(u32 esr);
 #endif /* __ASSEMBLY */
 
index 2509e4fe699225675f74876032e22b24b338a3b1..52ee273afeec0f7e3bb5466ebe6b4b825193693f 100644 (file)
@@ -82,6 +82,49 @@ static inline int notify_page_fault(struct pt_regs *regs, unsigned int esr)
 }
 #endif
 
+static void data_abort_decode(unsigned int esr)
+{
+       pr_alert("Data abort info:\n");
+
+       if (esr & ESR_ELx_ISV) {
+               pr_alert("  Access size = %u byte(s)\n",
+                        1U << ((esr & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT));
+               pr_alert("  SSE = %lu, SRT = %lu\n",
+                        (esr & ESR_ELx_SSE) >> ESR_ELx_SSE_SHIFT,
+                        (esr & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT);
+               pr_alert("  SF = %lu, AR = %lu\n",
+                        (esr & ESR_ELx_SF) >> ESR_ELx_SF_SHIFT,
+                        (esr & ESR_ELx_AR) >> ESR_ELx_AR_SHIFT);
+       } else {
+               pr_alert("  ISV = 0, ISS = 0x%08lu\n", esr & ESR_ELx_ISS_MASK);
+       }
+
+       pr_alert("  CM = %lu, WnR = %lu\n",
+                (esr & ESR_ELx_CM) >> ESR_ELx_CM_SHIFT,
+                (esr & ESR_ELx_WNR) >> ESR_ELx_WNR_SHIFT);
+}
+
+/*
+ * Decode mem abort information
+ */
+static void mem_abort_decode(unsigned int esr)
+{
+       pr_alert("Mem abort info:\n");
+
+       pr_alert("  Exception class = %s, IL = %u bits\n",
+                esr_get_class_string(esr),
+                (esr & ESR_ELx_IL) ? 32 : 16);
+       pr_alert("  SET = %lu, FnV = %lu\n",
+                (esr & ESR_ELx_SET_MASK) >> ESR_ELx_SET_SHIFT,
+                (esr & ESR_ELx_FnV) >> ESR_ELx_FnV_SHIFT);
+       pr_alert("  EA = %lu, S1PTW = %lu\n",
+                (esr & ESR_ELx_EA) >> ESR_ELx_EA_SHIFT,
+                (esr & ESR_ELx_S1PTW) >> ESR_ELx_S1PTW_SHIFT);
+
+       if (esr_is_data_abort(esr))
+               data_abort_decode(esr);
+}
+
 /*
  * Dump out the page tables associated with 'addr' in the currently active mm.
  */
@@ -248,6 +291,8 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
        pr_alert("Unable to handle kernel %s at virtual address %08lx\n", msg,
                 addr);
 
+       mem_abort_decode(esr);
+
        show_pte(addr);
        die("Oops", regs, esr);
        bust_spinlocks(0);
@@ -702,6 +747,8 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
        pr_alert("Unhandled fault: %s (0x%08x) at 0x%016lx\n",
                 inf->name, esr, addr);
 
+       mem_abort_decode(esr);
+
        info.si_signo = inf->sig;
        info.si_errno = 0;
        info.si_code  = inf->code;