linux/arch/x86/kernel/dumpstack_64.c
<<
>>
Prefs
   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/stacktrace.h>
  20
  21static char *exception_stack_names[N_EXCEPTION_STACKS] = {
  22                [ DOUBLEFAULT_STACK-1   ]       = "#DF",
  23                [ NMI_STACK-1           ]       = "NMI",
  24                [ DEBUG_STACK-1         ]       = "#DB",
  25                [ MCE_STACK-1           ]       = "#MC",
  26};
  27
  28static unsigned long exception_stack_sizes[N_EXCEPTION_STACKS] = {
  29        [0 ... N_EXCEPTION_STACKS - 1]          = EXCEPTION_STKSZ,
  30        [DEBUG_STACK - 1]                       = DEBUG_STKSZ
  31};
  32
  33const char *stack_type_name(enum stack_type type)
  34{
  35        BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
  36
  37        if (type == STACK_TYPE_IRQ)
  38                return "IRQ";
  39
  40        if (type == STACK_TYPE_ENTRY) {
  41                /*
  42                 * On 64-bit, we have a generic entry stack that we
  43                 * use for all the kernel entry points, including
  44                 * SYSENTER.
  45                 */
  46                return "ENTRY_TRAMPOLINE";
  47        }
  48
  49        if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST)
  50                return exception_stack_names[type - STACK_TYPE_EXCEPTION];
  51
  52        return NULL;
  53}
  54
  55static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
  56{
  57        unsigned long *begin, *end;
  58        struct pt_regs *regs;
  59        unsigned k;
  60
  61        BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
  62
  63        for (k = 0; k < N_EXCEPTION_STACKS; k++) {
  64                end   = (unsigned long *)raw_cpu_ptr(&orig_ist)->ist[k];
  65                begin = end - (exception_stack_sizes[k] / sizeof(long));
  66                regs  = (struct pt_regs *)end - 1;
  67
  68                if (stack <= begin || stack >= end)
  69                        continue;
  70
  71                info->type      = STACK_TYPE_EXCEPTION + k;
  72                info->begin     = begin;
  73                info->end       = end;
  74                info->next_sp   = (unsigned long *)regs->sp;
  75
  76                return true;
  77        }
  78
  79        return false;
  80}
  81
  82static bool in_irq_stack(unsigned long *stack, struct stack_info *info)
  83{
  84        unsigned long *end   = (unsigned long *)this_cpu_read(irq_stack_ptr);
  85        unsigned long *begin = end - (IRQ_STACK_SIZE / sizeof(long));
  86
  87        /*
  88         * This is a software stack, so 'end' can be a valid stack pointer.
  89         * It just means the stack is empty.
  90         */
  91        if (stack <= begin || stack > end)
  92                return false;
  93
  94        info->type      = STACK_TYPE_IRQ;
  95        info->begin     = begin;
  96        info->end       = end;
  97
  98        /*
  99         * The next stack pointer is the first thing pushed by the entry code
 100         * after switching to the irq stack.
 101         */
 102        info->next_sp = (unsigned long *)*(end - 1);
 103
 104        return true;
 105}
 106
 107int get_stack_info(unsigned long *stack, struct task_struct *task,
 108                   struct stack_info *info, unsigned long *visit_mask)
 109{
 110        if (!stack)
 111                goto unknown;
 112
 113        task = task ? : current;
 114
 115        if (in_task_stack(stack, task, info))
 116                goto recursion_check;
 117
 118        if (task != current)
 119                goto unknown;
 120
 121        if (in_exception_stack(stack, info))
 122                goto recursion_check;
 123
 124        if (in_irq_stack(stack, info))
 125                goto recursion_check;
 126
 127        if (in_entry_stack(stack, info))
 128                goto recursion_check;
 129
 130        goto unknown;
 131
 132recursion_check:
 133        /*
 134         * Make sure we don't iterate through any given stack more than once.
 135         * If it comes up a second time then there's something wrong going on:
 136         * just break out and report an unknown stack type.
 137         */
 138        if (visit_mask) {
 139                if (*visit_mask & (1UL << info->type)) {
 140                        printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
 141                        goto unknown;
 142                }
 143                *visit_mask |= 1UL << info->type;
 144        }
 145
 146        return 0;
 147
 148unknown:
 149        info->type = STACK_TYPE_UNKNOWN;
 150        return -EINVAL;
 151}
 152