linux/arch/s390/kernel/dumpstack.c
<<
>>
Prefs
   1/*
   2 * Stack dumping functions
   3 *
   4 *  Copyright IBM Corp. 1999, 2013
   5 */
   6
   7#include <linux/kallsyms.h>
   8#include <linux/hardirq.h>
   9#include <linux/kprobes.h>
  10#include <linux/utsname.h>
  11#include <linux/export.h>
  12#include <linux/kdebug.h>
  13#include <linux/ptrace.h>
  14#include <linux/mm.h>
  15#include <linux/module.h>
  16#include <linux/sched.h>
  17#include <asm/processor.h>
  18#include <asm/debug.h>
  19#include <asm/dis.h>
  20#include <asm/ipl.h>
  21
  22/*
  23 * For dump_trace we have tree different stack to consider:
  24 *   - the panic stack which is used if the kernel stack has overflown
  25 *   - the asynchronous interrupt stack (cpu related)
  26 *   - the synchronous kernel stack (process related)
  27 * The stack trace can start at any of the three stacks and can potentially
  28 * touch all of them. The order is: panic stack, async stack, sync stack.
  29 */
  30static unsigned long
  31__dump_trace(dump_trace_func_t func, void *data, unsigned long sp,
  32             unsigned long low, unsigned long high)
  33{
  34        struct stack_frame *sf;
  35        struct pt_regs *regs;
  36
  37        while (1) {
  38                if (sp < low || sp > high - sizeof(*sf))
  39                        return sp;
  40                sf = (struct stack_frame *) sp;
  41                /* Follow the backchain. */
  42                while (1) {
  43                        if (func(data, sf->gprs[8]))
  44                                return sp;
  45                        low = sp;
  46                        sp = sf->back_chain;
  47                        if (!sp)
  48                                break;
  49                        if (sp <= low || sp > high - sizeof(*sf))
  50                                return sp;
  51                        sf = (struct stack_frame *) sp;
  52                }
  53                /* Zero backchain detected, check for interrupt frame. */
  54                sp = (unsigned long) (sf + 1);
  55                if (sp <= low || sp > high - sizeof(*regs))
  56                        return sp;
  57                regs = (struct pt_regs *) sp;
  58                if (!user_mode(regs)) {
  59                        if (func(data, regs->psw.addr))
  60                                return sp;
  61                }
  62                low = sp;
  63                sp = regs->gprs[15];
  64        }
  65}
  66
  67void dump_trace(dump_trace_func_t func, void *data, struct task_struct *task,
  68                unsigned long sp)
  69{
  70        unsigned long frame_size;
  71
  72        frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
  73#ifdef CONFIG_CHECK_STACK
  74        sp = __dump_trace(func, data, sp,
  75                          S390_lowcore.panic_stack + frame_size - 4096,
  76                          S390_lowcore.panic_stack + frame_size);
  77#endif
  78        sp = __dump_trace(func, data, sp,
  79                          S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
  80                          S390_lowcore.async_stack + frame_size);
  81        if (task)
  82                __dump_trace(func, data, sp,
  83                             (unsigned long)task_stack_page(task),
  84                             (unsigned long)task_stack_page(task) + THREAD_SIZE);
  85        else
  86                __dump_trace(func, data, sp,
  87                             S390_lowcore.thread_info,
  88                             S390_lowcore.thread_info + THREAD_SIZE);
  89}
  90EXPORT_SYMBOL_GPL(dump_trace);
  91
  92struct return_address_data {
  93        unsigned long address;
  94        int depth;
  95};
  96
  97static int __return_address(void *data, unsigned long address)
  98{
  99        struct return_address_data *rd = data;
 100
 101        if (rd->depth--)
 102                return 0;
 103        rd->address = address;
 104        return 1;
 105}
 106
 107unsigned long return_address(int depth)
 108{
 109        struct return_address_data rd = { .depth = depth + 2 };
 110
 111        dump_trace(__return_address, &rd, NULL, current_stack_pointer());
 112        return rd.address;
 113}
 114EXPORT_SYMBOL_GPL(return_address);
 115
 116static int show_address(void *data, unsigned long address)
 117{
 118        printk("([<%016lx>] %pSR)\n", address, (void *)address);
 119        return 0;
 120}
 121
 122static void show_trace(struct task_struct *task, unsigned long sp)
 123{
 124        if (!sp)
 125                sp = task ? task->thread.ksp : current_stack_pointer();
 126        printk("Call Trace:\n");
 127        dump_trace(show_address, NULL, task, sp);
 128        if (!task)
 129                task = current;
 130        debug_show_held_locks(task);
 131}
 132
 133void show_stack(struct task_struct *task, unsigned long *sp)
 134{
 135        unsigned long *stack;
 136        int i;
 137
 138        stack = sp;
 139        if (!stack) {
 140                if (!task)
 141                        stack = (unsigned long *)current_stack_pointer();
 142                else
 143                        stack = (unsigned long *)task->thread.ksp;
 144        }
 145        for (i = 0; i < 20; i++) {
 146                if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
 147                        break;
 148                if ((i * sizeof(long) % 32) == 0)
 149                        printk("%s       ", i == 0 ? "" : "\n");
 150                printk("%016lx ", *stack++);
 151        }
 152        printk("\n");
 153        show_trace(task, (unsigned long)sp);
 154}
 155
 156static void show_last_breaking_event(struct pt_regs *regs)
 157{
 158        printk("Last Breaking-Event-Address:\n");
 159        printk(" [<%016lx>] %pSR\n", regs->args[0], (void *)regs->args[0]);
 160}
 161
 162void show_registers(struct pt_regs *regs)
 163{
 164        struct psw_bits *psw = &psw_bits(regs->psw);
 165        char *mode;
 166
 167        mode = user_mode(regs) ? "User" : "Krnl";
 168        printk("%s PSW : %p %p", mode, (void *)regs->psw.mask, (void *)regs->psw.addr);
 169        if (!user_mode(regs))
 170                printk(" (%pSR)", (void *)regs->psw.addr);
 171        printk("\n");
 172        printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
 173               "P:%x AS:%x CC:%x PM:%x", psw->r, psw->t, psw->i, psw->e,
 174               psw->key, psw->m, psw->w, psw->p, psw->as, psw->cc, psw->pm);
 175        printk(" RI:%x EA:%x", psw->ri, psw->eaba);
 176        printk("\n%s GPRS: %016lx %016lx %016lx %016lx\n", mode,
 177               regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
 178        printk("           %016lx %016lx %016lx %016lx\n",
 179               regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
 180        printk("           %016lx %016lx %016lx %016lx\n",
 181               regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
 182        printk("           %016lx %016lx %016lx %016lx\n",
 183               regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
 184        show_code(regs);
 185}
 186
 187void show_regs(struct pt_regs *regs)
 188{
 189        show_regs_print_info(KERN_DEFAULT);
 190        show_registers(regs);
 191        /* Show stack backtrace if pt_regs is from kernel mode */
 192        if (!user_mode(regs))
 193                show_trace(NULL, regs->gprs[15]);
 194        show_last_breaking_event(regs);
 195}
 196
 197static DEFINE_SPINLOCK(die_lock);
 198
 199void die(struct pt_regs *regs, const char *str)
 200{
 201        static int die_counter;
 202
 203        oops_enter();
 204        lgr_info_log();
 205        debug_stop_all();
 206        console_verbose();
 207        spin_lock_irq(&die_lock);
 208        bust_spinlocks(1);
 209        printk("%s: %04x ilc:%d [#%d] ", str, regs->int_code & 0xffff,
 210               regs->int_code >> 17, ++die_counter);
 211#ifdef CONFIG_PREEMPT
 212        printk("PREEMPT ");
 213#endif
 214#ifdef CONFIG_SMP
 215        printk("SMP ");
 216#endif
 217        if (debug_pagealloc_enabled())
 218                printk("DEBUG_PAGEALLOC");
 219        printk("\n");
 220        notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
 221        print_modules();
 222        show_regs(regs);
 223        bust_spinlocks(0);
 224        add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
 225        spin_unlock_irq(&die_lock);
 226        if (in_interrupt())
 227                panic("Fatal exception in interrupt");
 228        if (panic_on_oops)
 229                panic("Fatal exception: panic_on_oops");
 230        oops_exit();
 231        do_exit(SIGSEGV);
 232}
 233