diff options
author | Tejun Heo <tj@kernel.org> | 2010-01-04 19:17:33 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-01-04 19:17:33 -0500 |
commit | 32032df6c2f6c9c6b2ada2ce42322231824f70c2 (patch) | |
tree | b1ce838a37044bb38dfc128e2116ca35630e629a /arch/x86/kernel/dumpstack.c | |
parent | 22b737f4c75197372d64afc6ed1bccd58c00e549 (diff) | |
parent | c5974b835a909ff15c3b7e6cf6789b5eb919f419 (diff) |
Merge branch 'master' into percpu
Conflicts:
arch/powerpc/platforms/pseries/hvCall.S
include/linux/percpu.h
Diffstat (limited to 'arch/x86/kernel/dumpstack.c')
-rw-r--r-- | arch/x86/kernel/dumpstack.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 2d8a371d4339..c56bc2873030 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
@@ -109,6 +109,30 @@ print_context_stack(struct thread_info *tinfo, | |||
109 | } | 109 | } |
110 | return bp; | 110 | return bp; |
111 | } | 111 | } |
112 | EXPORT_SYMBOL_GPL(print_context_stack); | ||
113 | |||
114 | unsigned long | ||
115 | print_context_stack_bp(struct thread_info *tinfo, | ||
116 | unsigned long *stack, unsigned long bp, | ||
117 | const struct stacktrace_ops *ops, void *data, | ||
118 | unsigned long *end, int *graph) | ||
119 | { | ||
120 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
121 | unsigned long *ret_addr = &frame->return_address; | ||
122 | |||
123 | while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) { | ||
124 | unsigned long addr = *ret_addr; | ||
125 | |||
126 | if (__kernel_text_address(addr)) { | ||
127 | ops->address(data, addr, 1); | ||
128 | frame = frame->next_frame; | ||
129 | ret_addr = &frame->return_address; | ||
130 | print_ftrace_graph_addr(addr, data, ops, tinfo, graph); | ||
131 | } | ||
132 | } | ||
133 | return (unsigned long)frame; | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(print_context_stack_bp); | ||
112 | 136 | ||
113 | 137 | ||
114 | static void | 138 | static void |
@@ -141,10 +165,11 @@ static void print_trace_address(void *data, unsigned long addr, int reliable) | |||
141 | } | 165 | } |
142 | 166 | ||
143 | static const struct stacktrace_ops print_trace_ops = { | 167 | static const struct stacktrace_ops print_trace_ops = { |
144 | .warning = print_trace_warning, | 168 | .warning = print_trace_warning, |
145 | .warning_symbol = print_trace_warning_symbol, | 169 | .warning_symbol = print_trace_warning_symbol, |
146 | .stack = print_trace_stack, | 170 | .stack = print_trace_stack, |
147 | .address = print_trace_address, | 171 | .address = print_trace_address, |
172 | .walk_stack = print_context_stack, | ||
148 | }; | 173 | }; |
149 | 174 | ||
150 | void | 175 | void |
@@ -188,7 +213,7 @@ void dump_stack(void) | |||
188 | } | 213 | } |
189 | EXPORT_SYMBOL(dump_stack); | 214 | EXPORT_SYMBOL(dump_stack); |
190 | 215 | ||
191 | static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED; | 216 | static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; |
192 | static int die_owner = -1; | 217 | static int die_owner = -1; |
193 | static unsigned int die_nest_count; | 218 | static unsigned int die_nest_count; |
194 | 219 | ||
@@ -207,11 +232,11 @@ unsigned __kprobes long oops_begin(void) | |||
207 | /* racy, but better than risking deadlock. */ | 232 | /* racy, but better than risking deadlock. */ |
208 | raw_local_irq_save(flags); | 233 | raw_local_irq_save(flags); |
209 | cpu = smp_processor_id(); | 234 | cpu = smp_processor_id(); |
210 | if (!__raw_spin_trylock(&die_lock)) { | 235 | if (!arch_spin_trylock(&die_lock)) { |
211 | if (cpu == die_owner) | 236 | if (cpu == die_owner) |
212 | /* nested oops. should stop eventually */; | 237 | /* nested oops. should stop eventually */; |
213 | else | 238 | else |
214 | __raw_spin_lock(&die_lock); | 239 | arch_spin_lock(&die_lock); |
215 | } | 240 | } |
216 | die_nest_count++; | 241 | die_nest_count++; |
217 | die_owner = cpu; | 242 | die_owner = cpu; |
@@ -231,7 +256,7 @@ void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) | |||
231 | die_nest_count--; | 256 | die_nest_count--; |
232 | if (!die_nest_count) | 257 | if (!die_nest_count) |
233 | /* Nest count reaches zero, release the lock. */ | 258 | /* Nest count reaches zero, release the lock. */ |
234 | __raw_spin_unlock(&die_lock); | 259 | arch_spin_unlock(&die_lock); |
235 | raw_local_irq_restore(flags); | 260 | raw_local_irq_restore(flags); |
236 | oops_exit(); | 261 | oops_exit(); |
237 | 262 | ||
@@ -268,11 +293,12 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err) | |||
268 | 293 | ||
269 | show_registers(regs); | 294 | show_registers(regs); |
270 | #ifdef CONFIG_X86_32 | 295 | #ifdef CONFIG_X86_32 |
271 | sp = (unsigned long) (®s->sp); | 296 | if (user_mode_vm(regs)) { |
272 | savesegment(ss, ss); | ||
273 | if (user_mode(regs)) { | ||
274 | sp = regs->sp; | 297 | sp = regs->sp; |
275 | ss = regs->ss & 0xffff; | 298 | ss = regs->ss & 0xffff; |
299 | } else { | ||
300 | sp = kernel_stack_pointer(regs); | ||
301 | savesegment(ss, ss); | ||
276 | } | 302 | } |
277 | printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip); | 303 | printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip); |
278 | print_symbol("%s", regs->ip); | 304 | print_symbol("%s", regs->ip); |