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