1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/kernel.h>
7 #include <linux/zalloc.h>
10 #include "../../../perf-sys.h"
11 #include "../../../util/debug.h"
12 #include "../../../util/event.h"
13 #include "../../../util/perf_regs.h"
16 #define HWCAP_SVE (1 << 22)
19 static const struct sample_reg sample_reg_masks
[] = {
20 SMPL_REG(x0
, PERF_REG_ARM64_X0
),
21 SMPL_REG(x1
, PERF_REG_ARM64_X1
),
22 SMPL_REG(x2
, PERF_REG_ARM64_X2
),
23 SMPL_REG(x3
, PERF_REG_ARM64_X3
),
24 SMPL_REG(x4
, PERF_REG_ARM64_X4
),
25 SMPL_REG(x5
, PERF_REG_ARM64_X5
),
26 SMPL_REG(x6
, PERF_REG_ARM64_X6
),
27 SMPL_REG(x7
, PERF_REG_ARM64_X7
),
28 SMPL_REG(x8
, PERF_REG_ARM64_X8
),
29 SMPL_REG(x9
, PERF_REG_ARM64_X9
),
30 SMPL_REG(x10
, PERF_REG_ARM64_X10
),
31 SMPL_REG(x11
, PERF_REG_ARM64_X11
),
32 SMPL_REG(x12
, PERF_REG_ARM64_X12
),
33 SMPL_REG(x13
, PERF_REG_ARM64_X13
),
34 SMPL_REG(x14
, PERF_REG_ARM64_X14
),
35 SMPL_REG(x15
, PERF_REG_ARM64_X15
),
36 SMPL_REG(x16
, PERF_REG_ARM64_X16
),
37 SMPL_REG(x17
, PERF_REG_ARM64_X17
),
38 SMPL_REG(x18
, PERF_REG_ARM64_X18
),
39 SMPL_REG(x19
, PERF_REG_ARM64_X19
),
40 SMPL_REG(x20
, PERF_REG_ARM64_X20
),
41 SMPL_REG(x21
, PERF_REG_ARM64_X21
),
42 SMPL_REG(x22
, PERF_REG_ARM64_X22
),
43 SMPL_REG(x23
, PERF_REG_ARM64_X23
),
44 SMPL_REG(x24
, PERF_REG_ARM64_X24
),
45 SMPL_REG(x25
, PERF_REG_ARM64_X25
),
46 SMPL_REG(x26
, PERF_REG_ARM64_X26
),
47 SMPL_REG(x27
, PERF_REG_ARM64_X27
),
48 SMPL_REG(x28
, PERF_REG_ARM64_X28
),
49 SMPL_REG(x29
, PERF_REG_ARM64_X29
),
50 SMPL_REG(lr
, PERF_REG_ARM64_LR
),
51 SMPL_REG(sp
, PERF_REG_ARM64_SP
),
52 SMPL_REG(pc
, PERF_REG_ARM64_PC
),
53 SMPL_REG(vg
, PERF_REG_ARM64_VG
),
58 #define SDT_OP_REGEX1 "^(x[1-2]?[0-9]|3[0-1])$"
61 #define SDT_OP_REGEX2 "^\\[sp(, )?([0-9]+)?\\]$"
63 static regex_t sdt_op_regex1
, sdt_op_regex2
;
65 static int sdt_init_op_regex(void)
67 static int initialized
;
73 ret
= regcomp(&sdt_op_regex1
, SDT_OP_REGEX1
, REG_EXTENDED
);
77 ret
= regcomp(&sdt_op_regex2
, SDT_OP_REGEX2
, REG_EXTENDED
);
85 regfree(&sdt_op_regex1
);
87 pr_debug4("Regex compilation error.\n");
92 * SDT marker arguments on Arm64 uses %xREG or [sp, NUM], currently
93 * support these two formats.
95 int arch_sdt_arg_parse_op(char *old_op
, char **new_op
)
100 ret
= sdt_init_op_regex();
104 if (!regexec(&sdt_op_regex1
, old_op
, 3, rm
, 0)) {
106 new_len
= 2; /* % NULL */
107 new_len
+= (int)(rm
[1].rm_eo
- rm
[1].rm_so
);
109 *new_op
= zalloc(new_len
);
113 scnprintf(*new_op
, new_len
, "%%%.*s",
114 (int)(rm
[1].rm_eo
- rm
[1].rm_so
), old_op
+ rm
[1].rm_so
);
115 } else if (!regexec(&sdt_op_regex2
, old_op
, 5, rm
, 0)) {
116 /* [sp], [sp, NUM] or [sp,NUM] */
117 new_len
= 7; /* + ( % s p ) NULL */
119 /* If the argument is [sp], need to fill offset '0' */
120 if (rm
[2].rm_so
== -1)
123 new_len
+= (int)(rm
[2].rm_eo
- rm
[2].rm_so
);
125 *new_op
= zalloc(new_len
);
129 if (rm
[2].rm_so
== -1)
130 scnprintf(*new_op
, new_len
, "+0(%%sp)");
132 scnprintf(*new_op
, new_len
, "+%.*s(%%sp)",
133 (int)(rm
[2].rm_eo
- rm
[2].rm_so
),
134 old_op
+ rm
[2].rm_so
);
136 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op
);
140 return SDT_ARG_VALID
;
143 uint64_t arch__intr_reg_mask(void)
145 return PERF_REGS_MASK
;
148 uint64_t arch__user_reg_mask(void)
150 struct perf_event_attr attr
= {
151 .type
= PERF_TYPE_HARDWARE
,
152 .config
= PERF_COUNT_HW_CPU_CYCLES
,
153 .sample_type
= PERF_SAMPLE_REGS_USER
,
157 .sample_regs_user
= PERF_REGS_MASK
161 if (getauxval(AT_HWCAP
) & HWCAP_SVE
)
162 attr
.sample_regs_user
|= SMPL_REG_MASK(PERF_REG_ARM64_VG
);
165 * Check if the pmu supports perf extended regs, before
166 * returning the register mask to sample.
168 if (attr
.sample_regs_user
!= PERF_REGS_MASK
) {
169 event_attr_init(&attr
);
170 fd
= sys_perf_event_open(&attr
, 0, -1, -1, 0);
173 return attr
.sample_regs_user
;
176 return PERF_REGS_MASK
;
179 const struct sample_reg
*arch__sample_reg_masks(void)
181 return sample_reg_masks
;