diff options
Diffstat (limited to 'arch/mips/kernel/stacktrace.c')
| -rw-r--r-- | arch/mips/kernel/stacktrace.c | 32 |
1 files changed, 6 insertions, 26 deletions
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c index 676e6f69d24b..4aabe526a68e 100644 --- a/arch/mips/kernel/stacktrace.c +++ b/arch/mips/kernel/stacktrace.c | |||
| @@ -31,23 +31,21 @@ static void save_raw_context_stack(struct stack_trace *trace, | |||
| 31 | } | 31 | } |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static struct pt_regs * save_context_stack(struct stack_trace *trace, | 34 | static void save_context_stack(struct stack_trace *trace, |
| 35 | 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); | ||
| 43 | extern void ret_from_irq(void); | ||
| 44 | extern void ret_from_exception(void); | ||
| 45 | 41 | ||
| 46 | if (raw_show_trace || !__kernel_text_address(pc)) { | 42 | if (raw_show_trace || !__kernel_text_address(pc)) { |
| 43 | unsigned long stack_page = | ||
| 44 | (unsigned long)task_stack_page(task); | ||
| 47 | if (stack_page && sp >= stack_page && | 45 | if (stack_page && sp >= stack_page && |
| 48 | sp <= stack_page + THREAD_SIZE - 32) | 46 | sp <= stack_page + THREAD_SIZE - 32) |
| 49 | save_raw_context_stack(trace, sp); | 47 | save_raw_context_stack(trace, sp); |
| 50 | return NULL; | 48 | return; |
| 51 | } | 49 | } |
| 52 | do { | 50 | do { |
| 53 | if (trace->skip > 0) | 51 | if (trace->skip > 0) |
| @@ -56,25 +54,11 @@ static struct pt_regs * save_context_stack(struct stack_trace *trace, | |||
| 56 | trace->entries[trace->nr_entries++] = pc; | 54 | trace->entries[trace->nr_entries++] = pc; |
| 57 | if (trace->nr_entries >= trace->max_entries) | 55 | if (trace->nr_entries >= trace->max_entries) |
| 58 | break; | 56 | break; |
| 59 | /* | 57 | pc = unwind_stack(task, &sp, pc, &ra); |
| 60 | * If we reached the bottom of interrupt context, | ||
| 61 | * return saved pt_regs. | ||
| 62 | */ | ||
| 63 | if (pc == (unsigned long)ret_from_irq || | ||
| 64 | pc == (unsigned long)ret_from_exception) { | ||
| 65 | if (stack_page && sp >= stack_page && | ||
| 66 | sp <= stack_page + THREAD_SIZE - 32) | ||
| 67 | return (struct pt_regs *)sp; | ||
| 68 | break; | ||
| 69 | } | ||
| 70 | pc = unwind_stack(task, &sp, pc, ra); | ||
| 71 | ra = 0; | ||
| 72 | } while (pc); | 58 | } while (pc); |
| 73 | #else | 59 | #else |
| 74 | save_raw_context_stack(sp); | 60 | save_raw_context_stack(sp); |
| 75 | #endif | 61 | #endif |
| 76 | |||
| 77 | return NULL; | ||
| 78 | } | 62 | } |
| 79 | 63 | ||
| 80 | /* | 64 | /* |
| @@ -97,9 +81,5 @@ void save_stack_trace(struct stack_trace *trace, struct task_struct *task) | |||
| 97 | prepare_frametrace(regs); | 81 | prepare_frametrace(regs); |
| 98 | } | 82 | } |
| 99 | 83 | ||
| 100 | while (1) { | 84 | save_context_stack(trace, task, regs); |
| 101 | regs = save_context_stack(trace, task, regs); | ||
| 102 | if (!regs || trace->nr_entries >= trace->max_entries) | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | } | 85 | } |
