0001
0002 #include <errno.h>
0003 #include <string.h>
0004 #include "perf_regs.h"
0005 #include "event.h"
0006
0007 int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused,
0008 char **new_op __maybe_unused)
0009 {
0010 return SDT_ARG_SKIP;
0011 }
0012
0013 uint64_t __weak arch__intr_reg_mask(void)
0014 {
0015 return PERF_REGS_MASK;
0016 }
0017
0018 uint64_t __weak arch__user_reg_mask(void)
0019 {
0020 return PERF_REGS_MASK;
0021 }
0022
0023 #ifdef HAVE_PERF_REGS_SUPPORT
0024
0025 #define perf_event_arm_regs perf_event_arm64_regs
0026 #include "../../arch/arm64/include/uapi/asm/perf_regs.h"
0027 #undef perf_event_arm_regs
0028
0029 #include "../../arch/arm/include/uapi/asm/perf_regs.h"
0030 #include "../../arch/csky/include/uapi/asm/perf_regs.h"
0031 #include "../../arch/mips/include/uapi/asm/perf_regs.h"
0032 #include "../../arch/powerpc/include/uapi/asm/perf_regs.h"
0033 #include "../../arch/riscv/include/uapi/asm/perf_regs.h"
0034 #include "../../arch/s390/include/uapi/asm/perf_regs.h"
0035 #include "../../arch/x86/include/uapi/asm/perf_regs.h"
0036
0037 static const char *__perf_reg_name_arm64(int id)
0038 {
0039 switch (id) {
0040 case PERF_REG_ARM64_X0:
0041 return "x0";
0042 case PERF_REG_ARM64_X1:
0043 return "x1";
0044 case PERF_REG_ARM64_X2:
0045 return "x2";
0046 case PERF_REG_ARM64_X3:
0047 return "x3";
0048 case PERF_REG_ARM64_X4:
0049 return "x4";
0050 case PERF_REG_ARM64_X5:
0051 return "x5";
0052 case PERF_REG_ARM64_X6:
0053 return "x6";
0054 case PERF_REG_ARM64_X7:
0055 return "x7";
0056 case PERF_REG_ARM64_X8:
0057 return "x8";
0058 case PERF_REG_ARM64_X9:
0059 return "x9";
0060 case PERF_REG_ARM64_X10:
0061 return "x10";
0062 case PERF_REG_ARM64_X11:
0063 return "x11";
0064 case PERF_REG_ARM64_X12:
0065 return "x12";
0066 case PERF_REG_ARM64_X13:
0067 return "x13";
0068 case PERF_REG_ARM64_X14:
0069 return "x14";
0070 case PERF_REG_ARM64_X15:
0071 return "x15";
0072 case PERF_REG_ARM64_X16:
0073 return "x16";
0074 case PERF_REG_ARM64_X17:
0075 return "x17";
0076 case PERF_REG_ARM64_X18:
0077 return "x18";
0078 case PERF_REG_ARM64_X19:
0079 return "x19";
0080 case PERF_REG_ARM64_X20:
0081 return "x20";
0082 case PERF_REG_ARM64_X21:
0083 return "x21";
0084 case PERF_REG_ARM64_X22:
0085 return "x22";
0086 case PERF_REG_ARM64_X23:
0087 return "x23";
0088 case PERF_REG_ARM64_X24:
0089 return "x24";
0090 case PERF_REG_ARM64_X25:
0091 return "x25";
0092 case PERF_REG_ARM64_X26:
0093 return "x26";
0094 case PERF_REG_ARM64_X27:
0095 return "x27";
0096 case PERF_REG_ARM64_X28:
0097 return "x28";
0098 case PERF_REG_ARM64_X29:
0099 return "x29";
0100 case PERF_REG_ARM64_SP:
0101 return "sp";
0102 case PERF_REG_ARM64_LR:
0103 return "lr";
0104 case PERF_REG_ARM64_PC:
0105 return "pc";
0106 case PERF_REG_ARM64_VG:
0107 return "vg";
0108 default:
0109 return NULL;
0110 }
0111
0112 return NULL;
0113 }
0114
0115 static const char *__perf_reg_name_arm(int id)
0116 {
0117 switch (id) {
0118 case PERF_REG_ARM_R0:
0119 return "r0";
0120 case PERF_REG_ARM_R1:
0121 return "r1";
0122 case PERF_REG_ARM_R2:
0123 return "r2";
0124 case PERF_REG_ARM_R3:
0125 return "r3";
0126 case PERF_REG_ARM_R4:
0127 return "r4";
0128 case PERF_REG_ARM_R5:
0129 return "r5";
0130 case PERF_REG_ARM_R6:
0131 return "r6";
0132 case PERF_REG_ARM_R7:
0133 return "r7";
0134 case PERF_REG_ARM_R8:
0135 return "r8";
0136 case PERF_REG_ARM_R9:
0137 return "r9";
0138 case PERF_REG_ARM_R10:
0139 return "r10";
0140 case PERF_REG_ARM_FP:
0141 return "fp";
0142 case PERF_REG_ARM_IP:
0143 return "ip";
0144 case PERF_REG_ARM_SP:
0145 return "sp";
0146 case PERF_REG_ARM_LR:
0147 return "lr";
0148 case PERF_REG_ARM_PC:
0149 return "pc";
0150 default:
0151 return NULL;
0152 }
0153
0154 return NULL;
0155 }
0156
0157 static const char *__perf_reg_name_csky(int id)
0158 {
0159 switch (id) {
0160 case PERF_REG_CSKY_A0:
0161 return "a0";
0162 case PERF_REG_CSKY_A1:
0163 return "a1";
0164 case PERF_REG_CSKY_A2:
0165 return "a2";
0166 case PERF_REG_CSKY_A3:
0167 return "a3";
0168 case PERF_REG_CSKY_REGS0:
0169 return "regs0";
0170 case PERF_REG_CSKY_REGS1:
0171 return "regs1";
0172 case PERF_REG_CSKY_REGS2:
0173 return "regs2";
0174 case PERF_REG_CSKY_REGS3:
0175 return "regs3";
0176 case PERF_REG_CSKY_REGS4:
0177 return "regs4";
0178 case PERF_REG_CSKY_REGS5:
0179 return "regs5";
0180 case PERF_REG_CSKY_REGS6:
0181 return "regs6";
0182 case PERF_REG_CSKY_REGS7:
0183 return "regs7";
0184 case PERF_REG_CSKY_REGS8:
0185 return "regs8";
0186 case PERF_REG_CSKY_REGS9:
0187 return "regs9";
0188 case PERF_REG_CSKY_SP:
0189 return "sp";
0190 case PERF_REG_CSKY_LR:
0191 return "lr";
0192 case PERF_REG_CSKY_PC:
0193 return "pc";
0194 #if defined(__CSKYABIV2__)
0195 case PERF_REG_CSKY_EXREGS0:
0196 return "exregs0";
0197 case PERF_REG_CSKY_EXREGS1:
0198 return "exregs1";
0199 case PERF_REG_CSKY_EXREGS2:
0200 return "exregs2";
0201 case PERF_REG_CSKY_EXREGS3:
0202 return "exregs3";
0203 case PERF_REG_CSKY_EXREGS4:
0204 return "exregs4";
0205 case PERF_REG_CSKY_EXREGS5:
0206 return "exregs5";
0207 case PERF_REG_CSKY_EXREGS6:
0208 return "exregs6";
0209 case PERF_REG_CSKY_EXREGS7:
0210 return "exregs7";
0211 case PERF_REG_CSKY_EXREGS8:
0212 return "exregs8";
0213 case PERF_REG_CSKY_EXREGS9:
0214 return "exregs9";
0215 case PERF_REG_CSKY_EXREGS10:
0216 return "exregs10";
0217 case PERF_REG_CSKY_EXREGS11:
0218 return "exregs11";
0219 case PERF_REG_CSKY_EXREGS12:
0220 return "exregs12";
0221 case PERF_REG_CSKY_EXREGS13:
0222 return "exregs13";
0223 case PERF_REG_CSKY_EXREGS14:
0224 return "exregs14";
0225 case PERF_REG_CSKY_TLS:
0226 return "tls";
0227 case PERF_REG_CSKY_HI:
0228 return "hi";
0229 case PERF_REG_CSKY_LO:
0230 return "lo";
0231 #endif
0232 default:
0233 return NULL;
0234 }
0235
0236 return NULL;
0237 }
0238
0239 static const char *__perf_reg_name_mips(int id)
0240 {
0241 switch (id) {
0242 case PERF_REG_MIPS_PC:
0243 return "PC";
0244 case PERF_REG_MIPS_R1:
0245 return "$1";
0246 case PERF_REG_MIPS_R2:
0247 return "$2";
0248 case PERF_REG_MIPS_R3:
0249 return "$3";
0250 case PERF_REG_MIPS_R4:
0251 return "$4";
0252 case PERF_REG_MIPS_R5:
0253 return "$5";
0254 case PERF_REG_MIPS_R6:
0255 return "$6";
0256 case PERF_REG_MIPS_R7:
0257 return "$7";
0258 case PERF_REG_MIPS_R8:
0259 return "$8";
0260 case PERF_REG_MIPS_R9:
0261 return "$9";
0262 case PERF_REG_MIPS_R10:
0263 return "$10";
0264 case PERF_REG_MIPS_R11:
0265 return "$11";
0266 case PERF_REG_MIPS_R12:
0267 return "$12";
0268 case PERF_REG_MIPS_R13:
0269 return "$13";
0270 case PERF_REG_MIPS_R14:
0271 return "$14";
0272 case PERF_REG_MIPS_R15:
0273 return "$15";
0274 case PERF_REG_MIPS_R16:
0275 return "$16";
0276 case PERF_REG_MIPS_R17:
0277 return "$17";
0278 case PERF_REG_MIPS_R18:
0279 return "$18";
0280 case PERF_REG_MIPS_R19:
0281 return "$19";
0282 case PERF_REG_MIPS_R20:
0283 return "$20";
0284 case PERF_REG_MIPS_R21:
0285 return "$21";
0286 case PERF_REG_MIPS_R22:
0287 return "$22";
0288 case PERF_REG_MIPS_R23:
0289 return "$23";
0290 case PERF_REG_MIPS_R24:
0291 return "$24";
0292 case PERF_REG_MIPS_R25:
0293 return "$25";
0294 case PERF_REG_MIPS_R28:
0295 return "$28";
0296 case PERF_REG_MIPS_R29:
0297 return "$29";
0298 case PERF_REG_MIPS_R30:
0299 return "$30";
0300 case PERF_REG_MIPS_R31:
0301 return "$31";
0302 default:
0303 break;
0304 }
0305 return NULL;
0306 }
0307
0308 static const char *__perf_reg_name_powerpc(int id)
0309 {
0310 switch (id) {
0311 case PERF_REG_POWERPC_R0:
0312 return "r0";
0313 case PERF_REG_POWERPC_R1:
0314 return "r1";
0315 case PERF_REG_POWERPC_R2:
0316 return "r2";
0317 case PERF_REG_POWERPC_R3:
0318 return "r3";
0319 case PERF_REG_POWERPC_R4:
0320 return "r4";
0321 case PERF_REG_POWERPC_R5:
0322 return "r5";
0323 case PERF_REG_POWERPC_R6:
0324 return "r6";
0325 case PERF_REG_POWERPC_R7:
0326 return "r7";
0327 case PERF_REG_POWERPC_R8:
0328 return "r8";
0329 case PERF_REG_POWERPC_R9:
0330 return "r9";
0331 case PERF_REG_POWERPC_R10:
0332 return "r10";
0333 case PERF_REG_POWERPC_R11:
0334 return "r11";
0335 case PERF_REG_POWERPC_R12:
0336 return "r12";
0337 case PERF_REG_POWERPC_R13:
0338 return "r13";
0339 case PERF_REG_POWERPC_R14:
0340 return "r14";
0341 case PERF_REG_POWERPC_R15:
0342 return "r15";
0343 case PERF_REG_POWERPC_R16:
0344 return "r16";
0345 case PERF_REG_POWERPC_R17:
0346 return "r17";
0347 case PERF_REG_POWERPC_R18:
0348 return "r18";
0349 case PERF_REG_POWERPC_R19:
0350 return "r19";
0351 case PERF_REG_POWERPC_R20:
0352 return "r20";
0353 case PERF_REG_POWERPC_R21:
0354 return "r21";
0355 case PERF_REG_POWERPC_R22:
0356 return "r22";
0357 case PERF_REG_POWERPC_R23:
0358 return "r23";
0359 case PERF_REG_POWERPC_R24:
0360 return "r24";
0361 case PERF_REG_POWERPC_R25:
0362 return "r25";
0363 case PERF_REG_POWERPC_R26:
0364 return "r26";
0365 case PERF_REG_POWERPC_R27:
0366 return "r27";
0367 case PERF_REG_POWERPC_R28:
0368 return "r28";
0369 case PERF_REG_POWERPC_R29:
0370 return "r29";
0371 case PERF_REG_POWERPC_R30:
0372 return "r30";
0373 case PERF_REG_POWERPC_R31:
0374 return "r31";
0375 case PERF_REG_POWERPC_NIP:
0376 return "nip";
0377 case PERF_REG_POWERPC_MSR:
0378 return "msr";
0379 case PERF_REG_POWERPC_ORIG_R3:
0380 return "orig_r3";
0381 case PERF_REG_POWERPC_CTR:
0382 return "ctr";
0383 case PERF_REG_POWERPC_LINK:
0384 return "link";
0385 case PERF_REG_POWERPC_XER:
0386 return "xer";
0387 case PERF_REG_POWERPC_CCR:
0388 return "ccr";
0389 case PERF_REG_POWERPC_SOFTE:
0390 return "softe";
0391 case PERF_REG_POWERPC_TRAP:
0392 return "trap";
0393 case PERF_REG_POWERPC_DAR:
0394 return "dar";
0395 case PERF_REG_POWERPC_DSISR:
0396 return "dsisr";
0397 case PERF_REG_POWERPC_SIER:
0398 return "sier";
0399 case PERF_REG_POWERPC_MMCRA:
0400 return "mmcra";
0401 case PERF_REG_POWERPC_MMCR0:
0402 return "mmcr0";
0403 case PERF_REG_POWERPC_MMCR1:
0404 return "mmcr1";
0405 case PERF_REG_POWERPC_MMCR2:
0406 return "mmcr2";
0407 case PERF_REG_POWERPC_MMCR3:
0408 return "mmcr3";
0409 case PERF_REG_POWERPC_SIER2:
0410 return "sier2";
0411 case PERF_REG_POWERPC_SIER3:
0412 return "sier3";
0413 case PERF_REG_POWERPC_PMC1:
0414 return "pmc1";
0415 case PERF_REG_POWERPC_PMC2:
0416 return "pmc2";
0417 case PERF_REG_POWERPC_PMC3:
0418 return "pmc3";
0419 case PERF_REG_POWERPC_PMC4:
0420 return "pmc4";
0421 case PERF_REG_POWERPC_PMC5:
0422 return "pmc5";
0423 case PERF_REG_POWERPC_PMC6:
0424 return "pmc6";
0425 case PERF_REG_POWERPC_SDAR:
0426 return "sdar";
0427 case PERF_REG_POWERPC_SIAR:
0428 return "siar";
0429 default:
0430 break;
0431 }
0432 return NULL;
0433 }
0434
0435 static const char *__perf_reg_name_riscv(int id)
0436 {
0437 switch (id) {
0438 case PERF_REG_RISCV_PC:
0439 return "pc";
0440 case PERF_REG_RISCV_RA:
0441 return "ra";
0442 case PERF_REG_RISCV_SP:
0443 return "sp";
0444 case PERF_REG_RISCV_GP:
0445 return "gp";
0446 case PERF_REG_RISCV_TP:
0447 return "tp";
0448 case PERF_REG_RISCV_T0:
0449 return "t0";
0450 case PERF_REG_RISCV_T1:
0451 return "t1";
0452 case PERF_REG_RISCV_T2:
0453 return "t2";
0454 case PERF_REG_RISCV_S0:
0455 return "s0";
0456 case PERF_REG_RISCV_S1:
0457 return "s1";
0458 case PERF_REG_RISCV_A0:
0459 return "a0";
0460 case PERF_REG_RISCV_A1:
0461 return "a1";
0462 case PERF_REG_RISCV_A2:
0463 return "a2";
0464 case PERF_REG_RISCV_A3:
0465 return "a3";
0466 case PERF_REG_RISCV_A4:
0467 return "a4";
0468 case PERF_REG_RISCV_A5:
0469 return "a5";
0470 case PERF_REG_RISCV_A6:
0471 return "a6";
0472 case PERF_REG_RISCV_A7:
0473 return "a7";
0474 case PERF_REG_RISCV_S2:
0475 return "s2";
0476 case PERF_REG_RISCV_S3:
0477 return "s3";
0478 case PERF_REG_RISCV_S4:
0479 return "s4";
0480 case PERF_REG_RISCV_S5:
0481 return "s5";
0482 case PERF_REG_RISCV_S6:
0483 return "s6";
0484 case PERF_REG_RISCV_S7:
0485 return "s7";
0486 case PERF_REG_RISCV_S8:
0487 return "s8";
0488 case PERF_REG_RISCV_S9:
0489 return "s9";
0490 case PERF_REG_RISCV_S10:
0491 return "s10";
0492 case PERF_REG_RISCV_S11:
0493 return "s11";
0494 case PERF_REG_RISCV_T3:
0495 return "t3";
0496 case PERF_REG_RISCV_T4:
0497 return "t4";
0498 case PERF_REG_RISCV_T5:
0499 return "t5";
0500 case PERF_REG_RISCV_T6:
0501 return "t6";
0502 default:
0503 return NULL;
0504 }
0505
0506 return NULL;
0507 }
0508
0509 static const char *__perf_reg_name_s390(int id)
0510 {
0511 switch (id) {
0512 case PERF_REG_S390_R0:
0513 return "R0";
0514 case PERF_REG_S390_R1:
0515 return "R1";
0516 case PERF_REG_S390_R2:
0517 return "R2";
0518 case PERF_REG_S390_R3:
0519 return "R3";
0520 case PERF_REG_S390_R4:
0521 return "R4";
0522 case PERF_REG_S390_R5:
0523 return "R5";
0524 case PERF_REG_S390_R6:
0525 return "R6";
0526 case PERF_REG_S390_R7:
0527 return "R7";
0528 case PERF_REG_S390_R8:
0529 return "R8";
0530 case PERF_REG_S390_R9:
0531 return "R9";
0532 case PERF_REG_S390_R10:
0533 return "R10";
0534 case PERF_REG_S390_R11:
0535 return "R11";
0536 case PERF_REG_S390_R12:
0537 return "R12";
0538 case PERF_REG_S390_R13:
0539 return "R13";
0540 case PERF_REG_S390_R14:
0541 return "R14";
0542 case PERF_REG_S390_R15:
0543 return "R15";
0544 case PERF_REG_S390_FP0:
0545 return "FP0";
0546 case PERF_REG_S390_FP1:
0547 return "FP1";
0548 case PERF_REG_S390_FP2:
0549 return "FP2";
0550 case PERF_REG_S390_FP3:
0551 return "FP3";
0552 case PERF_REG_S390_FP4:
0553 return "FP4";
0554 case PERF_REG_S390_FP5:
0555 return "FP5";
0556 case PERF_REG_S390_FP6:
0557 return "FP6";
0558 case PERF_REG_S390_FP7:
0559 return "FP7";
0560 case PERF_REG_S390_FP8:
0561 return "FP8";
0562 case PERF_REG_S390_FP9:
0563 return "FP9";
0564 case PERF_REG_S390_FP10:
0565 return "FP10";
0566 case PERF_REG_S390_FP11:
0567 return "FP11";
0568 case PERF_REG_S390_FP12:
0569 return "FP12";
0570 case PERF_REG_S390_FP13:
0571 return "FP13";
0572 case PERF_REG_S390_FP14:
0573 return "FP14";
0574 case PERF_REG_S390_FP15:
0575 return "FP15";
0576 case PERF_REG_S390_MASK:
0577 return "MASK";
0578 case PERF_REG_S390_PC:
0579 return "PC";
0580 default:
0581 return NULL;
0582 }
0583
0584 return NULL;
0585 }
0586
0587 static const char *__perf_reg_name_x86(int id)
0588 {
0589 switch (id) {
0590 case PERF_REG_X86_AX:
0591 return "AX";
0592 case PERF_REG_X86_BX:
0593 return "BX";
0594 case PERF_REG_X86_CX:
0595 return "CX";
0596 case PERF_REG_X86_DX:
0597 return "DX";
0598 case PERF_REG_X86_SI:
0599 return "SI";
0600 case PERF_REG_X86_DI:
0601 return "DI";
0602 case PERF_REG_X86_BP:
0603 return "BP";
0604 case PERF_REG_X86_SP:
0605 return "SP";
0606 case PERF_REG_X86_IP:
0607 return "IP";
0608 case PERF_REG_X86_FLAGS:
0609 return "FLAGS";
0610 case PERF_REG_X86_CS:
0611 return "CS";
0612 case PERF_REG_X86_SS:
0613 return "SS";
0614 case PERF_REG_X86_DS:
0615 return "DS";
0616 case PERF_REG_X86_ES:
0617 return "ES";
0618 case PERF_REG_X86_FS:
0619 return "FS";
0620 case PERF_REG_X86_GS:
0621 return "GS";
0622 case PERF_REG_X86_R8:
0623 return "R8";
0624 case PERF_REG_X86_R9:
0625 return "R9";
0626 case PERF_REG_X86_R10:
0627 return "R10";
0628 case PERF_REG_X86_R11:
0629 return "R11";
0630 case PERF_REG_X86_R12:
0631 return "R12";
0632 case PERF_REG_X86_R13:
0633 return "R13";
0634 case PERF_REG_X86_R14:
0635 return "R14";
0636 case PERF_REG_X86_R15:
0637 return "R15";
0638
0639 #define XMM(x) \
0640 case PERF_REG_X86_XMM ## x: \
0641 case PERF_REG_X86_XMM ## x + 1: \
0642 return "XMM" #x;
0643 XMM(0)
0644 XMM(1)
0645 XMM(2)
0646 XMM(3)
0647 XMM(4)
0648 XMM(5)
0649 XMM(6)
0650 XMM(7)
0651 XMM(8)
0652 XMM(9)
0653 XMM(10)
0654 XMM(11)
0655 XMM(12)
0656 XMM(13)
0657 XMM(14)
0658 XMM(15)
0659 #undef XMM
0660 default:
0661 return NULL;
0662 }
0663
0664 return NULL;
0665 }
0666
0667 const char *perf_reg_name(int id, const char *arch)
0668 {
0669 const char *reg_name = NULL;
0670
0671 if (!strcmp(arch, "csky"))
0672 reg_name = __perf_reg_name_csky(id);
0673 else if (!strcmp(arch, "mips"))
0674 reg_name = __perf_reg_name_mips(id);
0675 else if (!strcmp(arch, "powerpc"))
0676 reg_name = __perf_reg_name_powerpc(id);
0677 else if (!strcmp(arch, "riscv"))
0678 reg_name = __perf_reg_name_riscv(id);
0679 else if (!strcmp(arch, "s390"))
0680 reg_name = __perf_reg_name_s390(id);
0681 else if (!strcmp(arch, "x86"))
0682 reg_name = __perf_reg_name_x86(id);
0683 else if (!strcmp(arch, "arm"))
0684 reg_name = __perf_reg_name_arm(id);
0685 else if (!strcmp(arch, "arm64"))
0686 reg_name = __perf_reg_name_arm64(id);
0687
0688 return reg_name ?: "unknown";
0689 }
0690
0691 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
0692 {
0693 int i, idx = 0;
0694 u64 mask = regs->mask;
0695
0696 if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE)
0697 return -EINVAL;
0698
0699 if (regs->cache_mask & (1ULL << id))
0700 goto out;
0701
0702 if (!(mask & (1ULL << id)))
0703 return -EINVAL;
0704
0705 for (i = 0; i < id; i++) {
0706 if (mask & (1ULL << i))
0707 idx++;
0708 }
0709
0710 regs->cache_mask |= (1ULL << id);
0711 regs->cache_regs[id] = regs->regs[idx];
0712
0713 out:
0714 *valp = regs->cache_regs[id];
0715 return 0;
0716 }
0717 #endif