summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2009-06-19 16:43:08 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-06-19 16:44:23 +0100
commitfeb97c3644a560ffdf9a17c65b1df807b5b4432f (patch)
treed9c84b8ad646cbf43e20c9a96e5db25b4ccd4ec6 /arch/arm/kernel
parentc894ed6956f126d60d888e8efc5fb3a595ba89ae (diff)
downloadlinux-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.c19
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;