From 23126692e30ec22760e0ef932c3c2fff00d440bb Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 28 Sep 2006 19:15:33 +0900 Subject: [MIPS] Stacktrace build-fix and improvement Fix build error due to stacktrace API change. Now save_stack_trace() tries to save all kernel context, including interrupts and exception. Also some asm code are changed a bit so that we can detect the end of current context easily. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 37fda3d..af6ef2f 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -220,8 +220,8 @@ NESTED(except_vec_vi_handler, 0, sp) CLI TRACE_IRQS_OFF move a0, sp - jalr v0 - j ret_from_irq + PTR_LA ra, ret_from_irq + jr v0 END(except_vec_vi_handler) /* @@ -349,8 +349,8 @@ NESTED(nmi_handler, PT_SIZE, sp) .set at __BUILD_\verbose \exception move a0, sp - jal do_\handler - j ret_from_exception + PTR_LA ra, ret_from_exception + j do_\handler END(handle_\exception) .endm diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index f851d0c..676e6f6 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c @@ -13,7 +13,7 @@ * Save stack-backtrace addresses into a stack_trace buffer: */ static void save_raw_context_stack(struct stack_trace *trace, - unsigned int skip, unsigned long reg29) + unsigned long reg29) { unsigned long *sp = (unsigned long *)reg29; unsigned long addr; @@ -21,10 +21,10 @@ static void save_raw_context_stack(struct stack_trace *trace, while (!kstack_end(sp)) { addr = *sp++; if (__kernel_text_address(addr)) { - if (!skip) - trace->entries[trace->nr_entries++] = addr; + if (trace->skip > 0) + trace->skip--; else - skip--; + trace->entries[trace->nr_entries++] = addr; if (trace->nr_entries >= trace->max_entries) break; } @@ -32,37 +32,40 @@ static void save_raw_context_stack(struct stack_trace *trace, } static struct pt_regs * save_context_stack(struct stack_trace *trace, - unsigned int skip, struct task_struct *task, struct pt_regs *regs) + struct task_struct *task, struct pt_regs *regs) { unsigned long sp = regs->regs[29]; #ifdef CONFIG_KALLSYMS unsigned long ra = regs->regs[31]; unsigned long pc = regs->cp0_epc; + unsigned long stack_page = + (unsigned long)task_stack_page(task); extern void ret_from_irq(void); + extern void ret_from_exception(void); if (raw_show_trace || !__kernel_text_address(pc)) { - save_raw_context_stack(trace, skip, sp); + if (stack_page && sp >= stack_page && + sp <= stack_page + THREAD_SIZE - 32) + save_raw_context_stack(trace, sp); return NULL; } do { - if (!skip) - trace->entries[trace->nr_entries++] = pc; + if (trace->skip > 0) + trace->skip--; else - skip--; + trace->entries[trace->nr_entries++] = pc; if (trace->nr_entries >= trace->max_entries) break; /* * If we reached the bottom of interrupt context, * return saved pt_regs. */ - if (pc == (unsigned long)ret_from_irq) { - unsigned long stack_page = - (unsigned long)task_stack_page(task); - if (!stack_page || - sp < stack_page || - sp > stack_page + THREAD_SIZE - 32) - break; - return (struct pt_regs *)sp; + if (pc == (unsigned long)ret_from_irq || + pc == (unsigned long)ret_from_exception) { + if (stack_page && sp >= stack_page && + sp <= stack_page + THREAD_SIZE - 32) + return (struct pt_regs *)sp; + break; } pc = unwind_stack(task, &sp, pc, ra); ra = 0; @@ -76,12 +79,8 @@ static struct pt_regs * save_context_stack(struct stack_trace *trace, /* * Save stack-backtrace addresses into a stack_trace buffer. - * If all_contexts is set, all contexts (hardirq, softirq and process) - * are saved. If not set then only the current context is saved. */ -void save_stack_trace(struct stack_trace *trace, - struct task_struct *task, int all_contexts, - unsigned int skip) +void save_stack_trace(struct stack_trace *trace, struct task_struct *task) { struct pt_regs dummyregs; struct pt_regs *regs = &dummyregs; @@ -99,13 +98,8 @@ void save_stack_trace(struct stack_trace *trace, } while (1) { - regs = save_context_stack(trace, skip, task, regs); - if (!all_contexts || !regs || - trace->nr_entries >= trace->max_entries) - break; - trace->entries[trace->nr_entries++] = ULONG_MAX; - if (trace->nr_entries >= trace->max_entries) + regs = save_context_stack(trace, task, regs); + if (!regs || trace->nr_entries >= trace->max_entries) break; - skip = 0; } } diff --git a/arch/mips/mm/tlbex-fault.S b/arch/mips/mm/tlbex-fault.S index 9e7f417..e99eaa1 100644 --- a/arch/mips/mm/tlbex-fault.S +++ b/arch/mips/mm/tlbex-fault.S @@ -19,8 +19,8 @@ move a0, sp REG_S a2, PT_BVADDR(sp) li a1, \write - jal do_page_fault - j ret_from_exception + PTR_LA ra, ret_from_exception + j do_page_fault END(tlb_do_page_fault_\write) .endm -- cgit v0.10.2