diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-06-19 11:43:08 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-06-19 11:44:23 -0400 |
commit | feb97c3644a560ffdf9a17c65b1df807b5b4432f (patch) | |
tree | d9c84b8ad646cbf43e20c9a96e5db25b4ccd4ec6 /arch/arm | |
parent | c894ed6956f126d60d888e8efc5fb3a595ba89ae (diff) |
[ARM] 5559/1: Limit the stack unwinding caused by a kthread exit
When a kthread function returns, it branches to do_exit(). However, the
unwinding information isn't valid anymore and any stack trace caused by
do_exit() may be incorrect. This patch adds a kernel_thread_exit()
function and annotated with '.cantunwind' so that the unwinder stops
when reaching it.
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/kernel/process.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 1585423699ee..56820cce91a4 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -352,6 +352,23 @@ asm( ".section .text\n" | |||
352 | " .size kernel_thread_helper, . - kernel_thread_helper\n" | 352 | " .size kernel_thread_helper, . - kernel_thread_helper\n" |
353 | " .previous"); | 353 | " .previous"); |
354 | 354 | ||
355 | #ifdef CONFIG_ARM_UNWIND | ||
356 | extern void kernel_thread_exit(long code); | ||
357 | asm( ".section .text\n" | ||
358 | " .align\n" | ||
359 | " .type kernel_thread_exit, #function\n" | ||
360 | "kernel_thread_exit:\n" | ||
361 | " .fnstart\n" | ||
362 | " .cantunwind\n" | ||
363 | " bl do_exit\n" | ||
364 | " nop\n" | ||
365 | " .fnend\n" | ||
366 | " .size kernel_thread_exit, . - kernel_thread_exit\n" | ||
367 | " .previous"); | ||
368 | #else | ||
369 | #define kernel_thread_exit do_exit | ||
370 | #endif | ||
371 | |||
355 | /* | 372 | /* |
356 | * Create a kernel thread. | 373 | * Create a kernel thread. |
357 | */ | 374 | */ |
@@ -363,7 +380,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |||
363 | 380 | ||
364 | regs.ARM_r1 = (unsigned long)arg; | 381 | regs.ARM_r1 = (unsigned long)arg; |
365 | regs.ARM_r2 = (unsigned long)fn; | 382 | regs.ARM_r2 = (unsigned long)fn; |
366 | regs.ARM_r3 = (unsigned long)do_exit; | 383 | regs.ARM_r3 = (unsigned long)kernel_thread_exit; |
367 | regs.ARM_pc = (unsigned long)kernel_thread_helper; | 384 | regs.ARM_pc = (unsigned long)kernel_thread_helper; |
368 | regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE; | 385 | regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE; |
369 | 386 | ||