arm64: Modify stack trace and dump for use with irq_stack
This patch allows unwind_frame() to traverse from interrupt stack to task stack correctly. It requires data from a dummy stack frame, created during irq_stack_entry(), added by a later patch. A similar approach is taken to modify dump_backtrace(), which expects to find struct pt_regs underneath any call to functions marked __exception. When on an irq_stack, the struct pt_regs is stored on the old task stack, the location of which is stored in the dummy stack frame. Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> [james.morse: merged two patches, reworked for per_cpu irq_stacks, and no alignment guarantees, added irq_stack definitions] Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:

committed by
Will Deacon

parent
6cdf9c7ca6
commit
132cd887b5
@@ -1,10 +1,32 @@
|
||||
#ifndef __ASM_IRQ_H
|
||||
#define __ASM_IRQ_H
|
||||
|
||||
#define IRQ_STACK_SIZE THREAD_SIZE
|
||||
#define IRQ_STACK_START_SP THREAD_START_SP
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <linux/percpu.h>
|
||||
|
||||
#include <asm-generic/irq.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
DECLARE_PER_CPU(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack);
|
||||
|
||||
/*
|
||||
* The highest address on the stack, and the first to be used. Used to
|
||||
* find the dummy-stack frame put down by el?_irq() in entry.S.
|
||||
*/
|
||||
#define IRQ_STACK_PTR(cpu) ((unsigned long)per_cpu(irq_stack, cpu) + IRQ_STACK_START_SP)
|
||||
|
||||
/*
|
||||
* The offset from irq_stack_ptr where entry.S will store the original
|
||||
* stack pointer. Used by unwind_frame() and dump_backtrace().
|
||||
*/
|
||||
#define IRQ_STACK_TO_TASK_STACK(ptr) *((unsigned long *)(ptr - 0x10));
|
||||
|
||||
extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
|
||||
|
||||
static inline int nr_legacy_irqs(void)
|
||||
@@ -12,4 +34,14 @@ static inline int nr_legacy_irqs(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool on_irq_stack(unsigned long sp, int cpu)
|
||||
{
|
||||
/* variable names the same as kernel/stacktrace.c */
|
||||
unsigned long low = (unsigned long)per_cpu(irq_stack, cpu);
|
||||
unsigned long high = low + IRQ_STACK_START_SP;
|
||||
|
||||
return (low <= sp && sp <= high);
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user