Icelake and later platforms support collecting XMM registers with PEBS event. Add support for 'perf script' to dump them, and support for the register parser in 'perf record -I=' ... to configure them. For now they are just printed in hex, we could potentially later add other formats too. Committer testing: Before: # perf record -IXMM0 Warning: unknown register XMM0, check man page or run 'perf record -I?' Usage: perf record [<options>] [<command>] or: perf record [<options>] -- <command> [<options>] # # perf record -I? available registers: AX BX CX DX SI DI BP SP IP FLAGS CS SS R8 R9 R10 R11 R12 R13 R14 R15 Usage: perf record [<options>] [<command>] or: perf record [<options>] -- <command> [<options>] # After: # perf record -IXMM0 Error: The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (cycles). /bin/dmesg | grep -i perf may provide additional information. # # perf record -I? available registers: AX BX CX DX SI DI BP SP IP FLAGS CS SS R8 R9 R10 R11 R12 R13 R14 R15 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 XMM9 XMM10 XMM11 XMM12 XMM13 XMM14 XMM15 Usage: perf record [<options>] [<command>] or: perf record [<options>] -- <command> [<options>] -I, --intr-regs[=<any register>] sample selected machine registers on interrupt, use -I ? to list register names # More work is needed to, when faced with such error, warn the user that that register is not available on the running platform.
Unified · Split
| @@ -8,9 +8,9 @@ · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | void perf_regs_load(u64 *regs); | 9 | void perf_regs_load(u64 *regs); |
| 10 | 10 | ||
| 11 | #define PERF_REGS_MAX PERF_REG_X86_XMM_MAX | ||
| 11 | #ifndef HAVE_ARCH_X86_64_SUPPORT | 12 | #ifndef HAVE_ARCH_X86_64_SUPPORT |
| 12 | #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) | 13 | #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) |
| 13 | #define PERF_REGS_MAX PERF_REG_X86_32_MAX | ||
| 14 | #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32 | 14 | #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32 |
| 15 | #else | 15 | #else |
| 16 | #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ | 16 | #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ |
| @@ -18,7 +18,6 @@ void perf_regs_load(u64 *regs); · 1 unmodified line | |||
| 18 | (1ULL << PERF_REG_X86_FS) | \ | 18 | (1ULL << PERF_REG_X86_FS) | \ |
| 19 | (1ULL << PERF_REG_X86_GS)) | 19 | (1ULL << PERF_REG_X86_GS)) |
| 20 | #define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT) | 20 | #define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT) |
| 21 | #define PERF_REGS_MAX PERF_REG_X86_64_MAX | ||
| 22 | #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64 | 21 | #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64 |
| 23 | #endif | 22 | #endif |
| 24 | #define PERF_REG_IP PERF_REG_X86_IP | 23 | #define PERF_REG_IP PERF_REG_X86_IP |
| @@ -77,6 +76,28 @@ static inline const char *perf_reg_name(int id) · 52 unmodified lines | |||
| 77 | case PERF_REG_X86_R15: | 76 | case PERF_REG_X86_R15: |
| 78 | return "R15"; | 77 | return "R15"; |
| 79 | #endif /* HAVE_ARCH_X86_64_SUPPORT */ | 78 | #endif /* HAVE_ARCH_X86_64_SUPPORT */ |
| 79 | |||
| 80 | #define XMM(x) \ | ||
| 81 | case PERF_REG_X86_XMM ## x: \ | ||
| 82 | case PERF_REG_X86_XMM ## x + 1: \ | ||
| 83 | return "XMM" #x; | ||
| 84 | XMM(0) | ||
| 85 | XMM(1) | ||
| 86 | XMM(2) | ||
| 87 | XMM(3) | ||
| 88 | XMM(4) | ||
| 89 | XMM(5) | ||
| 90 | XMM(6) | ||
| 91 | XMM(7) | ||
| 92 | XMM(8) | ||
| 93 | XMM(9) | ||
| 94 | XMM(10) | ||
| 95 | XMM(11) | ||
| 96 | XMM(12) | ||
| 97 | XMM(13) | ||
| 98 | XMM(14) | ||
| 99 | XMM(15) | ||
| 100 | #undef XMM | ||
| 80 | default: | 101 | default: |
| 81 | return NULL; | 102 | return NULL; |
| 82 | } | 103 | } |
| @@ -31,6 +31,22 @@ const struct sample_reg sample_reg_masks[] = { · 30 unmodified lines | |||
| 31 | SMPL_REG(R14, PERF_REG_X86_R14), | 31 | SMPL_REG(R14, PERF_REG_X86_R14), |
| 32 | SMPL_REG(R15, PERF_REG_X86_R15), | 32 | SMPL_REG(R15, PERF_REG_X86_R15), |
| 33 | #endif | 33 | #endif |
| 34 | SMPL_REG2(XMM0, PERF_REG_X86_XMM0), | ||
| 35 | SMPL_REG2(XMM1, PERF_REG_X86_XMM1), | ||
| 36 | SMPL_REG2(XMM2, PERF_REG_X86_XMM2), | ||
| 37 | SMPL_REG2(XMM3, PERF_REG_X86_XMM3), | ||
| 38 | SMPL_REG2(XMM4, PERF_REG_X86_XMM4), | ||
| 39 | SMPL_REG2(XMM5, PERF_REG_X86_XMM5), | ||
| 40 | SMPL_REG2(XMM6, PERF_REG_X86_XMM6), | ||
| 41 | SMPL_REG2(XMM7, PERF_REG_X86_XMM7), | ||
| 42 | SMPL_REG2(XMM8, PERF_REG_X86_XMM8), | ||
| 43 | SMPL_REG2(XMM9, PERF_REG_X86_XMM9), | ||
| 44 | SMPL_REG2(XMM10, PERF_REG_X86_XMM10), | ||
| 45 | SMPL_REG2(XMM11, PERF_REG_X86_XMM11), | ||
| 46 | SMPL_REG2(XMM12, PERF_REG_X86_XMM12), | ||
| 47 | SMPL_REG2(XMM13, PERF_REG_X86_XMM13), | ||
| 48 | SMPL_REG2(XMM14, PERF_REG_X86_XMM14), | ||
| 49 | SMPL_REG2(XMM15, PERF_REG_X86_XMM15), | ||
| 34 | SMPL_REG_END | 50 | SMPL_REG_END |
| 35 | }; | 51 | }; |
| 36 | 52 | ||
| @@ -12,6 +12,7 @@ struct sample_reg { · 11 unmodified lines | |||
| 12 | uint64_t mask; | 12 | uint64_t mask; |
| 13 | }; | 13 | }; |
| 14 | #define SMPL_REG(n, b) { .name = #n, .mask = 1ULL << (b) } | 14 | #define SMPL_REG(n, b) { .name = #n, .mask = 1ULL << (b) } |
| 15 | #define SMPL_REG2(n, b) { .name = #n, .mask = 3ULL << (b) } | ||
| 15 | #define SMPL_REG_END { .name = NULL } | 16 | #define SMPL_REG_END { .name = NULL } |
| 16 | 17 | ||
| 17 | extern const struct sample_reg sample_reg_masks[]; | 18 | extern const struct sample_reg sample_reg_masks[]; |