Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <errno.h>
0003 #include <string.h>
0004 #include <regex.h>
0005 #include <linux/zalloc.h>
0006 
0007 #include "../../../util/perf_regs.h"
0008 #include "../../../util/debug.h"
0009 #include "../../../util/event.h"
0010 #include "../../../util/header.h"
0011 #include "../../../perf-sys.h"
0012 #include "utils_header.h"
0013 
0014 #include <linux/kernel.h>
0015 
0016 #define PVR_POWER9      0x004E
0017 #define PVR_POWER10     0x0080
0018 
0019 const struct sample_reg sample_reg_masks[] = {
0020     SMPL_REG(r0, PERF_REG_POWERPC_R0),
0021     SMPL_REG(r1, PERF_REG_POWERPC_R1),
0022     SMPL_REG(r2, PERF_REG_POWERPC_R2),
0023     SMPL_REG(r3, PERF_REG_POWERPC_R3),
0024     SMPL_REG(r4, PERF_REG_POWERPC_R4),
0025     SMPL_REG(r5, PERF_REG_POWERPC_R5),
0026     SMPL_REG(r6, PERF_REG_POWERPC_R6),
0027     SMPL_REG(r7, PERF_REG_POWERPC_R7),
0028     SMPL_REG(r8, PERF_REG_POWERPC_R8),
0029     SMPL_REG(r9, PERF_REG_POWERPC_R9),
0030     SMPL_REG(r10, PERF_REG_POWERPC_R10),
0031     SMPL_REG(r11, PERF_REG_POWERPC_R11),
0032     SMPL_REG(r12, PERF_REG_POWERPC_R12),
0033     SMPL_REG(r13, PERF_REG_POWERPC_R13),
0034     SMPL_REG(r14, PERF_REG_POWERPC_R14),
0035     SMPL_REG(r15, PERF_REG_POWERPC_R15),
0036     SMPL_REG(r16, PERF_REG_POWERPC_R16),
0037     SMPL_REG(r17, PERF_REG_POWERPC_R17),
0038     SMPL_REG(r18, PERF_REG_POWERPC_R18),
0039     SMPL_REG(r19, PERF_REG_POWERPC_R19),
0040     SMPL_REG(r20, PERF_REG_POWERPC_R20),
0041     SMPL_REG(r21, PERF_REG_POWERPC_R21),
0042     SMPL_REG(r22, PERF_REG_POWERPC_R22),
0043     SMPL_REG(r23, PERF_REG_POWERPC_R23),
0044     SMPL_REG(r24, PERF_REG_POWERPC_R24),
0045     SMPL_REG(r25, PERF_REG_POWERPC_R25),
0046     SMPL_REG(r26, PERF_REG_POWERPC_R26),
0047     SMPL_REG(r27, PERF_REG_POWERPC_R27),
0048     SMPL_REG(r28, PERF_REG_POWERPC_R28),
0049     SMPL_REG(r29, PERF_REG_POWERPC_R29),
0050     SMPL_REG(r30, PERF_REG_POWERPC_R30),
0051     SMPL_REG(r31, PERF_REG_POWERPC_R31),
0052     SMPL_REG(nip, PERF_REG_POWERPC_NIP),
0053     SMPL_REG(msr, PERF_REG_POWERPC_MSR),
0054     SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3),
0055     SMPL_REG(ctr, PERF_REG_POWERPC_CTR),
0056     SMPL_REG(link, PERF_REG_POWERPC_LINK),
0057     SMPL_REG(xer, PERF_REG_POWERPC_XER),
0058     SMPL_REG(ccr, PERF_REG_POWERPC_CCR),
0059     SMPL_REG(softe, PERF_REG_POWERPC_SOFTE),
0060     SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
0061     SMPL_REG(dar, PERF_REG_POWERPC_DAR),
0062     SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
0063     SMPL_REG(sier, PERF_REG_POWERPC_SIER),
0064     SMPL_REG(mmcra, PERF_REG_POWERPC_MMCRA),
0065     SMPL_REG(mmcr0, PERF_REG_POWERPC_MMCR0),
0066     SMPL_REG(mmcr1, PERF_REG_POWERPC_MMCR1),
0067     SMPL_REG(mmcr2, PERF_REG_POWERPC_MMCR2),
0068     SMPL_REG(mmcr3, PERF_REG_POWERPC_MMCR3),
0069     SMPL_REG(sier2, PERF_REG_POWERPC_SIER2),
0070     SMPL_REG(sier3, PERF_REG_POWERPC_SIER3),
0071     SMPL_REG(pmc1, PERF_REG_POWERPC_PMC1),
0072     SMPL_REG(pmc2, PERF_REG_POWERPC_PMC2),
0073     SMPL_REG(pmc3, PERF_REG_POWERPC_PMC3),
0074     SMPL_REG(pmc4, PERF_REG_POWERPC_PMC4),
0075     SMPL_REG(pmc5, PERF_REG_POWERPC_PMC5),
0076     SMPL_REG(pmc6, PERF_REG_POWERPC_PMC6),
0077     SMPL_REG(sdar, PERF_REG_POWERPC_SDAR),
0078     SMPL_REG(siar, PERF_REG_POWERPC_SIAR),
0079     SMPL_REG_END
0080 };
0081 
0082 /* REG or %rREG */
0083 #define SDT_OP_REGEX1  "^(%r)?([1-2]?[0-9]|3[0-1])$"
0084 
0085 /* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
0086 #define SDT_OP_REGEX2  "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$"
0087 
0088 static regex_t sdt_op_regex1, sdt_op_regex2;
0089 
0090 static int sdt_init_op_regex(void)
0091 {
0092     static int initialized;
0093     int ret = 0;
0094 
0095     if (initialized)
0096         return 0;
0097 
0098     ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
0099     if (ret)
0100         goto error;
0101 
0102     ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
0103     if (ret)
0104         goto free_regex1;
0105 
0106     initialized = 1;
0107     return 0;
0108 
0109 free_regex1:
0110     regfree(&sdt_op_regex1);
0111 error:
0112     pr_debug4("Regex compilation error.\n");
0113     return ret;
0114 }
0115 
0116 /*
0117  * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
0118  * Possible variants of OP are:
0119  *  Format      Example
0120  *  -------------------------
0121  *  NUM(REG)    48(18)
0122  *  -NUM(REG)   -48(18)
0123  *  NUM(%rREG)  48(%r18)
0124  *  -NUM(%rREG) -48(%r18)
0125  *  REG     18
0126  *  %rREG       %r18
0127  *  iNUM        i0
0128  *  i-NUM       i-1
0129  *
0130  * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
0131  * and REG form with -mno-regnames. Here REG is general purpose register,
0132  * which is in 0 to 31 range.
0133  */
0134 int arch_sdt_arg_parse_op(char *old_op, char **new_op)
0135 {
0136     int ret, new_len;
0137     regmatch_t rm[5];
0138     char prefix;
0139 
0140     /* Constant argument. Uprobe does not support it */
0141     if (old_op[0] == 'i') {
0142         pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
0143         return SDT_ARG_SKIP;
0144     }
0145 
0146     ret = sdt_init_op_regex();
0147     if (ret < 0)
0148         return ret;
0149 
0150     if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
0151         /* REG or %rREG --> %gprREG */
0152 
0153         new_len = 5;    /* % g p r NULL */
0154         new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
0155 
0156         *new_op = zalloc(new_len);
0157         if (!*new_op)
0158             return -ENOMEM;
0159 
0160         scnprintf(*new_op, new_len, "%%gpr%.*s",
0161             (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so);
0162     } else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
0163         /*
0164          * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
0165          *  +/-NUM(%gprREG)
0166          */
0167         prefix = (rm[1].rm_so == -1) ? '+' : '-';
0168 
0169         new_len = 8;    /* +/- ( % g p r ) NULL */
0170         new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
0171         new_len += (int)(rm[4].rm_eo - rm[4].rm_so);
0172 
0173         *new_op = zalloc(new_len);
0174         if (!*new_op)
0175             return -ENOMEM;
0176 
0177         scnprintf(*new_op, new_len, "%c%.*s(%%gpr%.*s)", prefix,
0178             (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
0179             (int)(rm[4].rm_eo - rm[4].rm_so), old_op + rm[4].rm_so);
0180     } else {
0181         pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
0182         return SDT_ARG_SKIP;
0183     }
0184 
0185     return SDT_ARG_VALID;
0186 }
0187 
0188 uint64_t arch__intr_reg_mask(void)
0189 {
0190     struct perf_event_attr attr = {
0191         .type                   = PERF_TYPE_HARDWARE,
0192         .config                 = PERF_COUNT_HW_CPU_CYCLES,
0193         .sample_type            = PERF_SAMPLE_REGS_INTR,
0194         .precise_ip             = 1,
0195         .disabled               = 1,
0196         .exclude_kernel         = 1,
0197     };
0198     int fd;
0199     u32 version;
0200     u64 extended_mask = 0, mask = PERF_REGS_MASK;
0201 
0202     /*
0203      * Get the PVR value to set the extended
0204      * mask specific to platform.
0205      */
0206     version = (((mfspr(SPRN_PVR)) >>  16) & 0xFFFF);
0207     if (version == PVR_POWER9)
0208         extended_mask = PERF_REG_PMU_MASK_300;
0209     else if (version == PVR_POWER10)
0210         extended_mask = PERF_REG_PMU_MASK_31;
0211     else
0212         return mask;
0213 
0214     attr.sample_regs_intr = extended_mask;
0215     attr.sample_period = 1;
0216     event_attr_init(&attr);
0217 
0218     /*
0219      * check if the pmu supports perf extended regs, before
0220      * returning the register mask to sample.
0221      */
0222     fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
0223     if (fd != -1) {
0224         close(fd);
0225         mask |= extended_mask;
0226     }
0227     return mask;
0228 }