hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/riscv/kernel/stacktrace.c
....@@ -1,15 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2008 ARM Limited
34 * Copyright (C) 2014 Regents of the University of California
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License version 2 as
7
- * published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
135 */
146
157 #include <linux/export.h>
....@@ -20,6 +12,8 @@
2012 #include <linux/stacktrace.h>
2113 #include <linux/ftrace.h>
2214
15
+register unsigned long sp_in_global __asm__("sp");
16
+
2317 #ifdef CONFIG_FRAME_POINTER
2418
2519 struct stackframe {
....@@ -27,17 +21,17 @@
2721 unsigned long ra;
2822 };
2923
30
-static void notrace walk_stackframe(struct task_struct *task,
31
- struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg)
24
+void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
25
+ bool (*fn)(unsigned long, void *), void *arg)
3226 {
3327 unsigned long fp, sp, pc;
3428
3529 if (regs) {
36
- fp = GET_FP(regs);
37
- sp = GET_USP(regs);
38
- pc = GET_IP(regs);
30
+ fp = frame_pointer(regs);
31
+ sp = user_stack_pointer(regs);
32
+ pc = instruction_pointer(regs);
3933 } else if (task == NULL || task == current) {
40
- const register unsigned long current_sp __asm__ ("sp");
34
+ const register unsigned long current_sp = sp_in_global;
4135 fp = (unsigned long)__builtin_frame_address(0);
4236 sp = current_sp;
4337 pc = (unsigned long)walk_stackframe;
....@@ -63,13 +57,15 @@
6357 /* Unwind stack frame */
6458 frame = (struct stackframe *)fp - 1;
6559 sp = fp;
66
- fp = frame->fp;
67
-#ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
68
- pc = ftrace_graph_ret_addr(current, NULL, frame->ra,
69
- (unsigned long *)(fp - 8));
70
-#else
71
- pc = frame->ra - 0x4;
72
-#endif
60
+ if (regs && (regs->epc == pc) && (frame->fp & 0x7)) {
61
+ fp = frame->ra;
62
+ pc = regs->ra;
63
+ } else {
64
+ fp = frame->fp;
65
+ pc = ftrace_graph_ret_addr(current, NULL, frame->ra,
66
+ &frame->ra);
67
+ }
68
+
7369 }
7470 }
7571
....@@ -82,11 +78,10 @@
8278 unsigned long *ksp;
8379
8480 if (regs) {
85
- sp = GET_USP(regs);
86
- pc = GET_IP(regs);
81
+ sp = user_stack_pointer(regs);
82
+ pc = instruction_pointer(regs);
8783 } else if (task == NULL || task == current) {
88
- const register unsigned long current_sp __asm__ ("sp");
89
- sp = current_sp;
84
+ sp = sp_in_global;
9085 pc = (unsigned long)walk_stackframe;
9186 } else {
9287 /* task blocked in __switch_to */
....@@ -101,7 +96,7 @@
10196 while (!kstack_end(ksp)) {
10297 if (__kernel_text_address(pc) && unlikely(fn(pc, arg)))
10398 break;
104
- pc = (*ksp++) - 0x4;
99
+ pc = READ_ONCE_NOCHECK(*ksp++) - 0x4;
105100 }
106101 }
107102
....@@ -110,16 +105,17 @@
110105
111106 static bool print_trace_address(unsigned long pc, void *arg)
112107 {
113
- print_ip_sym(pc);
108
+ const char *loglvl = arg;
109
+
110
+ print_ip_sym(loglvl, pc);
114111 return false;
115112 }
116113
117
-void show_stack(struct task_struct *task, unsigned long *sp)
114
+void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
118115 {
119116 pr_cont("Call Trace:\n");
120
- walk_stackframe(task, NULL, print_trace_address, NULL);
117
+ walk_stackframe(task, NULL, print_trace_address, (void *)loglvl);
121118 }
122
-
123119
124120 static bool save_wchan(unsigned long pc, void *arg)
125121 {
....@@ -169,8 +165,6 @@
169165 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
170166 {
171167 walk_stackframe(tsk, NULL, save_trace, trace);
172
- if (trace->nr_entries < trace->max_entries)
173
- trace->entries[trace->nr_entries++] = ULONG_MAX;
174168 }
175169 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
176170