1 // SPDX-License-Identifier: GPL-2.0
5 #include <linux/kernel.h>
6 #include <linux/zalloc.h>
9 #include "../../../perf-sys.h"
10 #include "../../../util/perf_regs.h"
11 #include "../../../util/debug.h"
12 #include "../../../util/event.h"
13 #include "../../../util/pmu.h"
14 #include "../../../util/pmus.h"
16 static const struct sample_reg sample_reg_masks
[] = {
17 SMPL_REG(AX
, PERF_REG_X86_AX
),
18 SMPL_REG(BX
, PERF_REG_X86_BX
),
19 SMPL_REG(CX
, PERF_REG_X86_CX
),
20 SMPL_REG(DX
, PERF_REG_X86_DX
),
21 SMPL_REG(SI
, PERF_REG_X86_SI
),
22 SMPL_REG(DI
, PERF_REG_X86_DI
),
23 SMPL_REG(BP
, PERF_REG_X86_BP
),
24 SMPL_REG(SP
, PERF_REG_X86_SP
),
25 SMPL_REG(IP
, PERF_REG_X86_IP
),
26 SMPL_REG(FLAGS
, PERF_REG_X86_FLAGS
),
27 SMPL_REG(CS
, PERF_REG_X86_CS
),
28 SMPL_REG(SS
, PERF_REG_X86_SS
),
29 #ifdef HAVE_ARCH_X86_64_SUPPORT
30 SMPL_REG(R8
, PERF_REG_X86_R8
),
31 SMPL_REG(R9
, PERF_REG_X86_R9
),
32 SMPL_REG(R10
, PERF_REG_X86_R10
),
33 SMPL_REG(R11
, PERF_REG_X86_R11
),
34 SMPL_REG(R12
, PERF_REG_X86_R12
),
35 SMPL_REG(R13
, PERF_REG_X86_R13
),
36 SMPL_REG(R14
, PERF_REG_X86_R14
),
37 SMPL_REG(R15
, PERF_REG_X86_R15
),
39 SMPL_REG2(XMM0
, PERF_REG_X86_XMM0
),
40 SMPL_REG2(XMM1
, PERF_REG_X86_XMM1
),
41 SMPL_REG2(XMM2
, PERF_REG_X86_XMM2
),
42 SMPL_REG2(XMM3
, PERF_REG_X86_XMM3
),
43 SMPL_REG2(XMM4
, PERF_REG_X86_XMM4
),
44 SMPL_REG2(XMM5
, PERF_REG_X86_XMM5
),
45 SMPL_REG2(XMM6
, PERF_REG_X86_XMM6
),
46 SMPL_REG2(XMM7
, PERF_REG_X86_XMM7
),
47 SMPL_REG2(XMM8
, PERF_REG_X86_XMM8
),
48 SMPL_REG2(XMM9
, PERF_REG_X86_XMM9
),
49 SMPL_REG2(XMM10
, PERF_REG_X86_XMM10
),
50 SMPL_REG2(XMM11
, PERF_REG_X86_XMM11
),
51 SMPL_REG2(XMM12
, PERF_REG_X86_XMM12
),
52 SMPL_REG2(XMM13
, PERF_REG_X86_XMM13
),
53 SMPL_REG2(XMM14
, PERF_REG_X86_XMM14
),
54 SMPL_REG2(XMM15
, PERF_REG_X86_XMM15
),
60 const char *uprobe_name
;
62 #define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
63 #define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
65 static const struct sdt_name_reg sdt_reg_tbl
[] = {
66 SDT_NAME_REG(eax
, ax
),
67 SDT_NAME_REG(rax
, ax
),
70 SDT_NAME_REG(ebx
, bx
),
71 SDT_NAME_REG(rbx
, bx
),
74 SDT_NAME_REG(ecx
, cx
),
75 SDT_NAME_REG(rcx
, cx
),
78 SDT_NAME_REG(edx
, dx
),
79 SDT_NAME_REG(rdx
, dx
),
82 SDT_NAME_REG(esi
, si
),
83 SDT_NAME_REG(rsi
, si
),
84 SDT_NAME_REG(sil
, si
),
85 SDT_NAME_REG(edi
, di
),
86 SDT_NAME_REG(rdi
, di
),
87 SDT_NAME_REG(dil
, di
),
88 SDT_NAME_REG(ebp
, bp
),
89 SDT_NAME_REG(rbp
, bp
),
90 SDT_NAME_REG(bpl
, bp
),
91 SDT_NAME_REG(rsp
, sp
),
92 SDT_NAME_REG(esp
, sp
),
93 SDT_NAME_REG(spl
, sp
),
96 SDT_NAME_REG(r8b
, r8
),
97 SDT_NAME_REG(r8w
, r8
),
98 SDT_NAME_REG(r8d
, r8
),
99 SDT_NAME_REG(r9b
, r9
),
100 SDT_NAME_REG(r9w
, r9
),
101 SDT_NAME_REG(r9d
, r9
),
102 SDT_NAME_REG(r10b
, r10
),
103 SDT_NAME_REG(r10w
, r10
),
104 SDT_NAME_REG(r10d
, r10
),
105 SDT_NAME_REG(r11b
, r11
),
106 SDT_NAME_REG(r11w
, r11
),
107 SDT_NAME_REG(r11d
, r11
),
108 SDT_NAME_REG(r12b
, r12
),
109 SDT_NAME_REG(r12w
, r12
),
110 SDT_NAME_REG(r12d
, r12
),
111 SDT_NAME_REG(r13b
, r13
),
112 SDT_NAME_REG(r13w
, r13
),
113 SDT_NAME_REG(r13d
, r13
),
114 SDT_NAME_REG(r14b
, r14
),
115 SDT_NAME_REG(r14w
, r14
),
116 SDT_NAME_REG(r14d
, r14
),
117 SDT_NAME_REG(r15b
, r15
),
118 SDT_NAME_REG(r15w
, r15
),
119 SDT_NAME_REG(r15d
, r15
),
124 * Perf only supports OP which is in +/-NUM(REG) form.
125 * Here plus-minus sign, NUM and parenthesis are optional,
126 * only REG is mandatory.
128 * SDT events also supports indirect addressing mode with a
129 * symbol as offset, scaled mode and constants in OP. But
130 * perf does not support them yet. Below are few examples.
132 * OP with scaled mode:
136 * OP with indirect addressing mode:
141 * OP with constant values:
146 #define SDT_OP_REGEX "^([+\\-]?)([0-9]*)(\\(?)(%[a-z][a-z0-9]+)(\\)?)$"
148 static regex_t sdt_op_regex
;
150 static int sdt_init_op_regex(void)
152 static int initialized
;
158 ret
= regcomp(&sdt_op_regex
, SDT_OP_REGEX
, REG_EXTENDED
);
160 pr_debug4("Regex compilation error.\n");
169 * Max x86 register name length is 5(ex: %r15d). So, 6th char
170 * should always contain NULL. This helps to find register name
171 * length using strlen, instead of maintaining one more variable.
173 #define SDT_REG_NAME_SIZE 6
176 * The uprobe parser does not support all gas register names;
177 * so, we have to replace them (ex. for x86_64: %rax -> %ax).
178 * Note: If register does not require renaming, just copy
179 * paste as it is, but don't leave it empty.
181 static void sdt_rename_register(char *sdt_reg
, int sdt_len
, char *uprobe_reg
)
185 for (i
= 0; sdt_reg_tbl
[i
].sdt_name
!= NULL
; i
++) {
186 if (!strncmp(sdt_reg_tbl
[i
].sdt_name
, sdt_reg
, sdt_len
)) {
187 strcpy(uprobe_reg
, sdt_reg_tbl
[i
].uprobe_name
);
192 strncpy(uprobe_reg
, sdt_reg
, sdt_len
);
195 int arch_sdt_arg_parse_op(char *old_op
, char **new_op
)
197 char new_reg
[SDT_REG_NAME_SIZE
] = {0};
198 int new_len
= 0, ret
;
209 * Max prefix length is 2 as it may contains sign(+/-)
210 * and displacement 0 (Both sign and displacement 0 are
211 * optional so it may be empty). Use one more character
212 * to hold last NULL so that strlen can be used to find
213 * prefix length, instead of maintaining one more variable.
215 char prefix
[3] = {0};
217 ret
= sdt_init_op_regex();
222 * If unsupported OR does not match with regex OR
223 * register name too long, skip it.
225 if (strchr(old_op
, ',') || strchr(old_op
, '$') ||
226 regexec(&sdt_op_regex
, old_op
, 6, rm
, 0) ||
227 rm
[4].rm_eo
- rm
[4].rm_so
> SDT_REG_NAME_SIZE
) {
228 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op
);
234 * If SDT OP has parenthesis but does not provide
235 * displacement, add 0 for displacement.
237 * -----------------------------
238 * +24(%rdi) +24(%di) +
239 * 24(%rdi) +24(%di) +
242 * -80(%rbx) -80(%bx) -
244 if (rm
[3].rm_so
!= rm
[3].rm_eo
) {
245 if (rm
[1].rm_so
!= rm
[1].rm_eo
)
246 prefix
[0] = *(old_op
+ rm
[1].rm_so
);
247 else if (rm
[2].rm_so
!= rm
[2].rm_eo
)
250 scnprintf(prefix
, sizeof(prefix
), "+0");
253 /* Rename register */
254 sdt_rename_register(old_op
+ rm
[4].rm_so
, rm
[4].rm_eo
- rm
[4].rm_so
,
257 /* Prepare final OP which should be valid for uprobe_events */
258 new_len
= strlen(prefix
) +
259 (rm
[2].rm_eo
- rm
[2].rm_so
) +
260 (rm
[3].rm_eo
- rm
[3].rm_so
) +
262 (rm
[5].rm_eo
- rm
[5].rm_so
) +
265 *new_op
= zalloc(new_len
);
269 scnprintf(*new_op
, new_len
, "%.*s%.*s%.*s%.*s%.*s",
270 strlen(prefix
), prefix
,
271 (int)(rm
[2].rm_eo
- rm
[2].rm_so
), old_op
+ rm
[2].rm_so
,
272 (int)(rm
[3].rm_eo
- rm
[3].rm_so
), old_op
+ rm
[3].rm_so
,
273 strlen(new_reg
), new_reg
,
274 (int)(rm
[5].rm_eo
- rm
[5].rm_so
), old_op
+ rm
[5].rm_so
);
276 return SDT_ARG_VALID
;
279 const struct sample_reg
*arch__sample_reg_masks(void)
281 return sample_reg_masks
;
284 uint64_t arch__intr_reg_mask(void)
286 struct perf_event_attr attr
= {
287 .type
= PERF_TYPE_HARDWARE
,
288 .config
= PERF_COUNT_HW_CPU_CYCLES
,
289 .sample_type
= PERF_SAMPLE_REGS_INTR
,
290 .sample_regs_intr
= PERF_REG_EXTENDED_MASK
,
297 * In an unnamed union, init it here to build on older gcc versions
299 attr
.sample_period
= 1;
301 if (perf_pmus__num_core_pmus() > 1) {
302 struct perf_pmu
*pmu
= NULL
;
303 __u64 type
= PERF_TYPE_RAW
;
306 * The same register set is supported among different hybrid PMUs.
307 * Only check the first available one.
309 while ((pmu
= perf_pmus__scan_core(pmu
)) != NULL
) {
313 attr
.config
|= type
<< PERF_PMU_TYPE_SHIFT
;
316 event_attr_init(&attr
);
318 fd
= sys_perf_event_open(&attr
, 0, -1, -1, 0);
321 return (PERF_REG_EXTENDED_MASK
| PERF_REGS_MASK
);
324 return PERF_REGS_MASK
;
327 uint64_t arch__user_reg_mask(void)
329 return PERF_REGS_MASK
;