Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/kernel/dumpstack_32.c
26439 views
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(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(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
157