xref: /linux/tools/perf/util/perf_regs.c (revision b2128290c29902315e632ea59e0504d6bc9e9b42)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <elf.h>
3 #include <errno.h>
4 #include <string.h>
5 #include "dwarf-regs.h"
6 #include "perf_regs.h"
7 #include "util/sample.h"
8 #include "debug.h"
9 
10 int perf_sdt_arg_parse_op(uint16_t e_machine, char *old_op, char **new_op)
11 {
12 	int ret = SDT_ARG_SKIP;
13 
14 	switch (e_machine) {
15 	case EM_AARCH64:
16 		ret = __perf_sdt_arg_parse_op_arm64(old_op, new_op);
17 		break;
18 	case EM_PPC:
19 	case EM_PPC64:
20 		ret = __perf_sdt_arg_parse_op_powerpc(old_op, new_op);
21 		break;
22 	case EM_RISCV:
23 		ret = __perf_sdt_arg_parse_op_riscv(old_op, new_op);
24 		break;
25 	case EM_386:
26 	case EM_X86_64:
27 		ret = __perf_sdt_arg_parse_op_x86(old_op, new_op);
28 		break;
29 	case EM_S390:
30 		ret = __perf_sdt_arg_parse_op_s390(old_op, new_op);
31 		break;
32 	default:
33 		pr_debug("Unknown ELF machine %d, standard arguments parse will be skipped.\n",
34 			 e_machine);
35 		break;
36 	}
37 
38 	return ret;
39 }
40 
41 uint64_t perf_intr_reg_mask(uint16_t e_machine)
42 {
43 	uint64_t mask = 0;
44 
45 	switch (e_machine) {
46 	case EM_ARM:
47 		mask = __perf_reg_mask_arm(/*intr=*/true);
48 		break;
49 	case EM_AARCH64:
50 		mask = __perf_reg_mask_arm64(/*intr=*/true);
51 		break;
52 	case EM_CSKY:
53 		mask = __perf_reg_mask_csky(/*intr=*/true);
54 		break;
55 	case EM_LOONGARCH:
56 		mask = __perf_reg_mask_loongarch(/*intr=*/true);
57 		break;
58 	case EM_MIPS:
59 		mask = __perf_reg_mask_mips(/*intr=*/true);
60 		break;
61 	case EM_PPC:
62 	case EM_PPC64:
63 		mask = __perf_reg_mask_powerpc(/*intr=*/true);
64 		break;
65 	case EM_RISCV:
66 		mask = __perf_reg_mask_riscv(/*intr=*/true);
67 		break;
68 	case EM_S390:
69 		mask = __perf_reg_mask_s390(/*intr=*/true);
70 		break;
71 	case EM_386:
72 	case EM_X86_64:
73 		mask = __perf_reg_mask_x86(/*intr=*/true);
74 		break;
75 	default:
76 		pr_debug("Unknown ELF machine %d, interrupt sampling register mask will be empty.\n",
77 			 e_machine);
78 		break;
79 	}
80 
81 	return mask;
82 }
83 
84 uint64_t perf_user_reg_mask(uint16_t e_machine)
85 {
86 	uint64_t mask = 0;
87 
88 	switch (e_machine) {
89 	case EM_ARM:
90 		mask = __perf_reg_mask_arm(/*intr=*/false);
91 		break;
92 	case EM_AARCH64:
93 		mask = __perf_reg_mask_arm64(/*intr=*/false);
94 		break;
95 	case EM_CSKY:
96 		mask = __perf_reg_mask_csky(/*intr=*/false);
97 		break;
98 	case EM_LOONGARCH:
99 		mask = __perf_reg_mask_loongarch(/*intr=*/false);
100 		break;
101 	case EM_MIPS:
102 		mask = __perf_reg_mask_mips(/*intr=*/false);
103 		break;
104 	case EM_PPC:
105 	case EM_PPC64:
106 		mask = __perf_reg_mask_powerpc(/*intr=*/false);
107 		break;
108 	case EM_RISCV:
109 		mask = __perf_reg_mask_riscv(/*intr=*/false);
110 		break;
111 	case EM_S390:
112 		mask = __perf_reg_mask_s390(/*intr=*/false);
113 		break;
114 	case EM_386:
115 	case EM_X86_64:
116 		mask = __perf_reg_mask_x86(/*intr=*/false);
117 		break;
118 	default:
119 		pr_debug("Unknown ELF machine %d, user sampling register mask will be empty.\n",
120 			 e_machine);
121 		break;
122 	}
123 
124 	return mask;
125 }
126 
127 const char *perf_reg_name(int id, uint16_t e_machine, uint32_t e_flags)
128 {
129 	const char *reg_name = NULL;
130 
131 	switch (e_machine) {
132 	case EM_ARM:
133 		reg_name = __perf_reg_name_arm(id);
134 		break;
135 	case EM_AARCH64:
136 		reg_name = __perf_reg_name_arm64(id);
137 		break;
138 	case EM_CSKY:
139 		reg_name = __perf_reg_name_csky(id, e_flags);
140 		break;
141 	case EM_LOONGARCH:
142 		reg_name = __perf_reg_name_loongarch(id);
143 		break;
144 	case EM_MIPS:
145 		reg_name = __perf_reg_name_mips(id);
146 		break;
147 	case EM_PPC:
148 	case EM_PPC64:
149 		reg_name = __perf_reg_name_powerpc(id);
150 		break;
151 	case EM_RISCV:
152 		reg_name = __perf_reg_name_riscv(id);
153 		break;
154 	case EM_S390:
155 		reg_name = __perf_reg_name_s390(id);
156 		break;
157 	case EM_386:
158 	case EM_X86_64:
159 		reg_name = __perf_reg_name_x86(id);
160 		break;
161 	default:
162 		break;
163 	}
164 	if (reg_name)
165 		return reg_name;
166 
167 	pr_debug("Failed to find register %d for ELF machine type %u\n", id, e_machine);
168 	return "unknown";
169 }
170 
171 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
172 {
173 	int i, idx = 0;
174 	u64 mask = regs->mask;
175 
176 	if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE)
177 		return -EINVAL;
178 
179 	if (regs->cache_mask & (1ULL << id))
180 		goto out;
181 
182 	if (!(mask & (1ULL << id)))
183 		return -EINVAL;
184 
185 	for (i = 0; i < id; i++) {
186 		if (mask & (1ULL << i))
187 			idx++;
188 	}
189 
190 	regs->cache_mask |= (1ULL << id);
191 	regs->cache_regs[id] = regs->regs[idx];
192 
193 out:
194 	*valp = regs->cache_regs[id];
195 	return 0;
196 }
197 
198 uint64_t perf_arch_reg_ip(uint16_t e_machine)
199 {
200 	switch (e_machine) {
201 	case EM_ARM:
202 		return __perf_reg_ip_arm();
203 	case EM_AARCH64:
204 		return __perf_reg_ip_arm64();
205 	case EM_CSKY:
206 		return __perf_reg_ip_csky();
207 	case EM_LOONGARCH:
208 		return __perf_reg_ip_loongarch();
209 	case EM_MIPS:
210 		return __perf_reg_ip_mips();
211 	case EM_PPC:
212 	case EM_PPC64:
213 		return __perf_reg_ip_powerpc();
214 	case EM_RISCV:
215 		return __perf_reg_ip_riscv();
216 	case EM_S390:
217 		return __perf_reg_ip_s390();
218 	case EM_386:
219 	case EM_X86_64:
220 		return __perf_reg_ip_x86();
221 	default:
222 		pr_err("Failed to find IP register for ELF machine type %u\n", e_machine);
223 		return 0;
224 	}
225 }
226 
227 uint64_t perf_arch_reg_sp(uint16_t e_machine)
228 {
229 	switch (e_machine) {
230 	case EM_ARM:
231 		return __perf_reg_sp_arm();
232 	case EM_AARCH64:
233 		return __perf_reg_sp_arm64();
234 	case EM_CSKY:
235 		return __perf_reg_sp_csky();
236 	case EM_LOONGARCH:
237 		return __perf_reg_sp_loongarch();
238 	case EM_MIPS:
239 		return __perf_reg_sp_mips();
240 	case EM_PPC:
241 	case EM_PPC64:
242 		return __perf_reg_sp_powerpc();
243 	case EM_RISCV:
244 		return __perf_reg_sp_riscv();
245 	case EM_S390:
246 		return __perf_reg_sp_s390();
247 	case EM_386:
248 	case EM_X86_64:
249 		return __perf_reg_sp_x86();
250 	default:
251 		pr_err("Failed to find SP register for ELF machine type %u\n", e_machine);
252 		return 0;
253 	}
254 }
255