1 // SPDX-License-Identifier: GPL-2.0
5 #include <linux/zalloc.h>
7 #include "../../../util/perf_regs.h"
8 #include "../../../util/debug.h"
9 #include "../../../util/event.h"
10 #include "../../../util/header.h"
11 #include "../../../perf-sys.h"
12 #include "utils_header.h"
14 #include <linux/kernel.h>
16 #define PVR_POWER9 0x004E
17 #define PVR_POWER10 0x0080
19 const struct sample_reg sample_reg_masks
[] = {
20 SMPL_REG(r0
, PERF_REG_POWERPC_R0
),
21 SMPL_REG(r1
, PERF_REG_POWERPC_R1
),
22 SMPL_REG(r2
, PERF_REG_POWERPC_R2
),
23 SMPL_REG(r3
, PERF_REG_POWERPC_R3
),
24 SMPL_REG(r4
, PERF_REG_POWERPC_R4
),
25 SMPL_REG(r5
, PERF_REG_POWERPC_R5
),
26 SMPL_REG(r6
, PERF_REG_POWERPC_R6
),
27 SMPL_REG(r7
, PERF_REG_POWERPC_R7
),
28 SMPL_REG(r8
, PERF_REG_POWERPC_R8
),
29 SMPL_REG(r9
, PERF_REG_POWERPC_R9
),
30 SMPL_REG(r10
, PERF_REG_POWERPC_R10
),
31 SMPL_REG(r11
, PERF_REG_POWERPC_R11
),
32 SMPL_REG(r12
, PERF_REG_POWERPC_R12
),
33 SMPL_REG(r13
, PERF_REG_POWERPC_R13
),
34 SMPL_REG(r14
, PERF_REG_POWERPC_R14
),
35 SMPL_REG(r15
, PERF_REG_POWERPC_R15
),
36 SMPL_REG(r16
, PERF_REG_POWERPC_R16
),
37 SMPL_REG(r17
, PERF_REG_POWERPC_R17
),
38 SMPL_REG(r18
, PERF_REG_POWERPC_R18
),
39 SMPL_REG(r19
, PERF_REG_POWERPC_R19
),
40 SMPL_REG(r20
, PERF_REG_POWERPC_R20
),
41 SMPL_REG(r21
, PERF_REG_POWERPC_R21
),
42 SMPL_REG(r22
, PERF_REG_POWERPC_R22
),
43 SMPL_REG(r23
, PERF_REG_POWERPC_R23
),
44 SMPL_REG(r24
, PERF_REG_POWERPC_R24
),
45 SMPL_REG(r25
, PERF_REG_POWERPC_R25
),
46 SMPL_REG(r26
, PERF_REG_POWERPC_R26
),
47 SMPL_REG(r27
, PERF_REG_POWERPC_R27
),
48 SMPL_REG(r28
, PERF_REG_POWERPC_R28
),
49 SMPL_REG(r29
, PERF_REG_POWERPC_R29
),
50 SMPL_REG(r30
, PERF_REG_POWERPC_R30
),
51 SMPL_REG(r31
, PERF_REG_POWERPC_R31
),
52 SMPL_REG(nip
, PERF_REG_POWERPC_NIP
),
53 SMPL_REG(msr
, PERF_REG_POWERPC_MSR
),
54 SMPL_REG(orig_r3
, PERF_REG_POWERPC_ORIG_R3
),
55 SMPL_REG(ctr
, PERF_REG_POWERPC_CTR
),
56 SMPL_REG(link
, PERF_REG_POWERPC_LINK
),
57 SMPL_REG(xer
, PERF_REG_POWERPC_XER
),
58 SMPL_REG(ccr
, PERF_REG_POWERPC_CCR
),
59 SMPL_REG(softe
, PERF_REG_POWERPC_SOFTE
),
60 SMPL_REG(trap
, PERF_REG_POWERPC_TRAP
),
61 SMPL_REG(dar
, PERF_REG_POWERPC_DAR
),
62 SMPL_REG(dsisr
, PERF_REG_POWERPC_DSISR
),
63 SMPL_REG(sier
, PERF_REG_POWERPC_SIER
),
64 SMPL_REG(mmcra
, PERF_REG_POWERPC_MMCRA
),
65 SMPL_REG(mmcr0
, PERF_REG_POWERPC_MMCR0
),
66 SMPL_REG(mmcr1
, PERF_REG_POWERPC_MMCR1
),
67 SMPL_REG(mmcr2
, PERF_REG_POWERPC_MMCR2
),
68 SMPL_REG(mmcr3
, PERF_REG_POWERPC_MMCR3
),
69 SMPL_REG(sier2
, PERF_REG_POWERPC_SIER2
),
70 SMPL_REG(sier3
, PERF_REG_POWERPC_SIER3
),
75 #define SDT_OP_REGEX1 "^(%r)?([1-2]?[0-9]|3[0-1])$"
77 /* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
78 #define SDT_OP_REGEX2 "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$"
80 static regex_t sdt_op_regex1
, sdt_op_regex2
;
82 static int sdt_init_op_regex(void)
84 static int initialized
;
90 ret
= regcomp(&sdt_op_regex1
, SDT_OP_REGEX1
, REG_EXTENDED
);
94 ret
= regcomp(&sdt_op_regex2
, SDT_OP_REGEX2
, REG_EXTENDED
);
102 regfree(&sdt_op_regex1
);
104 pr_debug4("Regex compilation error.\n");
109 * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
110 * Possible variants of OP are:
112 * -------------------------
115 * NUM(%rREG) 48(%r18)
116 * -NUM(%rREG) -48(%r18)
122 * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
123 * and REG form with -mno-regnames. Here REG is general purpose register,
124 * which is in 0 to 31 range.
126 int arch_sdt_arg_parse_op(char *old_op
, char **new_op
)
132 /* Constant argument. Uprobe does not support it */
133 if (old_op
[0] == 'i') {
134 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op
);
138 ret
= sdt_init_op_regex();
142 if (!regexec(&sdt_op_regex1
, old_op
, 3, rm
, 0)) {
143 /* REG or %rREG --> %gprREG */
145 new_len
= 5; /* % g p r NULL */
146 new_len
+= (int)(rm
[2].rm_eo
- rm
[2].rm_so
);
148 *new_op
= zalloc(new_len
);
152 scnprintf(*new_op
, new_len
, "%%gpr%.*s",
153 (int)(rm
[2].rm_eo
- rm
[2].rm_so
), old_op
+ rm
[2].rm_so
);
154 } else if (!regexec(&sdt_op_regex2
, old_op
, 5, rm
, 0)) {
156 * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
159 prefix
= (rm
[1].rm_so
== -1) ? '+' : '-';
161 new_len
= 8; /* +/- ( % g p r ) NULL */
162 new_len
+= (int)(rm
[2].rm_eo
- rm
[2].rm_so
);
163 new_len
+= (int)(rm
[4].rm_eo
- rm
[4].rm_so
);
165 *new_op
= zalloc(new_len
);
169 scnprintf(*new_op
, new_len
, "%c%.*s(%%gpr%.*s)", prefix
,
170 (int)(rm
[2].rm_eo
- rm
[2].rm_so
), old_op
+ rm
[2].rm_so
,
171 (int)(rm
[4].rm_eo
- rm
[4].rm_so
), old_op
+ rm
[4].rm_so
);
173 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op
);
177 return SDT_ARG_VALID
;
180 uint64_t arch__intr_reg_mask(void)
182 struct perf_event_attr attr
= {
183 .type
= PERF_TYPE_HARDWARE
,
184 .config
= PERF_COUNT_HW_CPU_CYCLES
,
185 .sample_type
= PERF_SAMPLE_REGS_INTR
,
192 u64 extended_mask
= 0, mask
= PERF_REGS_MASK
;
195 * Get the PVR value to set the extended
196 * mask specific to platform.
198 version
= (((mfspr(SPRN_PVR
)) >> 16) & 0xFFFF);
199 if (version
== PVR_POWER9
)
200 extended_mask
= PERF_REG_PMU_MASK_300
;
201 else if (version
== PVR_POWER10
)
202 extended_mask
= PERF_REG_PMU_MASK_31
;
206 attr
.sample_regs_intr
= extended_mask
;
207 attr
.sample_period
= 1;
208 event_attr_init(&attr
);
211 * check if the pmu supports perf extended regs, before
212 * returning the register mask to sample.
214 fd
= sys_perf_event_open(&attr
, 0, -1, -1, 0);
217 mask
|= extended_mask
;