Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[safe/jmp/linux-2.6] / arch / x86 / kernel / dumpstack.c
index 4325165..c89a386 100644 (file)
 #include <linux/bug.h>
 #include <linux/nmi.h>
 #include <linux/sysfs.h>
-#include <linux/ftrace.h>
 
 #include <asm/stacktrace.h>
 
 #include "dumpstack.h"
 
 int panic_on_unrecovered_nmi;
+int panic_on_io_nmi;
 unsigned int code_bytes = 64;
 int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
 static int die_counter;
@@ -101,7 +101,7 @@ print_context_stack(struct thread_info *tinfo,
                                frame = frame->next_frame;
                                bp = (unsigned long) frame;
                        } else {
-                               ops->address(data, addr, bp == 0);
+                               ops->address(data, addr, 0);
                        }
                        print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
                }
@@ -109,6 +109,32 @@ print_context_stack(struct thread_info *tinfo,
        }
        return bp;
 }
+EXPORT_SYMBOL_GPL(print_context_stack);
+
+unsigned long
+print_context_stack_bp(struct thread_info *tinfo,
+                      unsigned long *stack, unsigned long bp,
+                      const struct stacktrace_ops *ops, void *data,
+                      unsigned long *end, int *graph)
+{
+       struct stack_frame *frame = (struct stack_frame *)bp;
+       unsigned long *ret_addr = &frame->return_address;
+
+       while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) {
+               unsigned long addr = *ret_addr;
+
+               if (!__kernel_text_address(addr))
+                       break;
+
+               ops->address(data, addr, 1);
+               frame = frame->next_frame;
+               ret_addr = &frame->return_address;
+               print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
+       }
+
+       return (unsigned long)frame;
+}
+EXPORT_SYMBOL_GPL(print_context_stack_bp);
 
 
 static void
@@ -141,10 +167,11 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
 }
 
 static const struct stacktrace_ops print_trace_ops = {
-       .warning = print_trace_warning,
-       .warning_symbol = print_trace_warning_symbol,
-       .stack = print_trace_stack,
-       .address = print_trace_address,
+       .warning                = print_trace_warning,
+       .warning_symbol         = print_trace_warning_symbol,
+       .stack                  = print_trace_stack,
+       .address                = print_trace_address,
+       .walk_stack             = print_context_stack,
 };
 
 void
@@ -188,7 +215,7 @@ void dump_stack(void)
 }
 EXPORT_SYMBOL(dump_stack);
 
-static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
+static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 static int die_owner = -1;
 static unsigned int die_nest_count;
 
@@ -197,21 +224,16 @@ unsigned __kprobes long oops_begin(void)
        int cpu;
        unsigned long flags;
 
-       /* notify the hw-branch tracer so it may disable tracing and
-          add the last trace to the trace buffer -
-          the earlier this happens, the more useful the trace. */
-       trace_hw_branch_oops();
-
        oops_enter();
 
        /* racy, but better than risking deadlock. */
        raw_local_irq_save(flags);
        cpu = smp_processor_id();
-       if (!__raw_spin_trylock(&die_lock)) {
+       if (!arch_spin_trylock(&die_lock)) {
                if (cpu == die_owner)
                        /* nested oops. should stop eventually */;
                else
-                       __raw_spin_lock(&die_lock);
+                       arch_spin_lock(&die_lock);
        }
        die_nest_count++;
        die_owner = cpu;
@@ -231,7 +253,7 @@ void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
        die_nest_count--;
        if (!die_nest_count)
                /* Nest count reaches zero, release the lock. */
-               __raw_spin_unlock(&die_lock);
+               arch_spin_unlock(&die_lock);
        raw_local_irq_restore(flags);
        oops_exit();
 
@@ -268,11 +290,12 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
 
        show_registers(regs);
 #ifdef CONFIG_X86_32
-       sp = (unsigned long) (&regs->sp);
-       savesegment(ss, ss);
-       if (user_mode(regs)) {
+       if (user_mode_vm(regs)) {
                sp = regs->sp;
                ss = regs->ss & 0xffff;
+       } else {
+               sp = kernel_stack_pointer(regs);
+               savesegment(ss, ss);
        }
        printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
        print_symbol("%s", regs->ip);