Message ID | 20200429060415.25930-3-anju@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | powerpc/perf: Add support for perf extended regs in powerpc | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/apply_patch | success | Successfully applied on branch powerpc/merge (54dc28ff5e0b3585224d49a31b53e030342ca5c3) |
snowpatch_ozlabs/build-ppc64le | success | Build succeeded |
snowpatch_ozlabs/build-ppc64be | success | Build succeeded |
snowpatch_ozlabs/build-ppc64e | success | Build succeeded |
snowpatch_ozlabs/build-pmac32 | warning | Upstream build failed, couldn't test patch |
snowpatch_ozlabs/checkpatch | warning | total: 0 errors, 3 warnings, 0 checks, 170 lines checked |
snowpatch_ozlabs/needsstable | success | Patch has no Fixes tags |
Hi Anju, Minor neats... > /* > diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h b/arch/powerpc/include/uapi/asm/perf_regs.h > index f599064dd8dc..604b831378fe 100644 > --- a/arch/powerpc/include/uapi/asm/perf_regs.h > +++ b/arch/powerpc/include/uapi/asm/perf_regs.h > @@ -48,6 +48,17 @@ 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, > + PERF_REG_EXTENDED_MAX, > + /* 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) Would it make sense to reuse PERF_REG_MASK? Userspace code already uses that name for the same expression. > +#define PERF_REG_EXTENDED_MASK (((1ULL << (PERF_REG_EXTENDED_MAX)) \ > + - 1) - PERF_REG_PMU_MASK) You don't need parenthesis in (PERF_REG_EXTENDED_MAX). Also, better to keep that `- 1)` in first line. > + > #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ > diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c > index 3dcfecf858f3..f56b77800a7b 100644 > --- a/arch/powerpc/perf/core-book3s.c > +++ b/arch/powerpc/perf/core-book3s.c > @@ -2276,6 +2276,7 @@ int register_power_pmu(struct power_pmu *pmu) > > power_pmu.attr_groups = ppmu->attr_groups; > > + power_pmu.capabilities |= (ppmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS); > #ifdef MSR_HV > /* > * Use FCHV to ignore kernel events if MSR.HV is set. > diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c > index a213a0aa5d25..57aa02568caf 100644 > --- a/arch/powerpc/perf/perf_regs.c > +++ b/arch/powerpc/perf/perf_regs.c > @@ -15,7 +15,8 @@ > > #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) > > -#define REG_RESERVED (~((1ULL << PERF_REG_POWERPC_MAX) - 1)) > +#define REG_RESERVED (~(PERF_REG_EXTENDED_MASK) & \ > + (~((1ULL << PERF_REG_POWERPC_MAX) - 1))) Can we reuse PERF_REG_PMU_MASK here and simplify it to: #define REG_RESERVED (~(PERF_REG_EXTENDED_MASK | PERF_REG_PMU_MASK)) > > static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { > PT_REGS_OFFSET(PERF_REG_POWERPC_R0, gpr[0]), > @@ -69,10 +70,22 @@ static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { > PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr), > }; > > +/* Function to return the extended register values */ > +static u64 get_ext_regs_value(int idx) > +{ > + switch (idx) { > + case PERF_REG_POWERPC_MMCR0: > + return mfspr(SPRN_MMCR0); > + case PERF_REG_POWERPC_MMCR1: > + return mfspr(SPRN_MMCR1); > + case PERF_REG_POWERPC_MMCR2: > + return mfspr(SPRN_MMCR2); Unnecessary tabs. [...] > diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h b/tools/arch/powerpc/include/uapi/asm/perf_regs.h > index f599064dd8dc..d66953294c73 100644 > --- a/tools/arch/powerpc/include/uapi/asm/perf_regs.h > +++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h > @@ -48,6 +48,17 @@ enum perf_event_powerpc_regs { > PERF_REG_POWERPC_DSISR, > PERF_REG_POWERPC_SIER, > PERF_REG_POWERPC_MMCRA, > - PERF_REG_POWERPC_MAX, > + /* Extended arch registers */ > + PERF_REG_POWERPC_MMCR0, > + PERF_REG_POWERPC_MMCR1, > + PERF_REG_POWERPC_MMCR2, > + PERF_REG_EXTENDED_MAX, > + /* Max regs without extended arch regs */ > + PERF_REG_POWERPC_MAX = PERF_REG_POWERPC_MMCRA + 1, > + Unnecesasy line. > }; > +#define PERF_REG_PMU_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1) > +#define PERF_REG_EXTENDED_MASK (((1ULL << (PERF_REG_EXTENDED_MAX))\ > + - 1) - PERF_REG_PMU_MASK) > + > #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ > diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h > index e18a3556f5e3..f7bbdb816f88 100644 > --- a/tools/perf/arch/powerpc/include/perf_regs.h > +++ b/tools/perf/arch/powerpc/include/perf_regs.h > @@ -64,7 +64,11 @@ 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", > + Unnecesasy line. Apart from those, for the series: Reviewed-and-Tested-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
On 4/29/20 11:34 AM, Anju T Sudhakar wrote: > The capability flag PERF_PMU_CAP_EXTENDED_REGS, is used to indicate the > PMU which support extended registers. The generic code define the mask > of extended registers as 0 for non supported architectures. > > Add support for extended registers in POWER9 architecture. For POWER9, > the extended registers are mmcr0, mmc1 and mmcr2. > > REG_RESERVED mask is redefined to accommodate the extended registers. > > With patch: > ---------------- > > # perf record -I? > available registers: r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 > r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 nip > msr orig_r3 ctr link xer ccr softe trap dar dsisr sier mmcra mmcr0 > mmcr1 mmcr2 Would prefer to have some flexibility in deciding what to expose in as extended regs. Meaning say if we want to add extended regs in power8 and if we dont want to show for ex say mmcr2 (just for example). Maddy > > # perf record -I ls > # perf script -D > > PERF_RECORD_SAMPLE(IP, 0x1): 9019/9019: 0 period: 1 addr: 0 > ... intr regs: mask 0xffffffffffff ABI 64-bit > .... r0 0xc00000000011b12c > .... r1 0xc000003f9a98b930 > .... r2 0xc000000001a32100 > .... r3 0xc000003f8fe9a800 > .... r4 0xc000003fd1810000 > .... r5 0x3e32557150 > .... r6 0xc000003f9a98b908 > .... r7 0xffffffc1cdae06ac > .... r8 0x818 > [.....] > .... r31 0xc000003ffd047230 > .... nip 0xc00000000011b2c0 > .... msr 0x9000000000009033 > .... orig_r3 0xc00000000011b21c > .... ctr 0xc000000000119380 > .... link 0xc00000000011b12c > .... xer 0x0 > .... ccr 0x28002222 > .... softe 0x1 > .... trap 0xf00 > .... dar 0x0 > .... dsisr 0x80000000000 > .... sier 0x0 > .... mmcra 0x80000000000 > .... mmcr0 0x82008090 > .... mmcr1 0x1e000000 > .... mmcr2 0x0 > ... thread: perf:9019 > > Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com> > --- > arch/powerpc/include/asm/perf_event_server.h | 5 +++ > arch/powerpc/include/uapi/asm/perf_regs.h | 13 +++++++- > arch/powerpc/perf/core-book3s.c | 1 + > arch/powerpc/perf/perf_regs.c | 29 ++++++++++++++-- > arch/powerpc/perf/power9-pmu.c | 1 + > .../arch/powerpc/include/uapi/asm/perf_regs.h | 13 +++++++- > tools/perf/arch/powerpc/include/perf_regs.h | 6 +++- > tools/perf/arch/powerpc/util/perf_regs.c | 33 +++++++++++++++++++ > 8 files changed, 95 insertions(+), 6 deletions(-) > > diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h > index 3e9703f44c7c..1d15953bd99e 100644 > --- a/arch/powerpc/include/asm/perf_event_server.h > +++ b/arch/powerpc/include/asm/perf_event_server.h > @@ -55,6 +55,11 @@ struct power_pmu { > int *blacklist_ev; > /* BHRB entries in the PMU */ > int bhrb_nr; > + /* > + * set this flag with `PERF_PMU_CAP_EXTENDED_REGS` if > + * the pmu supports extended perf regs capability > + */ > + int capabilities; > }; > > /* > diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h b/arch/powerpc/include/uapi/asm/perf_regs.h > index f599064dd8dc..604b831378fe 100644 > --- a/arch/powerpc/include/uapi/asm/perf_regs.h > +++ b/arch/powerpc/include/uapi/asm/perf_regs.h > @@ -48,6 +48,17 @@ 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, > + PERF_REG_EXTENDED_MAX, > + /* 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) > +#define PERF_REG_EXTENDED_MASK (((1ULL << (PERF_REG_EXTENDED_MAX)) \ > + - 1) - PERF_REG_PMU_MASK) > + > #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ > diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c > index 3dcfecf858f3..f56b77800a7b 100644 > --- a/arch/powerpc/perf/core-book3s.c > +++ b/arch/powerpc/perf/core-book3s.c > @@ -2276,6 +2276,7 @@ int register_power_pmu(struct power_pmu *pmu) > > power_pmu.attr_groups = ppmu->attr_groups; > > + power_pmu.capabilities |= (ppmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS); > #ifdef MSR_HV > /* > * Use FCHV to ignore kernel events if MSR.HV is set. > diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c > index a213a0aa5d25..57aa02568caf 100644 > --- a/arch/powerpc/perf/perf_regs.c > +++ b/arch/powerpc/perf/perf_regs.c > @@ -15,7 +15,8 @@ > > #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) > > -#define REG_RESERVED (~((1ULL << PERF_REG_POWERPC_MAX) - 1)) > +#define REG_RESERVED (~(PERF_REG_EXTENDED_MASK) & \ > + (~((1ULL << PERF_REG_POWERPC_MAX) - 1))) > > static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { > PT_REGS_OFFSET(PERF_REG_POWERPC_R0, gpr[0]), > @@ -69,10 +70,22 @@ static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { > PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr), > }; > > +/* Function to return the extended register values */ > +static u64 get_ext_regs_value(int idx) > +{ > + switch (idx) { > + case PERF_REG_POWERPC_MMCR0: > + return mfspr(SPRN_MMCR0); > + case PERF_REG_POWERPC_MMCR1: > + return mfspr(SPRN_MMCR1); > + case PERF_REG_POWERPC_MMCR2: > + return mfspr(SPRN_MMCR2); > + default: return 0; > + } > +} > + > u64 perf_reg_value(struct pt_regs *regs, int idx) > { > - if (WARN_ON_ONCE(idx >= PERF_REG_POWERPC_MAX)) > - return 0; > > if (idx == PERF_REG_POWERPC_SIER && > (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) || > @@ -85,6 +98,16 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) > IS_ENABLED(CONFIG_PPC32))) > return 0; > > + if (idx >= PERF_REG_POWERPC_MAX && idx < PERF_REG_EXTENDED_MAX) > + return get_ext_regs_value(idx); > + > + /* > + * If the idx is referring to value beyond the > + * supported registers, return 0 with a warning > + */ > + if (WARN_ON_ONCE(idx >= PERF_REG_EXTENDED_MAX)) > + return 0; > + > return regs_get_register(regs, pt_regs_offset[idx]); > } > > diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c > index 08c3ef796198..c37193b3e73f 100644 > --- a/arch/powerpc/perf/power9-pmu.c > +++ b/arch/powerpc/perf/power9-pmu.c > @@ -434,6 +434,7 @@ static struct power_pmu power9_pmu = { > .cache_events = &power9_cache_events, > .attr_groups = power9_pmu_attr_groups, > .bhrb_nr = 32, > + .capabilities = PERF_PMU_CAP_EXTENDED_REGS, > }; > > int init_power9_pmu(void) > diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h b/tools/arch/powerpc/include/uapi/asm/perf_regs.h > index f599064dd8dc..d66953294c73 100644 > --- a/tools/arch/powerpc/include/uapi/asm/perf_regs.h > +++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h > @@ -48,6 +48,17 @@ enum perf_event_powerpc_regs { > PERF_REG_POWERPC_DSISR, > PERF_REG_POWERPC_SIER, > PERF_REG_POWERPC_MMCRA, > - PERF_REG_POWERPC_MAX, > + /* Extended arch registers */ > + PERF_REG_POWERPC_MMCR0, > + PERF_REG_POWERPC_MMCR1, > + PERF_REG_POWERPC_MMCR2, > + PERF_REG_EXTENDED_MAX, > + /* Max regs without extended arch regs */ > + PERF_REG_POWERPC_MAX = PERF_REG_POWERPC_MMCRA + 1, > + > }; > +#define PERF_REG_PMU_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1) > +#define PERF_REG_EXTENDED_MASK (((1ULL << (PERF_REG_EXTENDED_MAX))\ > + - 1) - PERF_REG_PMU_MASK) > + > #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ > diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h > index e18a3556f5e3..f7bbdb816f88 100644 > --- a/tools/perf/arch/powerpc/include/perf_regs.h > +++ b/tools/perf/arch/powerpc/include/perf_regs.h > @@ -64,7 +64,11 @@ 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) > diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c > index 0a5242900248..37b150f9d1a1 100644 > --- a/tools/perf/arch/powerpc/util/perf_regs.c > +++ b/tools/perf/arch/powerpc/util/perf_regs.c > @@ -6,6 +6,8 @@ > > #include "../../../util/perf_regs.h" > #include "../../../util/debug.h" > +#include "../../../util/event.h" > +#include "../../../perf-sys.h" > > #include <linux/kernel.h> > > @@ -55,6 +57,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 +168,31 @@ 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, > + .sample_regs_intr = PERF_REG_EXTENDED_MASK, > + .precise_ip = 1, > + .disabled = 1, > + .exclude_kernel = 1, > + }; > + int fd; > + > + 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); > + return (PERF_REG_EXTENDED_MASK | PERF_REGS_MASK); > + } > + return PERF_REGS_MASK; > +}
> On 06-May-2020, at 9:56 AM, Madhavan Srinivasan <maddy@linux.ibm.com> wrote: > > > > On 4/29/20 11:34 AM, Anju T Sudhakar wrote: >> The capability flag PERF_PMU_CAP_EXTENDED_REGS, is used to indicate the >> PMU which support extended registers. The generic code define the mask >> of extended registers as 0 for non supported architectures. >> >> Add support for extended registers in POWER9 architecture. For POWER9, >> the extended registers are mmcr0, mmc1 and mmcr2. >> >> REG_RESERVED mask is redefined to accommodate the extended registers. >> >> With patch: >> ---------------- >> >> # perf record -I? >> available registers: r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 >> r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 nip >> msr orig_r3 ctr link xer ccr softe trap dar dsisr sier mmcra mmcr0 >> mmcr1 mmcr2 > > Would prefer to have some flexibility in deciding what to expose > in as extended regs. Meaning say if we want to add extended regs > in power8 and if we dont want to show for ex say mmcr2 (just for example). > One way to approach this is to have the "extended mask" exposed in sysfs: "/sys/bus/event_source/devices/cpu/caps/ext_regs_mask" by the platform pmu driver. This way the perf tool side can look at this and platform driver will also have control on what to expose as part of the extended regs. 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 we need to expose the appropriated mask to the perf tool side. Thanks Athira > Maddy > >> >> # perf record -I ls >> # perf script -D >> >> PERF_RECORD_SAMPLE(IP, 0x1): 9019/9019: 0 period: 1 addr: 0 >> ... intr regs: mask 0xffffffffffff ABI 64-bit >> .... r0 0xc00000000011b12c >> .... r1 0xc000003f9a98b930 >> .... r2 0xc000000001a32100 >> .... r3 0xc000003f8fe9a800 >> .... r4 0xc000003fd1810000 >> .... r5 0x3e32557150 >> .... r6 0xc000003f9a98b908 >> .... r7 0xffffffc1cdae06ac >> .... r8 0x818 >> [.....] >> .... r31 0xc000003ffd047230 >> .... nip 0xc00000000011b2c0 >> .... msr 0x9000000000009033 >> .... orig_r3 0xc00000000011b21c >> .... ctr 0xc000000000119380 >> .... link 0xc00000000011b12c >> .... xer 0x0 >> .... ccr 0x28002222 >> .... softe 0x1 >> .... trap 0xf00 >> .... dar 0x0 >> .... dsisr 0x80000000000 >> .... sier 0x0 >> .... mmcra 0x80000000000 >> .... mmcr0 0x82008090 >> .... mmcr1 0x1e000000 >> .... mmcr2 0x0 >> ... thread: perf:9019 >> >> Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com> >> --- >> arch/powerpc/include/asm/perf_event_server.h | 5 +++ >> arch/powerpc/include/uapi/asm/perf_regs.h | 13 +++++++- >> arch/powerpc/perf/core-book3s.c | 1 + >> arch/powerpc/perf/perf_regs.c | 29 ++++++++++++++-- >> arch/powerpc/perf/power9-pmu.c | 1 + >> .../arch/powerpc/include/uapi/asm/perf_regs.h | 13 +++++++- >> tools/perf/arch/powerpc/include/perf_regs.h | 6 +++- >> tools/perf/arch/powerpc/util/perf_regs.c | 33 +++++++++++++++++++ >> 8 files changed, 95 insertions(+), 6 deletions(-) >> >> diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h >> index 3e9703f44c7c..1d15953bd99e 100644 >> --- a/arch/powerpc/include/asm/perf_event_server.h >> +++ b/arch/powerpc/include/asm/perf_event_server.h >> @@ -55,6 +55,11 @@ struct power_pmu { >> int *blacklist_ev; >> /* BHRB entries in the PMU */ >> int bhrb_nr; >> + /* >> + * set this flag with `PERF_PMU_CAP_EXTENDED_REGS` if >> + * the pmu supports extended perf regs capability >> + */ >> + int capabilities; >> }; >> >> /* >> diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h b/arch/powerpc/include/uapi/asm/perf_regs.h >> index f599064dd8dc..604b831378fe 100644 >> --- a/arch/powerpc/include/uapi/asm/perf_regs.h >> +++ b/arch/powerpc/include/uapi/asm/perf_regs.h >> @@ -48,6 +48,17 @@ 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, >> + PERF_REG_EXTENDED_MAX, >> + /* 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) >> +#define PERF_REG_EXTENDED_MASK (((1ULL << (PERF_REG_EXTENDED_MAX)) \ >> + - 1) - PERF_REG_PMU_MASK) >> + >> #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ >> diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c >> index 3dcfecf858f3..f56b77800a7b 100644 >> --- a/arch/powerpc/perf/core-book3s.c >> +++ b/arch/powerpc/perf/core-book3s.c >> @@ -2276,6 +2276,7 @@ int register_power_pmu(struct power_pmu *pmu) >> >> power_pmu.attr_groups = ppmu->attr_groups; >> >> + power_pmu.capabilities |= (ppmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS); >> #ifdef MSR_HV >> /* >> * Use FCHV to ignore kernel events if MSR.HV is set. >> diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c >> index a213a0aa5d25..57aa02568caf 100644 >> --- a/arch/powerpc/perf/perf_regs.c >> +++ b/arch/powerpc/perf/perf_regs.c >> @@ -15,7 +15,8 @@ >> >> #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) >> >> -#define REG_RESERVED (~((1ULL << PERF_REG_POWERPC_MAX) - 1)) >> +#define REG_RESERVED (~(PERF_REG_EXTENDED_MASK) & \ >> + (~((1ULL << PERF_REG_POWERPC_MAX) - 1))) >> >> static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { >> PT_REGS_OFFSET(PERF_REG_POWERPC_R0, gpr[0]), >> @@ -69,10 +70,22 @@ static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { >> PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr), >> }; >> >> +/* Function to return the extended register values */ >> +static u64 get_ext_regs_value(int idx) >> +{ >> + switch (idx) { >> + case PERF_REG_POWERPC_MMCR0: >> + return mfspr(SPRN_MMCR0); >> + case PERF_REG_POWERPC_MMCR1: >> + return mfspr(SPRN_MMCR1); >> + case PERF_REG_POWERPC_MMCR2: >> + return mfspr(SPRN_MMCR2); >> + default: return 0; >> + } >> +} >> + >> u64 perf_reg_value(struct pt_regs *regs, int idx) >> { >> - if (WARN_ON_ONCE(idx >= PERF_REG_POWERPC_MAX)) >> - return 0; >> >> if (idx == PERF_REG_POWERPC_SIER && >> (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) || >> @@ -85,6 +98,16 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) >> IS_ENABLED(CONFIG_PPC32))) >> return 0; >> >> + if (idx >= PERF_REG_POWERPC_MAX && idx < PERF_REG_EXTENDED_MAX) >> + return get_ext_regs_value(idx); >> + >> + /* >> + * If the idx is referring to value beyond the >> + * supported registers, return 0 with a warning >> + */ >> + if (WARN_ON_ONCE(idx >= PERF_REG_EXTENDED_MAX)) >> + return 0; >> + >> return regs_get_register(regs, pt_regs_offset[idx]); >> } >> >> diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c >> index 08c3ef796198..c37193b3e73f 100644 >> --- a/arch/powerpc/perf/power9-pmu.c >> +++ b/arch/powerpc/perf/power9-pmu.c >> @@ -434,6 +434,7 @@ static struct power_pmu power9_pmu = { >> .cache_events = &power9_cache_events, >> .attr_groups = power9_pmu_attr_groups, >> .bhrb_nr = 32, >> + .capabilities = PERF_PMU_CAP_EXTENDED_REGS, >> }; >> >> int init_power9_pmu(void) >> diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h b/tools/arch/powerpc/include/uapi/asm/perf_regs.h >> index f599064dd8dc..d66953294c73 100644 >> --- a/tools/arch/powerpc/include/uapi/asm/perf_regs.h >> +++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h >> @@ -48,6 +48,17 @@ enum perf_event_powerpc_regs { >> PERF_REG_POWERPC_DSISR, >> PERF_REG_POWERPC_SIER, >> PERF_REG_POWERPC_MMCRA, >> - PERF_REG_POWERPC_MAX, >> + /* Extended arch registers */ >> + PERF_REG_POWERPC_MMCR0, >> + PERF_REG_POWERPC_MMCR1, >> + PERF_REG_POWERPC_MMCR2, >> + PERF_REG_EXTENDED_MAX, >> + /* Max regs without extended arch regs */ >> + PERF_REG_POWERPC_MAX = PERF_REG_POWERPC_MMCRA + 1, >> + >> }; >> +#define PERF_REG_PMU_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1) >> +#define PERF_REG_EXTENDED_MASK (((1ULL << (PERF_REG_EXTENDED_MAX))\ >> + - 1) - PERF_REG_PMU_MASK) >> + >> #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ >> diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h >> index e18a3556f5e3..f7bbdb816f88 100644 >> --- a/tools/perf/arch/powerpc/include/perf_regs.h >> +++ b/tools/perf/arch/powerpc/include/perf_regs.h >> @@ -64,7 +64,11 @@ 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) >> diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c >> index 0a5242900248..37b150f9d1a1 100644 >> --- a/tools/perf/arch/powerpc/util/perf_regs.c >> +++ b/tools/perf/arch/powerpc/util/perf_regs.c >> @@ -6,6 +6,8 @@ >> >> #include "../../../util/perf_regs.h" >> #include "../../../util/debug.h" >> +#include "../../../util/event.h" >> +#include "../../../perf-sys.h" >> >> #include <linux/kernel.h> >> >> @@ -55,6 +57,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 +168,31 @@ 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, >> + .sample_regs_intr = PERF_REG_EXTENDED_MASK, >> + .precise_ip = 1, >> + .disabled = 1, >> + .exclude_kernel = 1, >> + }; >> + int fd; >> + >> + 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); >> + return (PERF_REG_EXTENDED_MASK | PERF_REGS_MASK); >> + } >> + return PERF_REGS_MASK; >> +}
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index 3e9703f44c7c..1d15953bd99e 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h @@ -55,6 +55,11 @@ struct power_pmu { int *blacklist_ev; /* BHRB entries in the PMU */ int bhrb_nr; + /* + * set this flag with `PERF_PMU_CAP_EXTENDED_REGS` if + * the pmu supports extended perf regs capability + */ + int capabilities; }; /* diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h b/arch/powerpc/include/uapi/asm/perf_regs.h index f599064dd8dc..604b831378fe 100644 --- a/arch/powerpc/include/uapi/asm/perf_regs.h +++ b/arch/powerpc/include/uapi/asm/perf_regs.h @@ -48,6 +48,17 @@ 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, + PERF_REG_EXTENDED_MAX, + /* 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) +#define PERF_REG_EXTENDED_MASK (((1ULL << (PERF_REG_EXTENDED_MAX)) \ + - 1) - PERF_REG_PMU_MASK) + #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 3dcfecf858f3..f56b77800a7b 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -2276,6 +2276,7 @@ int register_power_pmu(struct power_pmu *pmu) power_pmu.attr_groups = ppmu->attr_groups; + power_pmu.capabilities |= (ppmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS); #ifdef MSR_HV /* * Use FCHV to ignore kernel events if MSR.HV is set. diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c index a213a0aa5d25..57aa02568caf 100644 --- a/arch/powerpc/perf/perf_regs.c +++ b/arch/powerpc/perf/perf_regs.c @@ -15,7 +15,8 @@ #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) -#define REG_RESERVED (~((1ULL << PERF_REG_POWERPC_MAX) - 1)) +#define REG_RESERVED (~(PERF_REG_EXTENDED_MASK) & \ + (~((1ULL << PERF_REG_POWERPC_MAX) - 1))) static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { PT_REGS_OFFSET(PERF_REG_POWERPC_R0, gpr[0]), @@ -69,10 +70,22 @@ static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = { PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr), }; +/* Function to return the extended register values */ +static u64 get_ext_regs_value(int idx) +{ + switch (idx) { + case PERF_REG_POWERPC_MMCR0: + return mfspr(SPRN_MMCR0); + case PERF_REG_POWERPC_MMCR1: + return mfspr(SPRN_MMCR1); + case PERF_REG_POWERPC_MMCR2: + return mfspr(SPRN_MMCR2); + default: return 0; + } +} + u64 perf_reg_value(struct pt_regs *regs, int idx) { - if (WARN_ON_ONCE(idx >= PERF_REG_POWERPC_MAX)) - return 0; if (idx == PERF_REG_POWERPC_SIER && (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) || @@ -85,6 +98,16 @@ u64 perf_reg_value(struct pt_regs *regs, int idx) IS_ENABLED(CONFIG_PPC32))) return 0; + if (idx >= PERF_REG_POWERPC_MAX && idx < PERF_REG_EXTENDED_MAX) + return get_ext_regs_value(idx); + + /* + * If the idx is referring to value beyond the + * supported registers, return 0 with a warning + */ + if (WARN_ON_ONCE(idx >= PERF_REG_EXTENDED_MAX)) + return 0; + return regs_get_register(regs, pt_regs_offset[idx]); } diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c index 08c3ef796198..c37193b3e73f 100644 --- a/arch/powerpc/perf/power9-pmu.c +++ b/arch/powerpc/perf/power9-pmu.c @@ -434,6 +434,7 @@ static struct power_pmu power9_pmu = { .cache_events = &power9_cache_events, .attr_groups = power9_pmu_attr_groups, .bhrb_nr = 32, + .capabilities = PERF_PMU_CAP_EXTENDED_REGS, }; int init_power9_pmu(void) diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h b/tools/arch/powerpc/include/uapi/asm/perf_regs.h index f599064dd8dc..d66953294c73 100644 --- a/tools/arch/powerpc/include/uapi/asm/perf_regs.h +++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h @@ -48,6 +48,17 @@ enum perf_event_powerpc_regs { PERF_REG_POWERPC_DSISR, PERF_REG_POWERPC_SIER, PERF_REG_POWERPC_MMCRA, - PERF_REG_POWERPC_MAX, + /* Extended arch registers */ + PERF_REG_POWERPC_MMCR0, + PERF_REG_POWERPC_MMCR1, + PERF_REG_POWERPC_MMCR2, + PERF_REG_EXTENDED_MAX, + /* Max regs without extended arch regs */ + PERF_REG_POWERPC_MAX = PERF_REG_POWERPC_MMCRA + 1, + }; +#define PERF_REG_PMU_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1) +#define PERF_REG_EXTENDED_MASK (((1ULL << (PERF_REG_EXTENDED_MAX))\ + - 1) - PERF_REG_PMU_MASK) + #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */ diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h index e18a3556f5e3..f7bbdb816f88 100644 --- a/tools/perf/arch/powerpc/include/perf_regs.h +++ b/tools/perf/arch/powerpc/include/perf_regs.h @@ -64,7 +64,11 @@ 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) diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c index 0a5242900248..37b150f9d1a1 100644 --- a/tools/perf/arch/powerpc/util/perf_regs.c +++ b/tools/perf/arch/powerpc/util/perf_regs.c @@ -6,6 +6,8 @@ #include "../../../util/perf_regs.h" #include "../../../util/debug.h" +#include "../../../util/event.h" +#include "../../../perf-sys.h" #include <linux/kernel.h> @@ -55,6 +57,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 +168,31 @@ 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, + .sample_regs_intr = PERF_REG_EXTENDED_MASK, + .precise_ip = 1, + .disabled = 1, + .exclude_kernel = 1, + }; + int fd; + + 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); + return (PERF_REG_EXTENDED_MASK | PERF_REGS_MASK); + } + return PERF_REGS_MASK; +}
The capability flag PERF_PMU_CAP_EXTENDED_REGS, is used to indicate the PMU which support extended registers. The generic code define the mask of extended registers as 0 for non supported architectures. Add support for extended registers in POWER9 architecture. For POWER9, the extended registers are mmcr0, mmc1 and mmcr2. REG_RESERVED mask is redefined to accommodate the extended registers. With patch: ---------------- # perf record -I? available registers: r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 nip msr orig_r3 ctr link xer ccr softe trap dar dsisr sier mmcra mmcr0 mmcr1 mmcr2 # perf record -I ls # perf script -D PERF_RECORD_SAMPLE(IP, 0x1): 9019/9019: 0 period: 1 addr: 0 ... intr regs: mask 0xffffffffffff ABI 64-bit .... r0 0xc00000000011b12c .... r1 0xc000003f9a98b930 .... r2 0xc000000001a32100 .... r3 0xc000003f8fe9a800 .... r4 0xc000003fd1810000 .... r5 0x3e32557150 .... r6 0xc000003f9a98b908 .... r7 0xffffffc1cdae06ac .... r8 0x818 [.....] .... r31 0xc000003ffd047230 .... nip 0xc00000000011b2c0 .... msr 0x9000000000009033 .... orig_r3 0xc00000000011b21c .... ctr 0xc000000000119380 .... link 0xc00000000011b12c .... xer 0x0 .... ccr 0x28002222 .... softe 0x1 .... trap 0xf00 .... dar 0x0 .... dsisr 0x80000000000 .... sier 0x0 .... mmcra 0x80000000000 .... mmcr0 0x82008090 .... mmcr1 0x1e000000 .... mmcr2 0x0 ... thread: perf:9019 Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com> --- arch/powerpc/include/asm/perf_event_server.h | 5 +++ arch/powerpc/include/uapi/asm/perf_regs.h | 13 +++++++- arch/powerpc/perf/core-book3s.c | 1 + arch/powerpc/perf/perf_regs.c | 29 ++++++++++++++-- arch/powerpc/perf/power9-pmu.c | 1 + .../arch/powerpc/include/uapi/asm/perf_regs.h | 13 +++++++- tools/perf/arch/powerpc/include/perf_regs.h | 6 +++- tools/perf/arch/powerpc/util/perf_regs.c | 33 +++++++++++++++++++ 8 files changed, 95 insertions(+), 6 deletions(-)