Patch defines struct perf_arch_regs{} for powerpc and update the per-cpu perf pmu structure to include perf_arch_regs bits. perf_arch_reg_value(), perf_get_arch_reg() and perf_get_arch_regs_mask() are implemented to return proper values for powerpc. Finally adds code to call the processor specific function to update the arch_regs register values.
Cc: Thomas Gleixner <t...@linutronix.de> Cc: Ingo Molnar <mi...@kernel.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Jiri Olsa <jo...@kernel.org> Cc: Arnaldo Carvalho de Melo <a...@kernel.org> Cc: Stephane Eranian <eran...@gmail.com> Cc: Russell King <li...@arm.linux.org.uk> Cc: Catalin Marinas <catalin.mari...@arm.com> Cc: Will Deacon <will.dea...@arm.com> Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org> Cc: Michael Ellerman <m...@ellerman.id.au> Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com> Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com> --- arch/powerpc/include/asm/perf_event_server.h | 11 ++++++++ arch/powerpc/perf/core-book3s.c | 38 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index e157489ee7a1..65699fefb5a8 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h @@ -12,6 +12,7 @@ #include <linux/types.h> #include <asm/hw_irq.h> #include <linux/device.h> +#include <uapi/asm/perf_regs.h> #include <uapi/asm/perf_event.h> /* Update perf_event_print_debug() if this changes */ @@ -21,6 +22,12 @@ struct perf_event; +struct perf_arch_regs { + unsigned long regs[PERF_ARCH_REG_POWERPC_MAX]; +}; + +#define perf_arch_regs perf_arch_regs + /* * This struct provides the constants and functions needed to * describe the PMU on a particular POWER-family CPU. @@ -52,6 +59,10 @@ struct power_pmu { /* BHRB entries in the PMU */ int bhrb_nr; + + /* perf_arch_regs bits */ + u64 ar_mask; + void (*get_arch_regs)(struct perf_arch_regs *regs); }; /* diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 4ed377f0f7b2..6acf086f31b3 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -57,6 +57,9 @@ struct cpu_hw_events { void *bhrb_context; struct perf_branch_stack bhrb_stack; struct perf_branch_entry bhrb_entries[BHRB_MAX_ENTRIES]; + + /* perf_arch_regs bits */ + struct perf_arch_regs ar_regs; }; static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); @@ -1928,6 +1931,33 @@ ssize_t power_events_sysfs_show(struct device *dev, return sprintf(page, "event=0x%02llx\n", pmu_attr->id); } +u64 perf_get_arch_regs_mask(void) +{ + return ppmu->ar_mask; +} + +struct perf_arch_regs *perf_get_arch_reg() +{ + struct cpu_hw_events *cpuhw; + + cpuhw = this_cpu_ptr(&cpu_hw_events); + if (!ppmu->ar_mask) + return NULL; + + return &cpuhw->ar_regs; +} + +u64 perf_arch_reg_value(struct perf_arch_regs *regs, int idx) +{ + struct cpu_hw_events *cpuhw; + + cpuhw = this_cpu_ptr(&cpu_hw_events); + if (WARN_ON_ONCE(idx >= PERF_ARCH_REG_POWERPC_MAX)) + return 0; + + return cpuhw->ar_regs.regs[idx]; +} + static struct pmu power_pmu = { .pmu_enable = power_pmu_enable, .pmu_disable = power_pmu_disable, @@ -2009,6 +2039,14 @@ static void record_and_restart(struct perf_event *event, unsigned long val, data.br_stack = &cpuhw->bhrb_stack; } + if (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) { + struct cpu_hw_events *cpuhw; + cpuhw = this_cpu_ptr(&cpu_hw_events); + + if (ppmu->get_arch_regs) + ppmu->get_arch_regs(&cpuhw->ar_regs); + } + if (perf_event_overflow(event, &data, regs)) power_pmu_stop(event, 0); } -- 2.7.4