diff options
| -rw-r--r-- | arch/mips/kernel/genex.S | 8 | ||||
| -rw-r--r-- | arch/mips/kernel/stacktrace.c | 52 | ||||
| -rw-r--r-- | arch/mips/mm/tlbex-fault.S | 4 |
3 files changed, 29 insertions, 35 deletions
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 37fda3dcdfc5..af6ef2fd8300 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S | |||
| @@ -220,8 +220,8 @@ NESTED(except_vec_vi_handler, 0, sp) | |||
| 220 | CLI | 220 | CLI |
| 221 | TRACE_IRQS_OFF | 221 | TRACE_IRQS_OFF |
| 222 | move a0, sp | 222 | move a0, sp |
| 223 | jalr v0 | 223 | PTR_LA ra, ret_from_irq |
| 224 | j ret_from_irq | 224 | jr v0 |
| 225 | END(except_vec_vi_handler) | 225 | END(except_vec_vi_handler) |
| 226 | 226 | ||
| 227 | /* | 227 | /* |
| @@ -349,8 +349,8 @@ NESTED(nmi_handler, PT_SIZE, sp) | |||
| 349 | .set at | 349 | .set at |
| 350 | __BUILD_\verbose \exception | 350 | __BUILD_\verbose \exception |
| 351 | move a0, sp | 351 | move a0, sp |
| 352 | jal do_\handler | 352 | PTR_LA ra, ret_from_exception |
| 353 | j ret_from_exception | 353 | j do_\handler |
| 354 | END(handle_\exception) | 354 | END(handle_\exception) |
| 355 | .endm | 355 | .endm |
| 356 | 356 | ||
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index f851d0cc245f..676e6f69d24b 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | * Save stack-backtrace addresses into a stack_trace buffer: | 13 | * Save stack-backtrace addresses into a stack_trace buffer: |
| 14 | */ | 14 | */ |
| 15 | static void save_raw_context_stack(struct stack_trace *trace, | 15 | static void save_raw_context_stack(struct stack_trace *trace, |
| 16 | unsigned int skip, unsigned long reg29) | 16 | unsigned long reg29) |
| 17 | { | 17 | { |
| 18 | unsigned long *sp = (unsigned long *)reg29; | 18 | unsigned long *sp = (unsigned long *)reg29; |
| 19 | unsigned long addr; | 19 | unsigned long addr; |
| @@ -21,10 +21,10 @@ static void save_raw_context_stack(struct stack_trace *trace, | |||
| 21 | while (!kstack_end(sp)) { | 21 | while (!kstack_end(sp)) { |
| 22 | addr = *sp++; | 22 | addr = *sp++; |
| 23 | if (__kernel_text_address(addr)) { | 23 | if (__kernel_text_address(addr)) { |
| 24 | if (!skip) | 24 | if (trace->skip > 0) |
| 25 | trace->entries[trace->nr_entries++] = addr; | 25 | trace->skip--; |
| 26 | else | 26 | else |
| 27 | skip--; | 27 | trace->entries[trace->nr_entries++] = addr; |
| 28 | if (trace->nr_entries >= trace->max_entries) | 28 | if (trace->nr_entries >= trace->max_entries) |
| 29 | break; | 29 | break; |
| 30 | } | 30 | } |
| @@ -32,37 +32,40 @@ static void save_raw_context_stack(struct stack_trace *trace, | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static struct pt_regs * save_context_stack(struct stack_trace *trace, | 34 | static struct pt_regs * save_context_stack(struct stack_trace *trace, |
| 35 | unsigned int skip, struct task_struct *task, struct pt_regs *regs) | 35 | struct task_struct *task, struct pt_regs *regs) |
| 36 | { | 36 | { |
| 37 | unsigned long sp = regs->regs[29]; | 37 | unsigned long sp = regs->regs[29]; |
| 38 | #ifdef CONFIG_KALLSYMS | 38 | #ifdef CONFIG_KALLSYMS |
| 39 | unsigned long ra = regs->regs[31]; | 39 | unsigned long ra = regs->regs[31]; |
| 40 | unsigned long pc = regs->cp0_epc; | 40 | unsigned long pc = regs->cp0_epc; |
| 41 | unsigned long stack_page = | ||
| 42 | (unsigned long)task_stack_page(task); | ||
| 41 | extern void ret_from_irq(void); | 43 | extern void ret_from_irq(void); |
| 44 | extern void ret_from_exception(void); | ||
| 42 | 45 | ||
| 43 | if (raw_show_trace || !__kernel_text_address(pc)) { | 46 | if (raw_show_trace || !__kernel_text_address(pc)) { |
| 44 | save_raw_context_stack(trace, skip, sp); | 47 | if (stack_page && sp >= stack_page && |
| 48 | sp <= stack_page + THREAD_SIZE - 32) | ||
| 49 | save_raw_context_stack(trace, sp); | ||
| 45 | return NULL; | 50 | return NULL; |
| 46 | } | 51 | } |
| 47 | do { | 52 | do { |
| 48 | if (!skip) | 53 | if (trace->skip > 0) |
| 49 | trace->entries[trace->nr_entries++] = pc; | 54 | trace->skip--; |
| 50 | else | 55 | else |
| 51 | skip--; | 56 | trace->entries[trace->nr_entries++] = pc; |
| 52 | if (trace->nr_entries >= trace->max_entries) | 57 | if (trace->nr_entries >= trace->max_entries) |
| 53 | break; | 58 | break; |
| 54 | /* | 59 | /* |
| 55 | * If we reached the bottom of interrupt context, | 60 | * If we reached the bottom of interrupt context, |
| 56 | * return saved pt_regs. | 61 | * return saved pt_regs. |
| 57 | */ | 62 | */ |
| 58 | if (pc == (unsigned long)ret_from_irq) { | 63 | if (pc == (unsigned long)ret_from_irq || |
| 59 | unsigned long stack_page = | 64 | pc == (unsigned long)ret_from_exception) { |
| 60 | (unsigned long)task_stack_page(task); | 65 | if (stack_page && sp >= stack_page && |
| 61 | if (!stack_page || | 66 | sp <= stack_page + THREAD_SIZE - 32) |
| 62 | sp < stack_page || | 67 | return (struct pt_regs *)sp; |
| 63 | sp > stack_page + THREAD_SIZE - 32) | 68 | break; |
| 64 | break; | ||
| 65 | return (struct pt_regs *)sp; | ||
| 66 | } | 69 | } |
| 67 | pc = unwind_stack(task, &sp, pc, ra); | 70 | pc = unwind_stack(task, &sp, pc, ra); |
| 68 | ra = 0; | 71 | ra = 0; |
| @@ -76,12 +79,8 @@ static struct pt_regs * save_context_stack(struct stack_trace *trace, | |||
| 76 | 79 | ||
| 77 | /* | 80 | /* |
| 78 | * Save stack-backtrace addresses into a stack_trace buffer. | 81 | * Save stack-backtrace addresses into a stack_trace buffer. |
| 79 | * If all_contexts is set, all contexts (hardirq, softirq and process) | ||
| 80 | * are saved. If not set then only the current context is saved. | ||
| 81 | */ | 82 | */ |
| 82 | void save_stack_trace(struct stack_trace *trace, | 83 | void save_stack_trace(struct stack_trace *trace, struct task_struct *task) |
| 83 | struct task_struct *task, int all_contexts, | ||
| 84 | unsigned int skip) | ||
| 85 | { | 84 | { |
| 86 | struct pt_regs dummyregs; | 85 | struct pt_regs dummyregs; |
| 87 | struct pt_regs *regs = &dummyregs; | 86 | struct pt_regs *regs = &dummyregs; |
| @@ -99,13 +98,8 @@ void save_stack_trace(struct stack_trace *trace, | |||
| 99 | } | 98 | } |
| 100 | 99 | ||
| 101 | while (1) { | 100 | while (1) { |
| 102 | regs = save_context_stack(trace, skip, task, regs); | 101 | regs = save_context_stack(trace, task, regs); |
| 103 | if (!all_contexts || !regs || | 102 | if (!regs || trace->nr_entries >= trace->max_entries) |
| 104 | trace->nr_entries >= trace->max_entries) | ||
| 105 | break; | ||
| 106 | trace->entries[trace->nr_entries++] = ULONG_MAX; | ||
| 107 | if (trace->nr_entries >= trace->max_entries) | ||
| 108 | break; | 103 | break; |
| 109 | skip = 0; | ||
| 110 | } | 104 | } |
| 111 | } | 105 | } |
diff --git a/arch/mips/mm/tlbex-fault.S b/arch/mips/mm/tlbex-fault.S index 9e7f4175b493..e99eaa1fbedc 100644 --- a/arch/mips/mm/tlbex-fault.S +++ b/arch/mips/mm/tlbex-fault.S | |||
| @@ -19,8 +19,8 @@ | |||
| 19 | move a0, sp | 19 | move a0, sp |
| 20 | REG_S a2, PT_BVADDR(sp) | 20 | REG_S a2, PT_BVADDR(sp) |
| 21 | li a1, \write | 21 | li a1, \write |
| 22 | jal do_page_fault | 22 | PTR_LA ra, ret_from_exception |
| 23 | j ret_from_exception | 23 | j do_page_fault |
| 24 | END(tlb_do_page_fault_\write) | 24 | END(tlb_do_page_fault_\write) |
| 25 | .endm | 25 | .endm |
| 26 | 26 | ||
