aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/dumpstack.c
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2010-01-08 03:26:34 -0500
committerJaroslav Kysela <perex@perex.cz>2010-01-08 03:26:34 -0500
commit1cb4f624ea38361b6397966470f0a1bed5532483 (patch)
tree418b05ddc854b09d64f7d5ee0c78875e42b5f151 /arch/x86/kernel/dumpstack.c
parent444c1953d496d272208902ff7010dc70d1f887f0 (diff)
parent2c1f1895ef2aa8f0e5497893eff71304aef332e1 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into fixes
Diffstat (limited to 'arch/x86/kernel/dumpstack.c')
-rw-r--r--arch/x86/kernel/dumpstack.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index b8ce165dde5d..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