summaryrefslogtreecommitdiffstats
path: root/arch/arm64/include/asm/irq.h
diff options
context:
space:
mode:
authorJames Morse <james.morse@arm.com>2015-12-15 12:21:25 +0100
committerWill Deacon <will.deacon@arm.com>2015-12-15 18:09:08 +0100
commit971c67ce37cfeeaf560e792a2c3bc21d8b67163a (patch)
treedabce8d15638e66a8c351454e78e3f5bac6f6c2f /arch/arm64/include/asm/irq.h
parentMerge branch 'aarch64/efi' into aarch64/for-next/core (diff)
downloadlinux-971c67ce37cfeeaf560e792a2c3bc21d8b67163a.tar.xz
linux-971c67ce37cfeeaf560e792a2c3bc21d8b67163a.zip
arm64: reduce stack use in irq_handler
The code for switching to irq_stack stores three pieces of information on the stack, fp+lr, as a fake stack frame (that lets us walk back onto the interrupted tasks stack frame), and the address of the struct pt_regs that contains the register values from kernel entry. (which dump_backtrace() will print in any stack trace). To reduce this, we store fp, and the pointer to the struct pt_regs. unwind_frame() can recognise this as the irq_stack dummy frame, (as it only appears at the top of the irq_stack), and use the struct pt_regs values to find the missing interrupted link-register. Suggested-by: Will Deacon <will.deacon@arm.com> Signed-off-by: James Morse <james.morse@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64/include/asm/irq.h')
-rw-r--r--arch/arm64/include/asm/irq.h11
1 files changed, 4 insertions, 7 deletions
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index 877c7e358384..3bece4379bd9 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -25,16 +25,13 @@ DECLARE_PER_CPU(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack);
* ------------
* | | <- irq_stack_ptr
* top ------------
- * | elr_el1 |
+ * | x19 | <- irq_stack_ptr - 0x08
* ------------
* | x29 | <- irq_stack_ptr - 0x10
* ------------
- * | xzr |
- * ------------
- * | x19 | <- irq_stack_ptr - 0x20
- * ------------
*
- * where x19 holds a copy of the task stack pointer.
+ * where x19 holds a copy of the task stack pointer where the struct pt_regs
+ * from kernel_entry can be found.
*
*/
#define IRQ_STACK_PTR(cpu) ((unsigned long)per_cpu(irq_stack, cpu) + IRQ_STACK_START_SP)
@@ -43,7 +40,7 @@ DECLARE_PER_CPU(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack);
* 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 - 0x20));
+#define IRQ_STACK_TO_TASK_STACK(ptr) (*((unsigned long *)((ptr) - 0x08)))
extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));