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