struct llist_node *kr_cur;
        struct task_struct *tsk;
 #endif
+#ifdef CONFIG_ARM_UNWIND
+       /*
+        * This field is used to track the stack pointer value when calling
+        * __entry routines. This is needed when IRQ stacks and overflow stacks
+        * are used, because in that case, the struct pt_regs passed to these
+        * __entry routines may be at the top of the task stack, while we are
+        * executing from another stack.
+        */
+       unsigned long sp_low;
+#endif
 };
 
 static __always_inline
 
                loglvl, where, from);
 #endif
 
-       if (in_entry_text(from) && end <= ALIGN(frame, THREAD_SIZE))
+       if (!IS_ENABLED(CONFIG_UNWINDER_ARM) &&
+           in_entry_text(from) && end <= ALIGN(frame, THREAD_SIZE))
                dump_mem(loglvl, "Exception stack", frame + 4, end);
 }
 
 
 #include <linux/spinlock.h>
 #include <linux/list.h>
 
+#include <asm/sections.h>
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
 #include <asm/unwind.h>
        frame->sp = ctrl.vrs[SP];
        frame->lr = ctrl.vrs[LR];
        frame->pc = ctrl.vrs[PC];
+       frame->sp_low = ctrl.sp_low;
 
        return URC_OK;
 }
                urc = unwind_frame(&frame);
                if (urc < 0)
                        break;
-               dump_backtrace_entry(where, frame.pc, frame.sp - 4, loglvl);
+               if (in_entry_text(where))
+                       dump_mem(loglvl, "Exception stack", frame.sp_low,
+                                frame.sp_low + sizeof(struct pt_regs));
+
+               dump_backtrace_entry(where, frame.pc, 0, loglvl);
        }
 }