perf tools powerpc: Add support for extended register capability
authorAnju T Sudhakar <anju@linux.vnet.ibm.com>
Fri, 7 Aug 2020 10:11:18 +0000 (06:11 -0400)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 7 Aug 2020 12:27:03 +0000 (09:27 -0300)
Add extended regs to sample_reg_mask in the tool side to use with `-I?`
option. Perf tools side uses extended mask to display the platform
supported register names (with -I? option) to the user and also send
this mask to the kernel to capture the extended registers in each
sample. Hence decide the mask value based on the processor version.

Currently definitions for `mfspr`, `SPRN_PVR` are part of
`arch/powerpc/util/header.c`. Move this to a header file so that these
definitions can be re-used in other source files as well.

Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com>
Reviewed-by: Kajol Jain <kjain@linux.ibm.com>
Reviewed-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Reviewed--by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Tested-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michael Neuling <mikey@neuling.org> <mikey@neuling.org>
Cc: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
[Decide extended mask at run time based on platform]
Signed-off-by: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/arch/powerpc/include/uapi/asm/perf_regs.h
tools/perf/arch/powerpc/include/perf_regs.h
tools/perf/arch/powerpc/util/header.c
tools/perf/arch/powerpc/util/perf_regs.c
tools/perf/arch/powerpc/util/utils_header.h [new file with mode: 0644]

index f599064dd8dc8431fbe705320d9afc7f862f1207..225c64c56813586d1e82a9906dbdba7ef96b0a53 100644 (file)
@@ -48,6 +48,18 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
        PERF_REG_POWERPC_MMCRA,
-       PERF_REG_POWERPC_MAX,
+       /* Extended registers */
+       PERF_REG_POWERPC_MMCR0,
+       PERF_REG_POWERPC_MMCR1,
+       PERF_REG_POWERPC_MMCR2,
+       /* Max regs without the extended regs */
+       PERF_REG_POWERPC_MAX = PERF_REG_POWERPC_MMCRA + 1,
 };
+
+#define PERF_REG_PMU_MASK      ((1ULL << PERF_REG_POWERPC_MAX) - 1)
+
+/* PERF_REG_EXTENDED_MASK value for CPU_FTR_ARCH_300 */
+#define PERF_REG_PMU_MASK_300   (((1ULL << (PERF_REG_POWERPC_MMCR2 + 1)) - 1) - PERF_REG_PMU_MASK)
+
+#define PERF_REG_MAX_ISA_300   (PERF_REG_POWERPC_MMCR2 + 1)
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
index e18a3556f5e315849854bc9fe6a8f42c52cd64f6..46ed00d36b013b463d7e4af7ba8507b6717ab38a 100644 (file)
@@ -64,7 +64,10 @@ static const char *reg_names[] = {
        [PERF_REG_POWERPC_DAR] = "dar",
        [PERF_REG_POWERPC_DSISR] = "dsisr",
        [PERF_REG_POWERPC_SIER] = "sier",
-       [PERF_REG_POWERPC_MMCRA] = "mmcra"
+       [PERF_REG_POWERPC_MMCRA] = "mmcra",
+       [PERF_REG_POWERPC_MMCR0] = "mmcr0",
+       [PERF_REG_POWERPC_MMCR1] = "mmcr1",
+       [PERF_REG_POWERPC_MMCR2] = "mmcr2",
 };
 
 static inline const char *perf_reg_name(int id)
index d4870074f14c714fa409e5f738ad186f3a0942e7..1a950171a66fa7a242d00e711544d79b56544b18 100644 (file)
@@ -7,17 +7,10 @@
 #include <string.h>
 #include <linux/stringify.h>
 #include "header.h"
+#include "utils_header.h"
 #include "metricgroup.h"
 #include <api/fs/fs.h>
 
-#define mfspr(rn)       ({unsigned long rval; \
-                        asm volatile("mfspr %0," __stringify(rn) \
-                                     : "=r" (rval)); rval; })
-
-#define SPRN_PVR        0x11F  /* Processor Version Register */
-#define PVR_VER(pvr)    (((pvr) >>  16) & 0xFFFF) /* Version field */
-#define PVR_REV(pvr)    (((pvr) >>   0) & 0xFFFF) /* Revison field */
-
 int
 get_cpuid(char *buffer, size_t sz)
 {
index 0a5242900248504530b760a60886d68cb1208df9..d64ba0c0c854e6f842d8cd903d661a9e8341bc88 100644 (file)
@@ -6,9 +6,15 @@
 
 #include "../../../util/perf_regs.h"
 #include "../../../util/debug.h"
+#include "../../../util/event.h"
+#include "../../../util/header.h"
+#include "../../../perf-sys.h"
+#include "utils_header.h"
 
 #include <linux/kernel.h>
 
+#define PVR_POWER9             0x004E
+
 const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(r0, PERF_REG_POWERPC_R0),
        SMPL_REG(r1, PERF_REG_POWERPC_R1),
@@ -55,6 +61,9 @@ const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
        SMPL_REG(sier, PERF_REG_POWERPC_SIER),
        SMPL_REG(mmcra, PERF_REG_POWERPC_MMCRA),
+       SMPL_REG(mmcr0, PERF_REG_POWERPC_MMCR0),
+       SMPL_REG(mmcr1, PERF_REG_POWERPC_MMCR1),
+       SMPL_REG(mmcr2, PERF_REG_POWERPC_MMCR2),
        SMPL_REG_END
 };
 
@@ -163,3 +172,43 @@ int arch_sdt_arg_parse_op(char *old_op, char **new_op)
 
        return SDT_ARG_VALID;
 }
+
+uint64_t arch__intr_reg_mask(void)
+{
+       struct perf_event_attr attr = {
+               .type                   = PERF_TYPE_HARDWARE,
+               .config                 = PERF_COUNT_HW_CPU_CYCLES,
+               .sample_type            = PERF_SAMPLE_REGS_INTR,
+               .precise_ip             = 1,
+               .disabled               = 1,
+               .exclude_kernel         = 1,
+       };
+       int fd;
+       u32 version;
+       u64 extended_mask = 0, mask = PERF_REGS_MASK;
+
+       /*
+        * Get the PVR value to set the extended
+        * mask specific to platform.
+        */
+       version = (((mfspr(SPRN_PVR)) >>  16) & 0xFFFF);
+       if (version == PVR_POWER9)
+               extended_mask = PERF_REG_PMU_MASK_300;
+       else
+               return mask;
+
+       attr.sample_regs_intr = extended_mask;
+       attr.sample_period = 1;
+       event_attr_init(&attr);
+
+       /*
+        * check if the pmu supports perf extended regs, before
+        * returning the register mask to sample.
+        */
+       fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
+       if (fd != -1) {
+               close(fd);
+               mask |= extended_mask;
+       }
+       return mask;
+}
diff --git a/tools/perf/arch/powerpc/util/utils_header.h b/tools/perf/arch/powerpc/util/utils_header.h
new file mode 100644 (file)
index 0000000..5788eb1
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PERF_UTIL_HEADER_H
+#define __PERF_UTIL_HEADER_H
+
+#include <linux/stringify.h>
+
+#define mfspr(rn)       ({unsigned long rval; \
+                       asm volatile("mfspr %0," __stringify(rn) \
+                               : "=r" (rval)); rval; })
+
+#define SPRN_PVR        0x11F   /* Processor Version Register */
+#define PVR_VER(pvr)    (((pvr) >>  16) & 0xFFFF) /* Version field */
+#define PVR_REV(pvr)    (((pvr) >>   0) & 0xFFFF) /* Revison field */
+
+#endif /* __PERF_UTIL_HEADER_H */