2006-08-06 19:00:32

by Chuck Ebbert

[permalink] [raw]
Subject: [patch] i386: fix stuck unwind into kernel thread

We cannot unwind past kernel_thread_helper.

Signed-off-by: Chuck Ebbert <[email protected]>

---

On top of previous arch_unw_user_mode() patch;
to make this apply to vanilla: s/(unsigned long)_stext/PAGE_OFFSET/

arch/i386/kernel/process.c | 6 ++++--
include/asm-i386/processor.h | 2 ++
include/asm-i386/unwind.h | 10 +++++++---
3 files changed, 13 insertions(+), 5 deletions(-)

--- 2.6.18-rc3-d4.orig/arch/i386/kernel/process.c
+++ 2.6.18-rc3-d4/arch/i386/kernel/process.c
@@ -319,15 +319,17 @@ void show_regs(struct pt_regs * regs)
* function to call, and %edx containing
* the "args".
*/
-extern void kernel_thread_helper(void);
__asm__(".section .text\n"
".align 4\n"
- "kernel_thread_helper:\n\t"
+ "kernel_thread_helper:\n"
+ ".globl kernel_thread_helper\n\t"
"movl %edx,%eax\n\t"
"pushl %edx\n\t"
"call *%ebx\n\t"
"pushl %eax\n\t"
"call do_exit\n"
+ "kernel_thread_helper_end:\n"
+ ".globl kernel_thread_helper_end\n"
".previous");

/*
--- 2.6.18-rc3-d4.orig/include/asm-i386/processor.h
+++ 2.6.18-rc3-d4/include/asm-i386/processor.h
@@ -555,6 +555,8 @@ extern void prepare_to_copy(struct task_
* create a kernel thread without removing it from tasklists
*/
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+extern void kernel_thread_helper(void);
+extern void kernel_thread_helper_end(void);

extern unsigned long thread_saved_pc(struct task_struct *tsk);
void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack);
--- 2.6.18-rc3-d4.orig/include/asm-i386/unwind.h
+++ 2.6.18-rc3-d4/include/asm-i386/unwind.h
@@ -79,9 +79,13 @@ static inline int arch_unw_user_mode(con
are properly annotated (and tracked in UNW_REGISTER_INFO). */
return user_mode_vm(&info->regs);
#else
- return info->regs.eip < (unsigned long)_stext
- || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
- && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
+ unsigned long eip = info->regs.eip;
+
+ return eip < (unsigned long)_stext
+ || (eip >= __fix_to_virt(FIX_VDSO)
+ && eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
+ || (eip >= (unsigned long)kernel_thread_helper
+ && eip < (unsigned long)kernel_thread_helper_end)
|| info->regs.esp < PAGE_OFFSET;
#endif
}
--
Chuck


2006-08-07 08:06:48

by Jan Beulich

[permalink] [raw]
Subject: Re: [patch] i386: fix stuck unwind into kernel thread

>>> Chuck Ebbert <[email protected]> 06.08.06 20:56 >>>
>We cannot unwind past kernel_thread_helper.

Just as mentioned before - we shouldn't add endless special cases to the code that interprets the unwind
information, but rather fix the unwind information so that it properly reflect the actual state. Like in the
other case, the piece of code should be properly annotated, which would require it to be moved into
an assembly file (it escapes me why code like that was ever placed in a C file).

Jan

2006-08-07 08:11:36

by Andi Kleen

[permalink] [raw]
Subject: Re: [patch] i386: fix stuck unwind into kernel thread

On Monday 07 August 2006 10:07, Jan Beulich wrote:
> >>> Chuck Ebbert <[email protected]> 06.08.06 20:56 >>>
> >We cannot unwind past kernel_thread_helper.
>
> Just as mentioned before - we shouldn't add endless special cases to the code that interprets the unwind
> information, but rather fix the unwind information so that it properly reflect the actual state. Like in the
> other case, the piece of code should be properly annotated, which would require it to be moved into
> an assembly file (it escapes me why code like that was ever placed in a C file).

I can do that.

-Andi