perf tools x86: Add support for recording and printing XMM registers
authorAndi Kleen <ak@linux.intel.com>
Mon, 6 May 2019 14:19:24 +0000 (07:19 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 15 May 2019 19:36:47 +0000 (16:36 -0300)
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.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20190506141926.13659-1-kan.liang@linux.intel.com
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/arch/x86/include/perf_regs.h
tools/perf/arch/x86/util/perf_regs.c
tools/perf/util/perf_regs.h

index 7f6d538f8a8953e5a988730dfe7fff391c49f541..b7321337d10036d577f6434850ccf85b52ade003 100644 (file)
@@ -8,9 +8,9 @@
 
 void perf_regs_load(u64 *regs);
 
+#define PERF_REGS_MAX PERF_REG_X86_XMM_MAX
 #ifndef HAVE_ARCH_X86_64_SUPPORT
 #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
-#define PERF_REGS_MAX PERF_REG_X86_32_MAX
 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
 #else
 #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
@@ -18,7 +18,6 @@ void perf_regs_load(u64 *regs);
                       (1ULL << PERF_REG_X86_FS) | \
                       (1ULL << PERF_REG_X86_GS))
 #define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT)
-#define PERF_REGS_MAX PERF_REG_X86_64_MAX
 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
 #endif
 #define PERF_REG_IP PERF_REG_X86_IP
@@ -77,6 +76,28 @@ static inline const char *perf_reg_name(int id)
        case PERF_REG_X86_R15:
                return "R15";
 #endif /* HAVE_ARCH_X86_64_SUPPORT */
+
+#define XMM(x) \
+       case PERF_REG_X86_XMM ## x:     \
+       case PERF_REG_X86_XMM ## x + 1: \
+               return "XMM" #x;
+       XMM(0)
+       XMM(1)
+       XMM(2)
+       XMM(3)
+       XMM(4)
+       XMM(5)
+       XMM(6)
+       XMM(7)
+       XMM(8)
+       XMM(9)
+       XMM(10)
+       XMM(11)
+       XMM(12)
+       XMM(13)
+       XMM(14)
+       XMM(15)
+#undef XMM
        default:
                return NULL;
        }
index fead6b3b4206e409fc4042ce5d850cae2629bae9..71d7604dbf0bcde07687b649cd083b51f1f66232 100644 (file)
@@ -31,6 +31,22 @@ const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(R14, PERF_REG_X86_R14),
        SMPL_REG(R15, PERF_REG_X86_R15),
 #endif
+       SMPL_REG2(XMM0, PERF_REG_X86_XMM0),
+       SMPL_REG2(XMM1, PERF_REG_X86_XMM1),
+       SMPL_REG2(XMM2, PERF_REG_X86_XMM2),
+       SMPL_REG2(XMM3, PERF_REG_X86_XMM3),
+       SMPL_REG2(XMM4, PERF_REG_X86_XMM4),
+       SMPL_REG2(XMM5, PERF_REG_X86_XMM5),
+       SMPL_REG2(XMM6, PERF_REG_X86_XMM6),
+       SMPL_REG2(XMM7, PERF_REG_X86_XMM7),
+       SMPL_REG2(XMM8, PERF_REG_X86_XMM8),
+       SMPL_REG2(XMM9, PERF_REG_X86_XMM9),
+       SMPL_REG2(XMM10, PERF_REG_X86_XMM10),
+       SMPL_REG2(XMM11, PERF_REG_X86_XMM11),
+       SMPL_REG2(XMM12, PERF_REG_X86_XMM12),
+       SMPL_REG2(XMM13, PERF_REG_X86_XMM13),
+       SMPL_REG2(XMM14, PERF_REG_X86_XMM14),
+       SMPL_REG2(XMM15, PERF_REG_X86_XMM15),
        SMPL_REG_END
 };
 
index c9319f8d17a6accc7267fedf6abb12ac99c873b2..1a15a4bfc28db32f5db555b98b4a4258fe66374a 100644 (file)
@@ -12,6 +12,7 @@ struct sample_reg {
        uint64_t mask;
 };
 #define SMPL_REG(n, b) { .name = #n, .mask = 1ULL << (b) }
+#define SMPL_REG2(n, b) { .name = #n, .mask = 3ULL << (b) }
 #define SMPL_REG_END { .name = NULL }
 
 extern const struct sample_reg sample_reg_masks[];