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 | } |