hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/arm64/include/asm/stacktrace.h
....@@ -1,17 +1,6 @@
1
+/* SPDX-License-Identifier: GPL-2.0-only */
12 /*
23 * Copyright (C) 2012 ARM Ltd.
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License version 2 as
6
- * published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope that it will be useful,
9
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- * GNU General Public License for more details.
12
- *
13
- * You should have received a copy of the GNU General Public License
14
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
154 */
165 #ifndef __ASM_STACKTRACE_H
176 #define __ASM_STACKTRACE_H
....@@ -19,18 +8,11 @@
198 #include <linux/percpu.h>
209 #include <linux/sched.h>
2110 #include <linux/sched/task_stack.h>
11
+#include <linux/types.h>
2212
2313 #include <asm/memory.h>
2414 #include <asm/ptrace.h>
2515 #include <asm/sdei.h>
26
-
27
-struct stackframe {
28
- unsigned long fp;
29
- unsigned long pc;
30
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
31
- int graph;
32
-#endif
33
-};
3416
3517 enum stack_type {
3618 STACK_TYPE_UNKNOWN,
....@@ -39,6 +21,7 @@
3921 STACK_TYPE_OVERFLOW,
4022 STACK_TYPE_SDEI_NORMAL,
4123 STACK_TYPE_SDEI_CRITICAL,
24
+ __NR_STACK_TYPES
4225 };
4326
4427 struct stack_info {
....@@ -47,23 +30,49 @@
4730 enum stack_type type;
4831 };
4932
33
+/*
34
+ * A snapshot of a frame record or fp/lr register values, along with some
35
+ * accounting information necessary for robust unwinding.
36
+ *
37
+ * @fp: The fp value in the frame record (or the real fp)
38
+ * @pc: The fp value in the frame record (or the real lr)
39
+ *
40
+ * @stacks_done: Stacks which have been entirely unwound, for which it is no
41
+ * longer valid to unwind to.
42
+ *
43
+ * @prev_fp: The fp that pointed to this frame record, or a synthetic value
44
+ * of 0. This is used to ensure that within a stack, each
45
+ * subsequent frame record is at an increasing address.
46
+ * @prev_type: The type of stack this frame record was on, or a synthetic
47
+ * value of STACK_TYPE_UNKNOWN. This is used to detect a
48
+ * transition from one stack to another.
49
+ *
50
+ * @graph: When FUNCTION_GRAPH_TRACER is selected, holds the index of a
51
+ * replacement lr value in the ftrace graph stack.
52
+ */
53
+struct stackframe {
54
+ unsigned long fp;
55
+ unsigned long pc;
56
+ DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
57
+ unsigned long prev_fp;
58
+ enum stack_type prev_type;
59
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
60
+ int graph;
61
+#endif
62
+};
63
+
5064 extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
5165 extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
52
- int (*fn)(struct stackframe *, void *), void *data);
53
-extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk);
66
+ bool (*fn)(void *, unsigned long), void *data);
67
+extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
68
+ const char *loglvl);
5469
5570 DECLARE_PER_CPU(unsigned long *, irq_stack_ptr);
5671
57
-#ifdef CONFIG_SHADOW_CALL_STACK
58
-DECLARE_PER_CPU(unsigned long *, irq_shadow_call_stack_ptr);
59
-#endif
60
-
61
-static inline bool on_irq_stack(unsigned long sp,
72
+static inline bool on_stack(unsigned long sp, unsigned long low,
73
+ unsigned long high, enum stack_type type,
6274 struct stack_info *info)
6375 {
64
- unsigned long low = (unsigned long)raw_cpu_read(irq_stack_ptr);
65
- unsigned long high = low + IRQ_STACK_SIZE;
66
-
6776 if (!low)
6877 return false;
6978
....@@ -73,28 +82,28 @@
7382 if (info) {
7483 info->low = low;
7584 info->high = high;
76
- info->type = STACK_TYPE_IRQ;
85
+ info->type = type;
7786 }
78
-
7987 return true;
8088 }
8189
82
-static inline bool on_task_stack(struct task_struct *tsk, unsigned long sp,
90
+static inline bool on_irq_stack(unsigned long sp,
8391 struct stack_info *info)
92
+{
93
+ unsigned long low = (unsigned long)raw_cpu_read(irq_stack_ptr);
94
+ unsigned long high = low + IRQ_STACK_SIZE;
95
+
96
+ return on_stack(sp, low, high, STACK_TYPE_IRQ, info);
97
+}
98
+
99
+static inline bool on_task_stack(const struct task_struct *tsk,
100
+ unsigned long sp,
101
+ struct stack_info *info)
84102 {
85103 unsigned long low = (unsigned long)task_stack_page(tsk);
86104 unsigned long high = low + THREAD_SIZE;
87105
88
- if (sp < low || sp >= high)
89
- return false;
90
-
91
- if (info) {
92
- info->low = low;
93
- info->high = high;
94
- info->type = STACK_TYPE_TASK;
95
- }
96
-
97
- return true;
106
+ return on_stack(sp, low, high, STACK_TYPE_TASK, info);
98107 }
99108
100109 #ifdef CONFIG_VMAP_STACK
....@@ -106,16 +115,7 @@
106115 unsigned long low = (unsigned long)raw_cpu_ptr(overflow_stack);
107116 unsigned long high = low + OVERFLOW_STACK_SIZE;
108117
109
- if (sp < low || sp >= high)
110
- return false;
111
-
112
- if (info) {
113
- info->low = low;
114
- info->high = high;
115
- info->type = STACK_TYPE_OVERFLOW;
116
- }
117
-
118
- return true;
118
+ return on_stack(sp, low, high, STACK_TYPE_OVERFLOW, info);
119119 }
120120 #else
121121 static inline bool on_overflow_stack(unsigned long sp,
....@@ -127,10 +127,13 @@
127127 * We can only safely access per-cpu stacks from current in a non-preemptible
128128 * context.
129129 */
130
-static inline bool on_accessible_stack(struct task_struct *tsk,
131
- unsigned long sp,
132
- struct stack_info *info)
130
+static inline bool on_accessible_stack(const struct task_struct *tsk,
131
+ unsigned long sp,
132
+ struct stack_info *info)
133133 {
134
+ if (info)
135
+ info->type = STACK_TYPE_UNKNOWN;
136
+
134137 if (on_task_stack(tsk, sp, info))
135138 return true;
136139 if (tsk != current || preemptible())
....@@ -145,4 +148,27 @@
145148 return false;
146149 }
147150
151
+static inline void start_backtrace(struct stackframe *frame,
152
+ unsigned long fp, unsigned long pc)
153
+{
154
+ frame->fp = fp;
155
+ frame->pc = pc;
156
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
157
+ frame->graph = 0;
158
+#endif
159
+
160
+ /*
161
+ * Prime the first unwind.
162
+ *
163
+ * In unwind_frame() we'll check that the FP points to a valid stack,
164
+ * which can't be STACK_TYPE_UNKNOWN, and the first unwind will be
165
+ * treated as a transition to whichever stack that happens to be. The
166
+ * prev_fp value won't be used, but we set it to 0 such that it is
167
+ * definitely not an accessible stack address.
168
+ */
169
+ bitmap_zero(frame->stacks_done, __NR_STACK_TYPES);
170
+ frame->prev_fp = 0;
171
+ frame->prev_type = STACK_TYPE_UNKNOWN;
172
+}
173
+
148174 #endif /* __ASM_STACKTRACE_H */