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