xref: /openbmc/linux/arch/x86/kernel/dumpstack_32.c (revision bf070bb0)
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 	return NULL;
30 }
31 
32 static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
33 {
34 	unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack);
35 	unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
36 
37 	/*
38 	 * This is a software stack, so 'end' can be a valid stack pointer.
39 	 * It just means the stack is empty.
40 	 */
41 	if (stack <= begin || stack > end)
42 		return false;
43 
44 	info->type	= STACK_TYPE_IRQ;
45 	info->begin	= begin;
46 	info->end	= end;
47 
48 	/*
49 	 * See irq_32.c -- the next stack pointer is stored at the beginning of
50 	 * the stack.
51 	 */
52 	info->next_sp	= (unsigned long *)*begin;
53 
54 	return true;
55 }
56 
57 static bool in_softirq_stack(unsigned long *stack, struct stack_info *info)
58 {
59 	unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack);
60 	unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
61 
62 	/*
63 	 * This is a software stack, so 'end' can be a valid stack pointer.
64 	 * It just means the stack is empty.
65 	 */
66 	if (stack <= begin || stack > end)
67 		return false;
68 
69 	info->type	= STACK_TYPE_SOFTIRQ;
70 	info->begin	= begin;
71 	info->end	= end;
72 
73 	/*
74 	 * The next stack pointer is stored at the beginning of the stack.
75 	 * See irq_32.c.
76 	 */
77 	info->next_sp	= (unsigned long *)*begin;
78 
79 	return true;
80 }
81 
82 int get_stack_info(unsigned long *stack, struct task_struct *task,
83 		   struct stack_info *info, unsigned long *visit_mask)
84 {
85 	if (!stack)
86 		goto unknown;
87 
88 	task = task ? : current;
89 
90 	if (in_task_stack(stack, task, info))
91 		goto recursion_check;
92 
93 	if (task != current)
94 		goto unknown;
95 
96 	if (in_hardirq_stack(stack, info))
97 		goto recursion_check;
98 
99 	if (in_softirq_stack(stack, info))
100 		goto recursion_check;
101 
102 	goto unknown;
103 
104 recursion_check:
105 	/*
106 	 * Make sure we don't iterate through any given stack more than once.
107 	 * If it comes up a second time then there's something wrong going on:
108 	 * just break out and report an unknown stack type.
109 	 */
110 	if (visit_mask) {
111 		if (*visit_mask & (1UL << info->type)) {
112 			printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
113 			goto unknown;
114 		}
115 		*visit_mask |= 1UL << info->type;
116 	}
117 
118 	return 0;
119 
120 unknown:
121 	info->type = STACK_TYPE_UNKNOWN;
122 	return -EINVAL;
123 }
124 
125 void show_regs(struct pt_regs *regs)
126 {
127 	int i;
128 
129 	show_regs_print_info(KERN_EMERG);
130 	__show_regs(regs, !user_mode(regs));
131 
132 	/*
133 	 * When in-kernel, we also print out the stack and code at the
134 	 * time of the fault..
135 	 */
136 	if (!user_mode(regs)) {
137 		unsigned int code_prologue = code_bytes * 43 / 64;
138 		unsigned int code_len = code_bytes;
139 		unsigned char c;
140 		u8 *ip;
141 
142 		show_trace_log_lvl(current, regs, NULL, KERN_EMERG);
143 
144 		pr_emerg("Code:");
145 
146 		ip = (u8 *)regs->ip - code_prologue;
147 		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
148 			/* try starting at IP */
149 			ip = (u8 *)regs->ip;
150 			code_len = code_len - code_prologue + 1;
151 		}
152 		for (i = 0; i < code_len; i++, ip++) {
153 			if (ip < (u8 *)PAGE_OFFSET ||
154 					probe_kernel_address(ip, c)) {
155 				pr_cont("  Bad EIP value.");
156 				break;
157 			}
158 			if (ip == (u8 *)regs->ip)
159 				pr_cont(" <%02x>", c);
160 			else
161 				pr_cont(" %02x", c);
162 		}
163 	}
164 	pr_cont("\n");
165 }
166