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