1 // SPDX-License-Identifier: GPL-2.0
5 #include <linux/zalloc.h>
7 #include "../../util/perf_regs.h"
8 #include "../../util/debug.h"
10 #include <linux/kernel.h>
12 const struct sample_reg sample_reg_masks
[] = {
13 SMPL_REG(r0
, PERF_REG_POWERPC_R0
),
14 SMPL_REG(r1
, PERF_REG_POWERPC_R1
),
15 SMPL_REG(r2
, PERF_REG_POWERPC_R2
),
16 SMPL_REG(r3
, PERF_REG_POWERPC_R3
),
17 SMPL_REG(r4
, PERF_REG_POWERPC_R4
),
18 SMPL_REG(r5
, PERF_REG_POWERPC_R5
),
19 SMPL_REG(r6
, PERF_REG_POWERPC_R6
),
20 SMPL_REG(r7
, PERF_REG_POWERPC_R7
),
21 SMPL_REG(r8
, PERF_REG_POWERPC_R8
),
22 SMPL_REG(r9
, PERF_REG_POWERPC_R9
),
23 SMPL_REG(r10
, PERF_REG_POWERPC_R10
),
24 SMPL_REG(r11
, PERF_REG_POWERPC_R11
),
25 SMPL_REG(r12
, PERF_REG_POWERPC_R12
),
26 SMPL_REG(r13
, PERF_REG_POWERPC_R13
),
27 SMPL_REG(r14
, PERF_REG_POWERPC_R14
),
28 SMPL_REG(r15
, PERF_REG_POWERPC_R15
),
29 SMPL_REG(r16
, PERF_REG_POWERPC_R16
),
30 SMPL_REG(r17
, PERF_REG_POWERPC_R17
),
31 SMPL_REG(r18
, PERF_REG_POWERPC_R18
),
32 SMPL_REG(r19
, PERF_REG_POWERPC_R19
),
33 SMPL_REG(r20
, PERF_REG_POWERPC_R20
),
34 SMPL_REG(r21
, PERF_REG_POWERPC_R21
),
35 SMPL_REG(r22
, PERF_REG_POWERPC_R22
),
36 SMPL_REG(r23
, PERF_REG_POWERPC_R23
),
37 SMPL_REG(r24
, PERF_REG_POWERPC_R24
),
38 SMPL_REG(r25
, PERF_REG_POWERPC_R25
),
39 SMPL_REG(r26
, PERF_REG_POWERPC_R26
),
40 SMPL_REG(r27
, PERF_REG_POWERPC_R27
),
41 SMPL_REG(r28
, PERF_REG_POWERPC_R28
),
42 SMPL_REG(r29
, PERF_REG_POWERPC_R29
),
43 SMPL_REG(r30
, PERF_REG_POWERPC_R30
),
44 SMPL_REG(r31
, PERF_REG_POWERPC_R31
),
45 SMPL_REG(nip
, PERF_REG_POWERPC_NIP
),
46 SMPL_REG(msr
, PERF_REG_POWERPC_MSR
),
47 SMPL_REG(orig_r3
, PERF_REG_POWERPC_ORIG_R3
),
48 SMPL_REG(ctr
, PERF_REG_POWERPC_CTR
),
49 SMPL_REG(link
, PERF_REG_POWERPC_LINK
),
50 SMPL_REG(xer
, PERF_REG_POWERPC_XER
),
51 SMPL_REG(ccr
, PERF_REG_POWERPC_CCR
),
52 SMPL_REG(softe
, PERF_REG_POWERPC_SOFTE
),
53 SMPL_REG(trap
, PERF_REG_POWERPC_TRAP
),
54 SMPL_REG(dar
, PERF_REG_POWERPC_DAR
),
55 SMPL_REG(dsisr
, PERF_REG_POWERPC_DSISR
),
56 SMPL_REG(sier
, PERF_REG_POWERPC_SIER
),
57 SMPL_REG(mmcra
, PERF_REG_POWERPC_MMCRA
),
62 #define SDT_OP_REGEX1 "^(%r)?([1-2]?[0-9]|3[0-1])$"
64 /* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
65 #define SDT_OP_REGEX2 "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$"
67 static regex_t sdt_op_regex1
, sdt_op_regex2
;
69 static int sdt_init_op_regex(void)
71 static int initialized
;
77 ret
= regcomp(&sdt_op_regex1
, SDT_OP_REGEX1
, REG_EXTENDED
);
81 ret
= regcomp(&sdt_op_regex2
, SDT_OP_REGEX2
, REG_EXTENDED
);
89 regfree(&sdt_op_regex1
);
91 pr_debug4("Regex compilation error.\n");
96 * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
97 * Possible variants of OP are:
99 * -------------------------
102 * NUM(%rREG) 48(%r18)
103 * -NUM(%rREG) -48(%r18)
109 * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
110 * and REG form with -mno-regnames. Here REG is general purpose register,
111 * which is in 0 to 31 range.
113 int arch_sdt_arg_parse_op(char *old_op
, char **new_op
)
119 /* Constant argument. Uprobe does not support it */
120 if (old_op
[0] == 'i') {
121 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op
);
125 ret
= sdt_init_op_regex();
129 if (!regexec(&sdt_op_regex1
, old_op
, 3, rm
, 0)) {
130 /* REG or %rREG --> %gprREG */
132 new_len
= 5; /* % g p r NULL */
133 new_len
+= (int)(rm
[2].rm_eo
- rm
[2].rm_so
);
135 *new_op
= zalloc(new_len
);
139 scnprintf(*new_op
, new_len
, "%%gpr%.*s",
140 (int)(rm
[2].rm_eo
- rm
[2].rm_so
), old_op
+ rm
[2].rm_so
);
141 } else if (!regexec(&sdt_op_regex2
, old_op
, 5, rm
, 0)) {
143 * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
146 prefix
= (rm
[1].rm_so
== -1) ? '+' : '-';
148 new_len
= 8; /* +/- ( % g p r ) NULL */
149 new_len
+= (int)(rm
[2].rm_eo
- rm
[2].rm_so
);
150 new_len
+= (int)(rm
[4].rm_eo
- rm
[4].rm_so
);
152 *new_op
= zalloc(new_len
);
156 scnprintf(*new_op
, new_len
, "%c%.*s(%%gpr%.*s)", prefix
,
157 (int)(rm
[2].rm_eo
- rm
[2].rm_so
), old_op
+ rm
[2].rm_so
,
158 (int)(rm
[4].rm_eo
- rm
[4].rm_so
), old_op
+ rm
[4].rm_so
);
160 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op
);
164 return SDT_ARG_VALID
;