mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
perf tools powerpc: Add support for extended register capability
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>
This commit is contained in:
parent
d01541d006
commit
33583e6950
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
15
tools/perf/arch/powerpc/util/utils_header.h
Normal file
15
tools/perf/arch/powerpc/util/utils_header.h
Normal file
@ -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 */
|
Loading…
Reference in New Issue
Block a user