diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2017-03-09 12:06:41 +0100 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-03-09 12:06:41 +0100 |
commit | 920c634aff6cb66e7f352668521eb1313897e93c (patch) | |
tree | 0f2e2eb15756fdd93c8ea47f9080fc3c1abeeae6 /arch/powerpc/perf/core-book3s.c | |
parent | b28ace12661fbcfd90959c1e84ff5a85113a82a1 (diff) | |
parent | 4b9de5da7e120c7f02395da729f0ec77ce7a6044 (diff) |
Merge tag 'irq-fixes-4.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/urgent
Pull irqchip/irqdomain updates for 4.11-rc2 from Marc Zyngier
- irqchip/crossbar: Some type tidying up
- irqchip/gicv3-its: Workaround for a Qualcomm erratum
- irqdomain: Compile for for systems that don't use CONFIG_IRQ_DOMAIN
Fixed up minor conflict in the crossbar driver.
Diffstat (limited to 'arch/powerpc/perf/core-book3s.c')
-rw-r--r-- | arch/powerpc/perf/core-book3s.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 270eb9b74e2e..595dd718ea87 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -57,6 +57,7 @@ struct cpu_hw_events { void *bhrb_context; struct perf_branch_stack bhrb_stack; struct perf_branch_entry bhrb_entries[BHRB_MAX_ENTRIES]; + u64 ic_init; }; static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); @@ -127,6 +128,10 @@ static inline void power_pmu_bhrb_disable(struct perf_event *event) {} static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in) {} static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {} static void pmao_restore_workaround(bool ebb) { } +static bool use_ic(u64 event) +{ + return false; +} #endif /* CONFIG_PPC32 */ static bool regs_use_siar(struct pt_regs *regs) @@ -243,7 +248,7 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs) */ if (ppmu->flags & PPMU_NO_SIPR) { unsigned long siar = mfspr(SPRN_SIAR); - if (siar >= PAGE_OFFSET) + if (is_kernel_addr(siar)) return PERF_RECORD_MISC_KERNEL; return PERF_RECORD_MISC_USER; } @@ -688,6 +693,15 @@ static void pmao_restore_workaround(bool ebb) mtspr(SPRN_PMC5, pmcs[4]); mtspr(SPRN_PMC6, pmcs[5]); } + +static bool use_ic(u64 event) +{ + if (cpu_has_feature(CPU_FTR_POWER9_DD1) && + (event == 0x200f2 || event == 0x300f2)) + return true; + + return false; +} #endif /* CONFIG_PPC64 */ static void perf_event_interrupt(struct pt_regs *regs); @@ -1007,6 +1021,7 @@ static u64 check_and_compute_delta(u64 prev, u64 val) static void power_pmu_read(struct perf_event *event) { s64 val, delta, prev; + struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); if (event->hw.state & PERF_HES_STOPPED) return; @@ -1016,6 +1031,13 @@ static void power_pmu_read(struct perf_event *event) if (is_ebb_event(event)) { val = read_pmc(event->hw.idx); + if (use_ic(event->attr.config)) { + val = mfspr(SPRN_IC); + if (val > cpuhw->ic_init) + val = val - cpuhw->ic_init; + else + val = val + (0 - cpuhw->ic_init); + } local64_set(&event->hw.prev_count, val); return; } @@ -1029,6 +1051,13 @@ static void power_pmu_read(struct perf_event *event) prev = local64_read(&event->hw.prev_count); barrier(); val = read_pmc(event->hw.idx); + if (use_ic(event->attr.config)) { + val = mfspr(SPRN_IC); + if (val > cpuhw->ic_init) + val = val - cpuhw->ic_init; + else + val = val + (0 - cpuhw->ic_init); + } delta = check_and_compute_delta(prev, val); if (!delta) return; @@ -1466,6 +1495,13 @@ nocheck: event->attr.branch_sample_type); } + /* + * Workaround for POWER9 DD1 to use the Instruction Counter + * register value for instruction counting + */ + if (use_ic(event->attr.config)) + cpuhw->ic_init = mfspr(SPRN_IC); + perf_pmu_enable(event->pmu); local_irq_restore(flags); return ret; |