linux/arch/x86/kernel/dumpstack_32.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
  21const char *stack_type_name(enum stack_type type)
  22{
  23        if (type == STACK_TYPE_IRQ)
  24                return "IRQ";
  25
  26        if (type == STACK_TYPE_SOFTIRQ)
  27                return "SOFTIRQ";
  28
  29        if (type == STACK_TYPE_ENTRY)
  30                return "ENTRY_TRAMPOLINE";
  31
  32        if (type == STACK_TYPE_EXCEPTION)
  33                return "#DF";
  34
  35        return NULL;
  36}
  37
  38static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
  39{
  40        unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack_ptr);
  41        unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
  42
  43        /*
  44         * This is a software stack, so 'end' can be a valid stack pointer.
  45         * It just means the stack is empty.
  46         */
  47        if (stack < begin || stack > end)
  48                return false;
  49
  50        info->type      = STACK_TYPE_IRQ;
  51        info->begin     = begin;
  52        info->end       = end;
  53
  54        /*
  55         * See irq_32.c -- the next stack pointer is stored at the beginning of
  56         * the stack.
  57         */
  58        info->next_sp   = (unsigned long *)*begin;
  59
  60        return true;
  61}
  62
  63static bool in_softirq_stack(unsigned long *stack, struct stack_info *info)
  64{
  65        unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack_ptr);
  66        unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
  67
  68        /*
  69         * This is a software stack, so 'end' can be a valid stack pointer.
  70         * It just means the stack is empty.
  71         */
  72        if (stack < begin || stack > end)
  73                return false;
  74
  75        info->type      = STACK_TYPE_SOFTIRQ;
  76        info->begin     = begin;
  77        info->end       = end;
  78
  79        /*
  80         * The next stack pointer is stored at the beginning of the stack.
  81         * See irq_32.c.
  82         */
  83        info->next_sp   = (unsigned long *)*begin;
  84
  85        return true;
  86}
  87
  88static bool in_doublefault_stack(unsigned long *stack, struct stack_info *info)
  89{
  90        struct cpu_entry_area *cea = get_cpu_entry_area(raw_smp_processor_id());
  91        struct doublefault_stack *ss = &cea->doublefault_stack;
  92
  93        void *begin = ss->stack;
  94        void *end = begin + sizeof(ss->stack);
  95
  96        if ((void *)stack < begin || (void *)stack >= end)
  97                return false;
  98
  99        info->type      = STACK_TYPE_EXCEPTION;
 100        info->begin     = begin;
 101        info->end       = end;
 102        info->next_sp   = (unsigned long *)this_cpu_read(cpu_tss_rw.x86_tss.sp);
 103
 104        return true;
 105}
 106
 107
 108int get_stack_info(unsigned long *stack, struct task_struct *task,
 109                   struct stack_info *info, unsigned long *visit_mask)
 110{
 111        if (!stack)
 112                goto unknown;
 113
 114        task = task ? : current;
 115
 116        if (in_task_stack(stack, task, info))
 117                goto recursion_check;
 118
 119        if (task != current)
 120                goto unknown;
 121
 122        if (in_entry_stack(stack, info))
 123                goto recursion_check;
 124
 125        if (in_hardirq_stack(stack, info))
 126                goto recursion_check;
 127
 128        if (in_softirq_stack(stack, info))
 129                goto recursion_check;
 130
 131        if (in_doublefault_stack(stack, info))
 132                goto recursion_check;
 133
 134        goto unknown;
 135
 136recursion_check:
 137        /*
 138         * Make sure we don't iterate through any given stack more than once.
 139         * If it comes up a second time then there's something wrong going on:
 140         * just break out and report an unknown stack type.
 141         */
 142        if (visit_mask) {
 143                if (*visit_mask & (1UL << info->type)) {
 144                        printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
 145                        goto unknown;
 146                }
 147                *visit_mask |= 1UL << info->type;
 148        }
 149
 150        return 0;
 151
 152unknown:
 153        info->type = STACK_TYPE_UNKNOWN;
 154        return -EINVAL;
 155}
 156