diff options
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_c return } static int __devexit rdc321x_gpio_remove(struct platform_device *pdev) { int ret; struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev); ret = gpiochip_remove(&rdc321x_gpio_dev->chip); if (ret) dev_err(&pdev->dev, "failed to unregister chip\n"); kfree(rdc321x_gpio_dev); platform_set_drvdata(pdev, NULL); return ret; } static struct platform_driver rdc321x_gpio_driver = { .driver.name = "rdc321x-gpio", .driver.owner = THIS_MODULE, .probe = rdc321x_gpio_probe, .remove = __devexit_p(rdc321x_gpio_remove), }; module_platform_driver(rdc321x_gpio_driver); MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); MODULE_DESCRIPTION("RDC321x GPIO driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:rdc321x-gpio"); | 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); | |