#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 */
 
 
 }
 #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.
  */
        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);
        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;