hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/arch/arm64/kernel/perf_callchain.c
....@@ -1,23 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * arm64 callchain support
34 *
45 * Copyright (C) 2015 ARM Limited
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
176 */
187 #include <linux/perf_event.h>
198 #include <linux/uaccess.h>
209
10
+#include <asm/pointer_auth.h>
2111 #include <asm/stacktrace.h>
2212
2313 struct frame_tail {
....@@ -35,9 +25,10 @@
3525 {
3626 struct frame_tail buftail;
3727 unsigned long err;
28
+ unsigned long lr;
3829
3930 /* Also check accessibility of one struct frame_tail beyond */
40
- if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
31
+ if (!access_ok(tail, sizeof(buftail)))
4132 return NULL;
4233
4334 pagefault_disable();
....@@ -47,7 +38,9 @@
4738 if (err)
4839 return NULL;
4940
50
- perf_callchain_store(entry, buftail.lr);
41
+ lr = ptrauth_strip_insn_pac(buftail.lr);
42
+
43
+ perf_callchain_store(entry, lr);
5144
5245 /*
5346 * Frame pointers should strictly progress back up the stack
....@@ -82,7 +75,7 @@
8275 unsigned long err;
8376
8477 /* Also check accessibility of one struct frame_tail beyond */
85
- if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
78
+ if (!access_ok(tail, sizeof(buftail)))
8679 return NULL;
8780
8881 pagefault_disable();
....@@ -109,7 +102,9 @@
109102 void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
110103 struct pt_regs *regs)
111104 {
112
- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
105
+ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
106
+
107
+ if (guest_cbs && guest_cbs->is_in_guest()) {
113108 /* We don't support guest os callchain now */
114109 return;
115110 }
....@@ -144,46 +139,45 @@
144139 * whist unwinding the stackframe and is like a subroutine return so we use
145140 * the PC.
146141 */
147
-static int callchain_trace(struct stackframe *frame, void *data)
142
+static bool callchain_trace(void *data, unsigned long pc)
148143 {
149144 struct perf_callchain_entry_ctx *entry = data;
150
- perf_callchain_store(entry, frame->pc);
151
- return 0;
145
+ perf_callchain_store(entry, pc);
146
+ return true;
152147 }
153148
154149 void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
155150 struct pt_regs *regs)
156151 {
152
+ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
157153 struct stackframe frame;
158154
159
- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
155
+ if (guest_cbs && guest_cbs->is_in_guest()) {
160156 /* We don't support guest os callchain now */
161157 return;
162158 }
163159
164
- frame.fp = regs->regs[29];
165
- frame.pc = regs->pc;
166
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
167
- frame.graph = current->curr_ret_stack;
168
-#endif
169
-
160
+ start_backtrace(&frame, regs->regs[29], regs->pc);
170161 walk_stackframe(current, &frame, callchain_trace, entry);
171162 }
172163
173164 unsigned long perf_instruction_pointer(struct pt_regs *regs)
174165 {
175
- if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
176
- return perf_guest_cbs->get_guest_ip();
166
+ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
167
+
168
+ if (guest_cbs && guest_cbs->is_in_guest())
169
+ return guest_cbs->get_guest_ip();
177170
178171 return instruction_pointer(regs);
179172 }
180173
181174 unsigned long perf_misc_flags(struct pt_regs *regs)
182175 {
176
+ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
183177 int misc = 0;
184178
185
- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
186
- if (perf_guest_cbs->is_user_mode())
179
+ if (guest_cbs && guest_cbs->is_in_guest()) {
180
+ if (guest_cbs->is_user_mode())
187181 misc |= PERF_RECORD_MISC_GUEST_USER;
188182 else
189183 misc |= PERF_RECORD_MISC_GUEST_KERNEL;