diff options
author | James Morse <james.morse@arm.com> | 2015-12-15 06:21:25 -0500 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2015-12-15 12:09:08 -0500 |
commit | 971c67ce37cfeeaf560e792a2c3bc21d8b67163a (patch) | |
tree | dabce8d15638e66a8c351454e78e3f5bac6f6c2f /arch/arm64/kernel/entry.S | |
parent | 129b985cc3f331d0e6908958f50757a3a1b37793 (diff) |
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/kernel/entry.S')
-rw-r--r-- | arch/arm64/kernel/entry.S | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 2284c296e3f7..0667fb7d8bb1 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S | |||
@@ -178,7 +178,7 @@ alternative_endif | |||
178 | mrs \rd, sp_el0 | 178 | mrs \rd, sp_el0 |
179 | .endm | 179 | .endm |
180 | 180 | ||
181 | .macro irq_stack_entry, dummy_lr | 181 | .macro irq_stack_entry |
182 | mov x19, sp // preserve the original sp | 182 | mov x19, sp // preserve the original sp |
183 | 183 | ||
184 | this_cpu_ptr irq_stack, x25, x26 | 184 | this_cpu_ptr irq_stack, x25, x26 |
@@ -196,10 +196,12 @@ alternative_endif | |||
196 | add x26, x25, x26 | 196 | add x26, x25, x26 |
197 | mov sp, x26 | 197 | mov sp, x26 |
198 | 198 | ||
199 | /* Add a dummy stack frame */ | 199 | /* |
200 | stp x29, \dummy_lr, [sp, #-16]! // dummy stack frame | 200 | * Add a dummy stack frame, this non-standard format is fixed up |
201 | * by unwind_frame() | ||
202 | */ | ||
203 | stp x29, x19, [sp, #-16]! | ||
201 | mov x29, sp | 204 | mov x29, sp |
202 | stp x19, xzr, [sp, #-16]! | ||
203 | 205 | ||
204 | 9998: | 206 | 9998: |
205 | .endm | 207 | .endm |
@@ -229,7 +231,7 @@ tsk .req x28 // current thread_info | |||
229 | .macro irq_handler | 231 | .macro irq_handler |
230 | ldr_l x1, handle_arch_irq | 232 | ldr_l x1, handle_arch_irq |
231 | mov x0, sp | 233 | mov x0, sp |
232 | irq_stack_entry x22 | 234 | irq_stack_entry |
233 | blr x1 | 235 | blr x1 |
234 | irq_stack_exit | 236 | irq_stack_exit |
235 | .endm | 237 | .endm |