root/arch/s390/kernel/dumpstack.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. stack_type_name
  2. in_stack
  3. in_task_stack
  4. in_irq_stack
  5. in_nodat_stack
  6. in_restart_stack
  7. get_stack_info
  8. show_stack
  9. show_last_breaking_event
  10. show_registers
  11. show_regs
  12. die

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Stack dumping functions
   4  *
   5  *  Copyright IBM Corp. 1999, 2013
   6  */
   7 
   8 #include <linux/kallsyms.h>
   9 #include <linux/hardirq.h>
  10 #include <linux/kprobes.h>
  11 #include <linux/utsname.h>
  12 #include <linux/export.h>
  13 #include <linux/kdebug.h>
  14 #include <linux/ptrace.h>
  15 #include <linux/mm.h>
  16 #include <linux/module.h>
  17 #include <linux/sched.h>
  18 #include <linux/sched/debug.h>
  19 #include <linux/sched/task_stack.h>
  20 #include <asm/processor.h>
  21 #include <asm/debug.h>
  22 #include <asm/dis.h>
  23 #include <asm/ipl.h>
  24 #include <asm/unwind.h>
  25 
  26 const char *stack_type_name(enum stack_type type)
  27 {
  28         switch (type) {
  29         case STACK_TYPE_TASK:
  30                 return "task";
  31         case STACK_TYPE_IRQ:
  32                 return "irq";
  33         case STACK_TYPE_NODAT:
  34                 return "nodat";
  35         case STACK_TYPE_RESTART:
  36                 return "restart";
  37         default:
  38                 return "unknown";
  39         }
  40 }
  41 
  42 static inline bool in_stack(unsigned long sp, struct stack_info *info,
  43                             enum stack_type type, unsigned long low,
  44                             unsigned long high)
  45 {
  46         if (sp < low || sp >= high)
  47                 return false;
  48         info->type = type;
  49         info->begin = low;
  50         info->end = high;
  51         return true;
  52 }
  53 
  54 static bool in_task_stack(unsigned long sp, struct task_struct *task,
  55                           struct stack_info *info)
  56 {
  57         unsigned long stack;
  58 
  59         stack = (unsigned long) task_stack_page(task);
  60         return in_stack(sp, info, STACK_TYPE_TASK, stack, stack + THREAD_SIZE);
  61 }
  62 
  63 static bool in_irq_stack(unsigned long sp, struct stack_info *info)
  64 {
  65         unsigned long frame_size, top;
  66 
  67         frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
  68         top = S390_lowcore.async_stack + frame_size;
  69         return in_stack(sp, info, STACK_TYPE_IRQ, top - THREAD_SIZE, top);
  70 }
  71 
  72 static bool in_nodat_stack(unsigned long sp, struct stack_info *info)
  73 {
  74         unsigned long frame_size, top;
  75 
  76         frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
  77         top = S390_lowcore.nodat_stack + frame_size;
  78         return in_stack(sp, info, STACK_TYPE_NODAT, top - THREAD_SIZE, top);
  79 }
  80 
  81 static bool in_restart_stack(unsigned long sp, struct stack_info *info)
  82 {
  83         unsigned long frame_size, top;
  84 
  85         frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
  86         top = S390_lowcore.restart_stack + frame_size;
  87         return in_stack(sp, info, STACK_TYPE_RESTART, top - THREAD_SIZE, top);
  88 }
  89 
  90 int get_stack_info(unsigned long sp, struct task_struct *task,
  91                    struct stack_info *info, unsigned long *visit_mask)
  92 {
  93         if (!sp)
  94                 goto unknown;
  95 
  96         task = task ? : current;
  97 
  98         /* Check per-task stack */
  99         if (in_task_stack(sp, task, info))
 100                 goto recursion_check;
 101 
 102         if (task != current)
 103                 goto unknown;
 104 
 105         /* Check per-cpu stacks */
 106         if (!in_irq_stack(sp, info) &&
 107             !in_nodat_stack(sp, info) &&
 108             !in_restart_stack(sp, info))
 109                 goto unknown;
 110 
 111 recursion_check:
 112         /*
 113          * Make sure we don't iterate through any given stack more than once.
 114          * If it comes up a second time then there's something wrong going on:
 115          * just break out and report an unknown stack type.
 116          */
 117         if (*visit_mask & (1UL << info->type))
 118                 goto unknown;
 119         *visit_mask |= 1UL << info->type;
 120         return 0;
 121 unknown:
 122         info->type = STACK_TYPE_UNKNOWN;
 123         return -EINVAL;
 124 }
 125 
 126 void show_stack(struct task_struct *task, unsigned long *stack)
 127 {
 128         struct unwind_state state;
 129 
 130         printk("Call Trace:\n");
 131         if (!task)
 132                 task = current;
 133         unwind_for_each_frame(&state, task, NULL, (unsigned long) stack)
 134                 printk(state.reliable ? " [<%016lx>] %pSR \n" :
 135                                         "([<%016lx>] %pSR)\n",
 136                        state.ip, (void *) state.ip);
 137         debug_show_held_locks(task ? : current);
 138 }
 139 
 140 static void show_last_breaking_event(struct pt_regs *regs)
 141 {
 142         printk("Last Breaking-Event-Address:\n");
 143         printk(" [<%016lx>] %pSR\n", regs->args[0], (void *)regs->args[0]);
 144 }
 145 
 146 void show_registers(struct pt_regs *regs)
 147 {
 148         struct psw_bits *psw = &psw_bits(regs->psw);
 149         char *mode;
 150 
 151         mode = user_mode(regs) ? "User" : "Krnl";
 152         printk("%s PSW : %px %px", mode, (void *)regs->psw.mask, (void *)regs->psw.addr);
 153         if (!user_mode(regs))
 154                 pr_cont(" (%pSR)", (void *)regs->psw.addr);
 155         pr_cont("\n");
 156         printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
 157                "P:%x AS:%x CC:%x PM:%x", psw->per, psw->dat, psw->io, psw->ext,
 158                psw->key, psw->mcheck, psw->wait, psw->pstate, psw->as, psw->cc, psw->pm);
 159         pr_cont(" RI:%x EA:%x\n", psw->ri, psw->eaba);
 160         printk("%s GPRS: %016lx %016lx %016lx %016lx\n", mode,
 161                regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
 162         printk("           %016lx %016lx %016lx %016lx\n",
 163                regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
 164         printk("           %016lx %016lx %016lx %016lx\n",
 165                regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
 166         printk("           %016lx %016lx %016lx %016lx\n",
 167                regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
 168         show_code(regs);
 169 }
 170 
 171 void 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_stack(NULL, (unsigned long *) regs->gprs[15]);
 178         show_last_breaking_event(regs);
 179 }
 180 
 181 static DEFINE_SPINLOCK(die_lock);
 182 
 183 void 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 ilc:%d [#%d] ", str, regs->int_code & 0xffff,
 194                regs->int_code >> 17, ++die_counter);
 195 #ifdef CONFIG_PREEMPT
 196         pr_cont("PREEMPT ");
 197 #endif
 198         pr_cont("SMP ");
 199         if (debug_pagealloc_enabled())
 200                 pr_cont("DEBUG_PAGEALLOC");
 201         pr_cont("\n");
 202         notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
 203         print_modules();
 204         show_regs(regs);
 205         bust_spinlocks(0);
 206         add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
 207         spin_unlock_irq(&die_lock);
 208         if (in_interrupt())
 209                 panic("Fatal exception in interrupt");
 210         if (panic_on_oops)
 211                 panic("Fatal exception: panic_on_oops");
 212         oops_exit();
 213         do_exit(SIGSEGV);
 214 }

/* [<][>][^][v][top][bottom][index][help] */