aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/dumpstack.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-01-04 19:17:33 -0500
committerTejun Heo <tj@kernel.org>2010-01-04 19:17:33 -0500
commit32032df6c2f6c9c6b2ada2ce42322231824f70c2 (patch)
treeb1ce838a37044bb38dfc128e2116ca35630e629a /arch/x86/kernel/dumpstack.c
parent22b737f4c75197372d64afc6ed1bccd58c00e549 (diff)
parentc5974b835a909ff15c3b7e6cf6789b5eb919f419 (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.c48
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}
112EXPORT_SYMBOL_GPL(print_context_stack);
113
114unsigned long
115print_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}
135EXPORT_SYMBOL_GPL(print_context_stack_bp);
112 136
113 137
114static void 138static void
@@ -141,10 +165,11 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
141} 165}
142 166
143static const struct stacktrace_ops print_trace_ops = { 167static 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
150void 175void
@@ -188,7 +213,7 @@ void dump_stack(void)
188} 213}
189EXPORT_SYMBOL(dump_stack); 214EXPORT_SYMBOL(dump_stack);
190 215
191static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED; 216static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED;
192static int die_owner = -1; 217static int die_owner = -1;
193static unsigned int die_nest_count; 218static 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) (&regs->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);