~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/arch/powerpc/util/perf_regs.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <errno.h>
  3 #include <string.h>
  4 #include <regex.h>
  5 #include <linux/zalloc.h>
  6 
  7 #include "perf_regs.h"
  8 #include "../../../util/perf_regs.h"
  9 #include "../../../util/debug.h"
 10 #include "../../../util/event.h"
 11 #include "../../../util/header.h"
 12 #include "../../../perf-sys.h"
 13 #include "utils_header.h"
 14 
 15 #include <linux/kernel.h>
 16 
 17 #define PVR_POWER9              0x004E
 18 #define PVR_POWER10             0x0080
 19 
 20 static const struct sample_reg sample_reg_masks[] = {
 21         SMPL_REG(r0, PERF_REG_POWERPC_R0),
 22         SMPL_REG(r1, PERF_REG_POWERPC_R1),
 23         SMPL_REG(r2, PERF_REG_POWERPC_R2),
 24         SMPL_REG(r3, PERF_REG_POWERPC_R3),
 25         SMPL_REG(r4, PERF_REG_POWERPC_R4),
 26         SMPL_REG(r5, PERF_REG_POWERPC_R5),
 27         SMPL_REG(r6, PERF_REG_POWERPC_R6),
 28         SMPL_REG(r7, PERF_REG_POWERPC_R7),
 29         SMPL_REG(r8, PERF_REG_POWERPC_R8),
 30         SMPL_REG(r9, PERF_REG_POWERPC_R9),
 31         SMPL_REG(r10, PERF_REG_POWERPC_R10),
 32         SMPL_REG(r11, PERF_REG_POWERPC_R11),
 33         SMPL_REG(r12, PERF_REG_POWERPC_R12),
 34         SMPL_REG(r13, PERF_REG_POWERPC_R13),
 35         SMPL_REG(r14, PERF_REG_POWERPC_R14),
 36         SMPL_REG(r15, PERF_REG_POWERPC_R15),
 37         SMPL_REG(r16, PERF_REG_POWERPC_R16),
 38         SMPL_REG(r17, PERF_REG_POWERPC_R17),
 39         SMPL_REG(r18, PERF_REG_POWERPC_R18),
 40         SMPL_REG(r19, PERF_REG_POWERPC_R19),
 41         SMPL_REG(r20, PERF_REG_POWERPC_R20),
 42         SMPL_REG(r21, PERF_REG_POWERPC_R21),
 43         SMPL_REG(r22, PERF_REG_POWERPC_R22),
 44         SMPL_REG(r23, PERF_REG_POWERPC_R23),
 45         SMPL_REG(r24, PERF_REG_POWERPC_R24),
 46         SMPL_REG(r25, PERF_REG_POWERPC_R25),
 47         SMPL_REG(r26, PERF_REG_POWERPC_R26),
 48         SMPL_REG(r27, PERF_REG_POWERPC_R27),
 49         SMPL_REG(r28, PERF_REG_POWERPC_R28),
 50         SMPL_REG(r29, PERF_REG_POWERPC_R29),
 51         SMPL_REG(r30, PERF_REG_POWERPC_R30),
 52         SMPL_REG(r31, PERF_REG_POWERPC_R31),
 53         SMPL_REG(nip, PERF_REG_POWERPC_NIP),
 54         SMPL_REG(msr, PERF_REG_POWERPC_MSR),
 55         SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3),
 56         SMPL_REG(ctr, PERF_REG_POWERPC_CTR),
 57         SMPL_REG(link, PERF_REG_POWERPC_LINK),
 58         SMPL_REG(xer, PERF_REG_POWERPC_XER),
 59         SMPL_REG(ccr, PERF_REG_POWERPC_CCR),
 60         SMPL_REG(softe, PERF_REG_POWERPC_SOFTE),
 61         SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
 62         SMPL_REG(dar, PERF_REG_POWERPC_DAR),
 63         SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
 64         SMPL_REG(sier, PERF_REG_POWERPC_SIER),
 65         SMPL_REG(mmcra, PERF_REG_POWERPC_MMCRA),
 66         SMPL_REG(mmcr0, PERF_REG_POWERPC_MMCR0),
 67         SMPL_REG(mmcr1, PERF_REG_POWERPC_MMCR1),
 68         SMPL_REG(mmcr2, PERF_REG_POWERPC_MMCR2),
 69         SMPL_REG(mmcr3, PERF_REG_POWERPC_MMCR3),
 70         SMPL_REG(sier2, PERF_REG_POWERPC_SIER2),
 71         SMPL_REG(sier3, PERF_REG_POWERPC_SIER3),
 72         SMPL_REG(pmc1, PERF_REG_POWERPC_PMC1),
 73         SMPL_REG(pmc2, PERF_REG_POWERPC_PMC2),
 74         SMPL_REG(pmc3, PERF_REG_POWERPC_PMC3),
 75         SMPL_REG(pmc4, PERF_REG_POWERPC_PMC4),
 76         SMPL_REG(pmc5, PERF_REG_POWERPC_PMC5),
 77         SMPL_REG(pmc6, PERF_REG_POWERPC_PMC6),
 78         SMPL_REG(sdar, PERF_REG_POWERPC_SDAR),
 79         SMPL_REG(siar, PERF_REG_POWERPC_SIAR),
 80         SMPL_REG_END
 81 };
 82 
 83 /* REG or %rREG */
 84 #define SDT_OP_REGEX1  "^(%r)?([1-2]?[0-9]|3[0-1])$"
 85 
 86 /* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
 87 #define SDT_OP_REGEX2  "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$"
 88 
 89 static regex_t sdt_op_regex1, sdt_op_regex2;
 90 
 91 static int sdt_init_op_regex(void)
 92 {
 93         static int initialized;
 94         int ret = 0;
 95 
 96         if (initialized)
 97                 return 0;
 98 
 99         ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
100         if (ret)
101                 goto error;
102 
103         ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
104         if (ret)
105                 goto free_regex1;
106 
107         initialized = 1;
108         return 0;
109 
110 free_regex1:
111         regfree(&sdt_op_regex1);
112 error:
113         pr_debug4("Regex compilation error.\n");
114         return ret;
115 }
116 
117 /*
118  * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
119  * Possible variants of OP are:
120  *      Format          Example
121  *      -------------------------
122  *      NUM(REG)        48(18)
123  *      -NUM(REG)       -48(18)
124  *      NUM(%rREG)      48(%r18)
125  *      -NUM(%rREG)     -48(%r18)
126  *      REG             18
127  *      %rREG           %r18
128  *      iNUM            i0
129  *      i-NUM           i-1
130  *
131  * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
132  * and REG form with -mno-regnames. Here REG is general purpose register,
133  * which is in 0 to 31 range.
134  */
135 int arch_sdt_arg_parse_op(char *old_op, char **new_op)
136 {
137         int ret, new_len;
138         regmatch_t rm[5];
139         char prefix;
140 
141         /* Constant argument. Uprobe does not support it */
142         if (old_op[0] == 'i') {
143                 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
144                 return SDT_ARG_SKIP;
145         }
146 
147         ret = sdt_init_op_regex();
148         if (ret < 0)
149                 return ret;
150 
151         if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
152                 /* REG or %rREG --> %gprREG */
153 
154                 new_len = 5;    /* % g p r NULL */
155                 new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
156 
157                 *new_op = zalloc(new_len);
158                 if (!*new_op)
159                         return -ENOMEM;
160 
161                 scnprintf(*new_op, new_len, "%%gpr%.*s",
162                         (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so);
163         } else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
164                 /*
165                  * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
166                  *      +/-NUM(%gprREG)
167                  */
168                 prefix = (rm[1].rm_so == -1) ? '+' : '-';
169 
170                 new_len = 8;    /* +/- ( % g p r ) NULL */
171                 new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
172                 new_len += (int)(rm[4].rm_eo - rm[4].rm_so);
173 
174                 *new_op = zalloc(new_len);
175                 if (!*new_op)
176                         return -ENOMEM;
177 
178                 scnprintf(*new_op, new_len, "%c%.*s(%%gpr%.*s)", prefix,
179                         (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
180                         (int)(rm[4].rm_eo - rm[4].rm_so), old_op + rm[4].rm_so);
181         } else {
182                 pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
183                 return SDT_ARG_SKIP;
184         }
185 
186         return SDT_ARG_VALID;
187 }
188 
189 uint64_t arch__intr_reg_mask(void)
190 {
191         struct perf_event_attr attr = {
192                 .type                   = PERF_TYPE_HARDWARE,
193                 .config                 = PERF_COUNT_HW_CPU_CYCLES,
194                 .sample_type            = PERF_SAMPLE_REGS_INTR,
195                 .precise_ip             = 1,
196                 .disabled               = 1,
197                 .exclude_kernel         = 1,
198         };
199         int fd;
200         u32 version;
201         u64 extended_mask = 0, mask = PERF_REGS_MASK;
202 
203         /*
204          * Get the PVR value to set the extended
205          * mask specific to platform.
206          */
207         version = (((mfspr(SPRN_PVR)) >>  16) & 0xFFFF);
208         if (version == PVR_POWER9)
209                 extended_mask = PERF_REG_PMU_MASK_300;
210         else if (version == PVR_POWER10)
211                 extended_mask = PERF_REG_PMU_MASK_31;
212         else
213                 return mask;
214 
215         attr.sample_regs_intr = extended_mask;
216         attr.sample_period = 1;
217         event_attr_init(&attr);
218 
219         /*
220          * check if the pmu supports perf extended regs, before
221          * returning the register mask to sample.
222          */
223         fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
224         if (fd != -1) {
225                 close(fd);
226                 mask |= extended_mask;
227         }
228         return mask;
229 }
230 
231 uint64_t arch__user_reg_mask(void)
232 {
233         return PERF_REGS_MASK;
234 }
235 
236 const struct sample_reg *arch__sample_reg_masks(void)
237 {
238         return sample_reg_masks;
239 }
240 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php