um: Make stack trace reliable against kernel mode faults
[platform/adaptation/renesas_rcar/renesas_kernel.git] / arch / um / kernel / sysrq.c
index 33cc72e..7122bf9 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/sysrq.h>
+#include <os.h>
 
 struct stack_frame {
        struct stack_frame *next_frame;
@@ -48,29 +49,42 @@ static void print_stack_trace(unsigned long *sp, unsigned long bp)
 /*Stolen from arch/i386/kernel/traps.c */
 static const int kstack_depth_to_print = 24;
 
-static unsigned long get_frame_pointer(struct task_struct *task)
+static unsigned long get_frame_pointer(struct task_struct *task,
+                                      struct pt_regs *segv_regs)
 {
        if (!task || task == current)
-               return current_bp();
+               return segv_regs ? PT_REGS_BP(segv_regs) : current_bp();
        else
                return KSTK_EBP(task);
 }
 
+static unsigned long *get_stack_pointer(struct task_struct *task,
+                                       struct pt_regs *segv_regs)
+{
+       if (!task || task == current)
+               return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp();
+       else
+               return (unsigned long *)KSTK_ESP(task);
+}
+
 void show_stack(struct task_struct *task, unsigned long *stack)
 {
        unsigned long *sp = stack, bp = 0;
+       struct pt_regs *segv_regs = current->thread.segv_regs;
        int i;
 
+       if (!segv_regs && os_is_signal_stack()) {
+               printk(KERN_ERR "Received SIGSEGV in SIGSEGV handler,"
+                               " aborting stack trace!\n");
+               return;
+       }
+
 #ifdef CONFIG_FRAME_POINTER
-       bp = get_frame_pointer(task);
+       bp = get_frame_pointer(task, segv_regs);
 #endif
 
-       if (!stack) {
-               if (!task || task == current)
-                       sp = current_sp();
-               else
-                       sp = (unsigned long *)KSTK_ESP(task);
-       }
+       if (!stack)
+               sp = get_stack_pointer(task, segv_regs);
 
        printk(KERN_INFO "Stack:\n");
        stack = sp;