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 f599064..225c64c 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 e18a355..46ed00d 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 d487007..1a95017 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 0a52429..d64ba0c 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 */