diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-06-19 16:43:08 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-06-19 16:44:23 +0100 |
commit | feb97c3644a560ffdf9a17c65b1df807b5b4432f (patch) | |
tree | d9c84b8ad646cbf43e20c9a96e5db25b4ccd4ec6 /arch/arm/kernel | |
parent | c894ed6956f126d60d888e8efc5fb3a595ba89ae (diff) | |
download | linux-feb97c3644a560ffdf9a17c65b1df807b5b4432f.tar.bz2 |
[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/kernel')
-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" " .size kernel_thread_helper, . - kernel_thread_helper\n" " .previous"); +#ifdef CONFIG_ARM_UNWIND +extern void kernel_thread_exit(long code); +asm( ".section .text\n" +" .align\n" +" .type kernel_thread_exit, #function\n" +"kernel_thread_exit:\n" +" .fnstart\n" +" .cantunwind\n" +" bl do_exit\n" +" nop\n" +" .fnend\n" +" .size kernel_thread_exit, . - kernel_thread_exit\n" +" .previous"); +#else +#define kernel_thread_exit do_exit +#endif + /* * Create a kernel thread. */ @@ -363,7 +380,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) regs.ARM_r1 = (unsigned long)arg; regs.ARM_r2 = (unsigned long)fn; - regs.ARM_r3 = (unsigned long)do_exit; + regs.ARM_r3 = (unsigned long)kernel_thread_exit; regs.ARM_pc = (unsigned long)kernel_thread_helper; regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE; |