1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <errno.h>
4 #include <string.h>
5 #include <regex.h>
6 #include <linux/kernel.h>
7 #include <linux/zalloc.h>
8
9 #include "../debug.h"
10 #include "../event.h"
11 #include "../pmu.h"
12 #include "../pmus.h"
13 #include "../perf_regs.h"
14 #include "../../perf-sys.h"
15 #include "../../arch/x86/include/perf_regs.h"
16
17 struct sdt_name_reg {
18 const char *sdt_name;
19 const char *uprobe_name;
20 };
21 #define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
22 #define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
23
24 static const struct sdt_name_reg sdt_reg_tbl[] = {
25 SDT_NAME_REG(eax, ax),
26 SDT_NAME_REG(rax, ax),
27 SDT_NAME_REG(al, ax),
28 SDT_NAME_REG(ah, ax),
29 SDT_NAME_REG(ebx, bx),
30 SDT_NAME_REG(rbx, bx),
31 SDT_NAME_REG(bl, bx),
32 SDT_NAME_REG(bh, bx),
33 SDT_NAME_REG(ecx, cx),
34 SDT_NAME_REG(rcx, cx),
35 SDT_NAME_REG(cl, cx),
36 SDT_NAME_REG(ch, cx),
37 SDT_NAME_REG(edx, dx),
38 SDT_NAME_REG(rdx, dx),
39 SDT_NAME_REG(dl, dx),
40 SDT_NAME_REG(dh, dx),
41 SDT_NAME_REG(esi, si),
42 SDT_NAME_REG(rsi, si),
43 SDT_NAME_REG(sil, si),
44 SDT_NAME_REG(edi, di),
45 SDT_NAME_REG(rdi, di),
46 SDT_NAME_REG(dil, di),
47 SDT_NAME_REG(ebp, bp),
48 SDT_NAME_REG(rbp, bp),
49 SDT_NAME_REG(bpl, bp),
50 SDT_NAME_REG(rsp, sp),
51 SDT_NAME_REG(esp, sp),
52 SDT_NAME_REG(spl, sp),
53
54 /* rNN registers */
55 SDT_NAME_REG(r8b, r8),
56 SDT_NAME_REG(r8w, r8),
57 SDT_NAME_REG(r8d, r8),
58 SDT_NAME_REG(r9b, r9),
59 SDT_NAME_REG(r9w, r9),
60 SDT_NAME_REG(r9d, r9),
61 SDT_NAME_REG(r10b, r10),
62 SDT_NAME_REG(r10w, r10),
63 SDT_NAME_REG(r10d, r10),
64 SDT_NAME_REG(r11b, r11),
65 SDT_NAME_REG(r11w, r11),
66 SDT_NAME_REG(r11d, r11),
67 SDT_NAME_REG(r12b, r12),
68 SDT_NAME_REG(r12w, r12),
69 SDT_NAME_REG(r12d, r12),
70 SDT_NAME_REG(r13b, r13),
71 SDT_NAME_REG(r13w, r13),
72 SDT_NAME_REG(r13d, r13),
73 SDT_NAME_REG(r14b, r14),
74 SDT_NAME_REG(r14w, r14),
75 SDT_NAME_REG(r14d, r14),
76 SDT_NAME_REG(r15b, r15),
77 SDT_NAME_REG(r15w, r15),
78 SDT_NAME_REG(r15d, r15),
79 SDT_NAME_REG_END,
80 };
81
82 /*
83 * Perf only supports OP which is in +/-NUM(REG) form.
84 * Here plus-minus sign, NUM and parenthesis are optional,
85 * only REG is mandatory.
86 *
87 * SDT events also supports indirect addressing mode with a
88 * symbol as offset, scaled mode and constants in OP. But
89 * perf does not support them yet. Below are few examples.
90 *
91 * OP with scaled mode:
92 * (%rax,%rsi,8)
93 * 10(%ras,%rsi,8)
94 *
95 * OP with indirect addressing mode:
96 * check_action(%rip)
97 * mp_+52(%rip)
98 * 44+mp_(%rip)
99 *
100 * OP with constant values:
101 * $0
102 * $123
103 * $-1
104 */
105 #define SDT_OP_REGEX "^([+\\-]?)([0-9]*)(\\(?)(%[a-z][a-z0-9]+)(\\)?)$"
106
107 static regex_t sdt_op_regex;
108
sdt_init_op_regex(void)109 static int sdt_init_op_regex(void)
110 {
111 static int initialized;
112 int ret = 0;
113
114 if (initialized)
115 return 0;
116
117 ret = regcomp(&sdt_op_regex, SDT_OP_REGEX, REG_EXTENDED);
118 if (ret < 0) {
119 pr_debug4("Regex compilation error.\n");
120 return ret;
121 }
122
123 initialized = 1;
124 return 0;
125 }
126
127 /*
128 * Max x86 register name length is 5(ex: %r15d). So, 6th char
129 * should always contain NULL. This helps to find register name
130 * length using strlen, instead of maintaining one more variable.
131 */
132 #define SDT_REG_NAME_SIZE 6
133
134 /*
135 * The uprobe parser does not support all gas register names;
136 * so, we have to replace them (ex. for x86_64: %rax -> %ax).
137 * Note: If register does not require renaming, just copy
138 * paste as it is, but don't leave it empty.
139 */
sdt_rename_register(char * sdt_reg,int sdt_len,char * uprobe_reg)140 static void sdt_rename_register(char *sdt_reg, int sdt_len, char *uprobe_reg)
141 {
142 int i = 0;
143
144 for (i = 0; sdt_reg_tbl[i].sdt_name != NULL; i++) {
145 if (!strncmp(sdt_reg_tbl[i].sdt_name, sdt_reg, sdt_len)) {
146 strcpy(uprobe_reg, sdt_reg_tbl[i].uprobe_name);
147 return;
148 }
149 }
150
151 strncpy(uprobe_reg, sdt_reg, sdt_len);
152 }
153
__perf_sdt_arg_parse_op_x86(char * old_op,char ** new_op)154 int __perf_sdt_arg_parse_op_x86(char *old_op, char **new_op)
155 {
156 char new_reg[SDT_REG_NAME_SIZE] = {0};
157 int new_len = 0, ret;
158 /*
159 * rm[0]: +/-NUM(REG)
160 * rm[1]: +/-
161 * rm[2]: NUM
162 * rm[3]: (
163 * rm[4]: REG
164 * rm[5]: )
165 */
166 regmatch_t rm[6];
167 /*
168 * Max prefix length is 2 as it may contains sign(+/-)
169 * and displacement 0 (Both sign and displacement 0 are
170 * optional so it may be empty). Use one more character
171 * to hold last NULL so that strlen can be used to find
172 * prefix length, instead of maintaining one more variable.
173 */
174 char prefix[3] = {0};
175
176 ret = sdt_init_op_regex();
177 if (ret < 0)
178 return ret;
179
180 /*
181 * If unsupported OR does not match with regex OR
182 * register name too long, skip it.
183 */
184 if (strchr(old_op, ',') || strchr(old_op, '$') ||
185 regexec(&sdt_op_regex, old_op, 6, rm, 0) ||
186 rm[4].rm_eo - rm[4].rm_so > SDT_REG_NAME_SIZE) {
187 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
188 return SDT_ARG_SKIP;
189 }
190
191 /*
192 * Prepare prefix.
193 * If SDT OP has parenthesis but does not provide
194 * displacement, add 0 for displacement.
195 * SDT Uprobe Prefix
196 * -----------------------------
197 * +24(%rdi) +24(%di) +
198 * 24(%rdi) +24(%di) +
199 * %rdi %di
200 * (%rdi) +0(%di) +0
201 * -80(%rbx) -80(%bx) -
202 */
203 if (rm[3].rm_so != rm[3].rm_eo) {
204 if (rm[1].rm_so != rm[1].rm_eo)
205 prefix[0] = *(old_op + rm[1].rm_so);
206 else if (rm[2].rm_so != rm[2].rm_eo)
207 prefix[0] = '+';
208 else
209 scnprintf(prefix, sizeof(prefix), "+0");
210 }
211
212 /* Rename register */
213 sdt_rename_register(old_op + rm[4].rm_so, rm[4].rm_eo - rm[4].rm_so,
214 new_reg);
215
216 /* Prepare final OP which should be valid for uprobe_events */
217 new_len = strlen(prefix) +
218 (rm[2].rm_eo - rm[2].rm_so) +
219 (rm[3].rm_eo - rm[3].rm_so) +
220 strlen(new_reg) +
221 (rm[5].rm_eo - rm[5].rm_so) +
222 1; /* NULL */
223
224 *new_op = zalloc(new_len);
225 if (!*new_op)
226 return -ENOMEM;
227
228 scnprintf(*new_op, new_len, "%.*s%.*s%.*s%.*s%.*s",
229 strlen(prefix), prefix,
230 (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
231 (int)(rm[3].rm_eo - rm[3].rm_so), old_op + rm[3].rm_so,
232 strlen(new_reg), new_reg,
233 (int)(rm[5].rm_eo - rm[5].rm_so), old_op + rm[5].rm_so);
234
235 return SDT_ARG_VALID;
236 }
237
__perf_reg_mask_x86(bool intr)238 uint64_t __perf_reg_mask_x86(bool intr)
239 {
240 struct perf_event_attr attr = {
241 .type = PERF_TYPE_HARDWARE,
242 .config = PERF_COUNT_HW_CPU_CYCLES,
243 .sample_type = PERF_SAMPLE_REGS_INTR,
244 .sample_regs_intr = PERF_REG_EXTENDED_MASK,
245 .precise_ip = 1,
246 .disabled = 1,
247 .exclude_kernel = 1,
248 };
249 int fd;
250
251 if (!intr)
252 return PERF_REGS_MASK;
253
254 /*
255 * In an unnamed union, init it here to build on older gcc versions
256 */
257 attr.sample_period = 1;
258
259 if (perf_pmus__num_core_pmus() > 1) {
260 struct perf_pmu *pmu = NULL;
261 __u64 type = PERF_TYPE_RAW;
262
263 /*
264 * The same register set is supported among different hybrid PMUs.
265 * Only check the first available one.
266 */
267 while ((pmu = perf_pmus__scan_core(pmu)) != NULL) {
268 type = pmu->type;
269 break;
270 }
271 attr.config |= type << PERF_PMU_TYPE_SHIFT;
272 }
273
274 event_attr_init(&attr);
275 fd = sys_perf_event_open(&attr, /*pid=*/0, /*cpu=*/-1,
276 /*group_fd=*/-1, /*flags=*/0);
277 if (fd != -1) {
278 close(fd);
279 return (PERF_REG_EXTENDED_MASK | PERF_REGS_MASK);
280 }
281
282 return PERF_REGS_MASK;
283 }
284
__perf_reg_name_x86(int id)285 const char *__perf_reg_name_x86(int id)
286 {
287 switch (id) {
288 case PERF_REG_X86_AX:
289 return "AX";
290 case PERF_REG_X86_BX:
291 return "BX";
292 case PERF_REG_X86_CX:
293 return "CX";
294 case PERF_REG_X86_DX:
295 return "DX";
296 case PERF_REG_X86_SI:
297 return "SI";
298 case PERF_REG_X86_DI:
299 return "DI";
300 case PERF_REG_X86_BP:
301 return "BP";
302 case PERF_REG_X86_SP:
303 return "SP";
304 case PERF_REG_X86_IP:
305 return "IP";
306 case PERF_REG_X86_FLAGS:
307 return "FLAGS";
308 case PERF_REG_X86_CS:
309 return "CS";
310 case PERF_REG_X86_SS:
311 return "SS";
312 case PERF_REG_X86_DS:
313 return "DS";
314 case PERF_REG_X86_ES:
315 return "ES";
316 case PERF_REG_X86_FS:
317 return "FS";
318 case PERF_REG_X86_GS:
319 return "GS";
320 case PERF_REG_X86_R8:
321 return "R8";
322 case PERF_REG_X86_R9:
323 return "R9";
324 case PERF_REG_X86_R10:
325 return "R10";
326 case PERF_REG_X86_R11:
327 return "R11";
328 case PERF_REG_X86_R12:
329 return "R12";
330 case PERF_REG_X86_R13:
331 return "R13";
332 case PERF_REG_X86_R14:
333 return "R14";
334 case PERF_REG_X86_R15:
335 return "R15";
336
337 #define XMM(x) \
338 case PERF_REG_X86_XMM ## x: \
339 case PERF_REG_X86_XMM ## x + 1: \
340 return "XMM" #x;
341 XMM(0)
342 XMM(1)
343 XMM(2)
344 XMM(3)
345 XMM(4)
346 XMM(5)
347 XMM(6)
348 XMM(7)
349 XMM(8)
350 XMM(9)
351 XMM(10)
352 XMM(11)
353 XMM(12)
354 XMM(13)
355 XMM(14)
356 XMM(15)
357 #undef XMM
358 default:
359 return NULL;
360 }
361
362 return NULL;
363 }
364
__perf_reg_ip_x86(void)365 uint64_t __perf_reg_ip_x86(void)
366 {
367 return PERF_REG_X86_IP;
368 }
369
__perf_reg_sp_x86(void)370 uint64_t __perf_reg_sp_x86(void)
371 {
372 return PERF_REG_X86_SP;
373 }
374