xref: /openbmc/linux/arch/x86/kernel/dumpstack_32.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
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  
stack_type_name(enum stack_type type)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  
in_hardirq_stack(unsigned long * stack,struct stack_info * info)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  
in_softirq_stack(unsigned long * stack,struct stack_info * info)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  
in_doublefault_stack(unsigned long * stack,struct stack_info * info)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  
get_stack_info(unsigned long * stack,struct task_struct * task,struct stack_info * info,unsigned long * visit_mask)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