~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/kernel/dumpstack_32.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 21 const 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 
 38 static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
 39 {
 40         unsigned long *begin = (unsigned long *)this_cpu_read(pcpu_hot.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 
 63 static bool in_softirq_stack(unsigned long *stack, struct stack_info *info)
 64 {
 65         unsigned long *begin = (unsigned long *)this_cpu_read(pcpu_hot.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 
 88 static 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 
108 int 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 
136 recursion_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 
152 unknown:
153         info->type = STACK_TYPE_UNKNOWN;
154         return -EINVAL;
155 }
156 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php