root/arch/x86/kernel/dumpstack_64.c

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

DEFINITIONS

This source file includes following definitions.
  1. stack_type_name
  2. in_exception_stack
  3. in_irq_stack
  4. get_stack_info

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  Copyright (C) 1991, 1992  Linus Torvalds
   4  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
   5  */
   6 #include <linux/sched/debug.h>
   7 #include <linux/kallsyms.h>
   8 #include <linux/kprobes.h>
   9 #include <linux/uaccess.h>
  10 #include <linux/hardirq.h>
  11 #include <linux/kdebug.h>
  12 #include <linux/export.h>
  13 #include <linux/ptrace.h>
  14 #include <linux/kexec.h>
  15 #include <linux/sysfs.h>
  16 #include <linux/bug.h>
  17 #include <linux/nmi.h>
  18 
  19 #include <asm/cpu_entry_area.h>
  20 #include <asm/stacktrace.h>
  21 
  22 static const char * const exception_stack_names[] = {
  23                 [ ESTACK_DF     ]       = "#DF",
  24                 [ ESTACK_NMI    ]       = "NMI",
  25                 [ ESTACK_DB2    ]       = "#DB2",
  26                 [ ESTACK_DB1    ]       = "#DB1",
  27                 [ ESTACK_DB     ]       = "#DB",
  28                 [ ESTACK_MCE    ]       = "#MC",
  29 };
  30 
  31 const char *stack_type_name(enum stack_type type)
  32 {
  33         BUILD_BUG_ON(N_EXCEPTION_STACKS != 6);
  34 
  35         if (type == STACK_TYPE_IRQ)
  36                 return "IRQ";
  37 
  38         if (type == STACK_TYPE_ENTRY) {
  39                 /*
  40                  * On 64-bit, we have a generic entry stack that we
  41                  * use for all the kernel entry points, including
  42                  * SYSENTER.
  43                  */
  44                 return "ENTRY_TRAMPOLINE";
  45         }
  46 
  47         if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST)
  48                 return exception_stack_names[type - STACK_TYPE_EXCEPTION];
  49 
  50         return NULL;
  51 }
  52 
  53 /**
  54  * struct estack_pages - Page descriptor for exception stacks
  55  * @offs:       Offset from the start of the exception stack area
  56  * @size:       Size of the exception stack
  57  * @type:       Type to store in the stack_info struct
  58  */
  59 struct estack_pages {
  60         u32     offs;
  61         u16     size;
  62         u16     type;
  63 };
  64 
  65 #define EPAGERANGE(st)                                                  \
  66         [PFN_DOWN(CEA_ESTACK_OFFS(st)) ...                              \
  67          PFN_DOWN(CEA_ESTACK_OFFS(st) + CEA_ESTACK_SIZE(st) - 1)] = {   \
  68                 .offs   = CEA_ESTACK_OFFS(st),                          \
  69                 .size   = CEA_ESTACK_SIZE(st),                          \
  70                 .type   = STACK_TYPE_EXCEPTION + ESTACK_ ##st, }
  71 
  72 /*
  73  * Array of exception stack page descriptors. If the stack is larger than
  74  * PAGE_SIZE, all pages covering a particular stack will have the same
  75  * info. The guard pages including the not mapped DB2 stack are zeroed
  76  * out.
  77  */
  78 static const
  79 struct estack_pages estack_pages[CEA_ESTACK_PAGES] ____cacheline_aligned = {
  80         EPAGERANGE(DF),
  81         EPAGERANGE(NMI),
  82         EPAGERANGE(DB1),
  83         EPAGERANGE(DB),
  84         EPAGERANGE(MCE),
  85 };
  86 
  87 static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
  88 {
  89         unsigned long begin, end, stk = (unsigned long)stack;
  90         const struct estack_pages *ep;
  91         struct pt_regs *regs;
  92         unsigned int k;
  93 
  94         BUILD_BUG_ON(N_EXCEPTION_STACKS != 6);
  95 
  96         begin = (unsigned long)__this_cpu_read(cea_exception_stacks);
  97         /*
  98          * Handle the case where stack trace is collected _before_
  99          * cea_exception_stacks had been initialized.
 100          */
 101         if (!begin)
 102                 return false;
 103 
 104         end = begin + sizeof(struct cea_exception_stacks);
 105         /* Bail if @stack is outside the exception stack area. */
 106         if (stk < begin || stk >= end)
 107                 return false;
 108 
 109         /* Calc page offset from start of exception stacks */
 110         k = (stk - begin) >> PAGE_SHIFT;
 111         /* Lookup the page descriptor */
 112         ep = &estack_pages[k];
 113         /* Guard page? */
 114         if (!ep->size)
 115                 return false;
 116 
 117         begin += (unsigned long)ep->offs;
 118         end = begin + (unsigned long)ep->size;
 119         regs = (struct pt_regs *)end - 1;
 120 
 121         info->type      = ep->type;
 122         info->begin     = (unsigned long *)begin;
 123         info->end       = (unsigned long *)end;
 124         info->next_sp   = (unsigned long *)regs->sp;
 125         return true;
 126 }
 127 
 128 static bool in_irq_stack(unsigned long *stack, struct stack_info *info)
 129 {
 130         unsigned long *end   = (unsigned long *)this_cpu_read(hardirq_stack_ptr);
 131         unsigned long *begin = end - (IRQ_STACK_SIZE / sizeof(long));
 132 
 133         /*
 134          * This is a software stack, so 'end' can be a valid stack pointer.
 135          * It just means the stack is empty.
 136          */
 137         if (stack < begin || stack >= end)
 138                 return false;
 139 
 140         info->type      = STACK_TYPE_IRQ;
 141         info->begin     = begin;
 142         info->end       = end;
 143 
 144         /*
 145          * The next stack pointer is the first thing pushed by the entry code
 146          * after switching to the irq stack.
 147          */
 148         info->next_sp = (unsigned long *)*(end - 1);
 149 
 150         return true;
 151 }
 152 
 153 int get_stack_info(unsigned long *stack, struct task_struct *task,
 154                    struct stack_info *info, unsigned long *visit_mask)
 155 {
 156         if (!stack)
 157                 goto unknown;
 158 
 159         task = task ? : current;
 160 
 161         if (in_task_stack(stack, task, info))
 162                 goto recursion_check;
 163 
 164         if (task != current)
 165                 goto unknown;
 166 
 167         if (in_exception_stack(stack, info))
 168                 goto recursion_check;
 169 
 170         if (in_irq_stack(stack, info))
 171                 goto recursion_check;
 172 
 173         if (in_entry_stack(stack, info))
 174                 goto recursion_check;
 175 
 176         goto unknown;
 177 
 178 recursion_check:
 179         /*
 180          * Make sure we don't iterate through any given stack more than once.
 181          * If it comes up a second time then there's something wrong going on:
 182          * just break out and report an unknown stack type.
 183          */
 184         if (visit_mask) {
 185                 if (*visit_mask & (1UL << info->type)) {
 186                         printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
 187                         goto unknown;
 188                 }
 189                 *visit_mask |= 1UL << info->type;
 190         }
 191 
 192         return 0;
 193 
 194 unknown:
 195         info->type = STACK_TYPE_UNKNOWN;
 196         return -EINVAL;
 197 }

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