Hello, Here:
+ /* + * On Book E and perhaps other processsors, singlestep is handled on + * the critical exception stack. This causes current_thread_info() + * to fail, since it it locates the thread_info by masking off + * the low bits of the current stack pointer. We work around + * this issue by copying the thread_info from the kernel stack + * before calling kgdb_handle_exception, and copying it back + * afterwards. On most processors the copy is avoided since + * exception_thread_info == thread_info. + */ + thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1)); + exception_thread_info = current_thread_info(); - calling current_thread_info() is incorrect, as it assumes 8K stack, but for Book E and ppc4xx the critical exception stack is 4K and is 4K-aligned (see head_4xx.S, head_44x.S and head_fsl_booke.S in arch/ppc/kernel/). So depending on the actual kernel layout/configuration exception_thread_info could point 4K below the critical exception stack. Even if (exception_stack_bottom & ~(THREAD_SIZE-1)) != 0 (i.e. the stack is NOT 8K aligned) everything seems to work OK in most cases (the overwritten data are not so critical?). But we did encountered one case when trying to single step from the default breakpoint made the kernel to hang. There are several possible ways to fix that: - make the critical exception stack to be 8K aligned: ===================================================================================== diff -upr a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S --- a/arch/ppc/kernel/head_4xx.S 2006-07-05 20:23:51.000000000 +0400 +++ b/arch/ppc/kernel/head_4xx.S 2006-07-05 19:54:51.000000000 +0400 @@ -1001,7 +1001,7 @@ swapper_pg_dir: /* Stack for handling critical exceptions from kernel mode */ .section .bss - .align 12 + .align 13 exception_stack_bottom: .space 4096 critical_stack_top: ===================================================================================== - replace call to current_thread_info() with: ===================================================================================== diff -upr a/arch/ppc/kernel/kgdb.c b/arch/ppc/kernel/kgdb.c --- a/arch/ppc/kernel/kgdb.c 2006-07-05 19:53:29.000000000 +0400 +++ b/arch/ppc/kernel/kgdb.c 2006-07-05 20:18:06.000000000 +0400 @@ -106,29 +106,32 @@ static int kgdb_breakpoint(struct pt_reg static int kgdb_singlestep(struct pt_regs *regs) { struct thread_info *thread_info, *exception_thread_info; + register unsigned long sp asm("r1"); if (user_mode(regs)) return 0; + +#if defined(CONFIG_40x) || defined(CONFIG_44x) || defined(CONFIG_E500) /* - * On Book E and perhaps other processsors, singlestep is handled on + * On Book E, ppc40x, and ppc44x, singlestep is handled on * the critical exception stack. This causes current_thread_info() - * to fail, since it it locates the thread_info by masking off + * to fail, since it locates the thread_info by masking off * the low bits of the current stack pointer. We work around * this issue by copying the thread_info from the kernel stack * before calling kgdb_handle_exception, and copying it back - * afterwards. On most processors the copy is avoided since - * exception_thread_info == thread_info. + * afterwards. */ +#define CRIT_STACK_SIZE 0x1000 /* 4kB */ thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1)); - exception_thread_info = current_thread_info(); - - if (thread_info != exception_thread_info) - memcpy(exception_thread_info, thread_info, sizeof *thread_info); + exception_thread_info = (struct thread_info *)(sp & ~(CRIT_STACK_SIZE-1)); + memcpy(exception_thread_info, thread_info, sizeof *thread_info); kgdb_handle_exception(0, SIGTRAP, 0, regs); - if (thread_info != exception_thread_info) - memcpy(thread_info, exception_thread_info, sizeof *thread_info); + memcpy(thread_info, exception_thread_info, sizeof *thread_info); +#else + kgdb_handle_exception(0, SIGTRAP, 0, regs); +#endif return 1; } ===================================================================================== or ===================================================================================== diff -upr a/arch/ppc/kernel/kgdb.c c/arch/ppc/kernel/kgdb.c --- a/arch/ppc/kernel/kgdb.c 2006-07-05 19:53:29.000000000 +0400 +++ c/arch/ppc/kernel/kgdb.c 2006-07-05 20:17:51.000000000 +0400 @@ -110,9 +110,9 @@ static int kgdb_singlestep(struct pt_reg if (user_mode(regs)) return 0; /* - * On Book E and perhaps other processsors, singlestep is handled on + * On Book E and perhaps other processors, singlestep is handled on * the critical exception stack. This causes current_thread_info() - * to fail, since it it locates the thread_info by masking off + * to fail, since it locates the thread_info by masking off * the low bits of the current stack pointer. We work around * this issue by copying the thread_info from the kernel stack * before calling kgdb_handle_exception, and copying it back @@ -122,8 +122,14 @@ static int kgdb_singlestep(struct pt_reg thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1)); exception_thread_info = current_thread_info(); - if (thread_info != exception_thread_info) + if (thread_info != exception_thread_info) { + #define CRIT_STACK_SIZE 0x1000 + register unsigned long sp asm("r1"); + + exception_thread_info = + (struct thread_info *)(sp & ~(CRIT_STACK_SIZE-1)); memcpy(exception_thread_info, thread_info, sizeof *thread_info); + } kgdb_handle_exception(0, SIGTRAP, 0, regs); ===================================================================================== To say the true, I don't like all the three (these are just to illustrate the idea). Seems some general cleanup in handling the stack size would make sense. Suggestions? Thanks, Andrei Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Kgdb-bugreport mailing list Kgdb-bugreport@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport