aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/perf/core-book3s.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/perf/core-book3s.c')
-rw-r--r--arch/powerpc/perf/core-book3s.c39
1 files changed, 33 insertions, 6 deletions
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 81f8a0c838ae..b0723002a396 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -10,6 +10,7 @@
10 */ 10 */
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/sched/clock.h>
13#include <linux/perf_event.h> 14#include <linux/perf_event.h>
14#include <linux/percpu.h> 15#include <linux/percpu.h>
15#include <linux/hardirq.h> 16#include <linux/hardirq.h>
@@ -130,6 +131,14 @@ static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
130static void pmao_restore_workaround(bool ebb) { } 131static void pmao_restore_workaround(bool ebb) { }
131#endif /* CONFIG_PPC32 */ 132#endif /* CONFIG_PPC32 */
132 133
134bool is_sier_available(void)
135{
136 if (ppmu->flags & PPMU_HAS_SIER)
137 return true;
138
139 return false;
140}
141
133static bool regs_use_siar(struct pt_regs *regs) 142static bool regs_use_siar(struct pt_regs *regs)
134{ 143{
135 /* 144 /*
@@ -864,6 +873,8 @@ static int power_check_constraints(struct cpu_hw_events *cpuhw,
864 int i, j; 873 int i, j;
865 unsigned long addf = ppmu->add_fields; 874 unsigned long addf = ppmu->add_fields;
866 unsigned long tadd = ppmu->test_adder; 875 unsigned long tadd = ppmu->test_adder;
876 unsigned long grp_mask = ppmu->group_constraint_mask;
877 unsigned long grp_val = ppmu->group_constraint_val;
867 878
868 if (n_ev > ppmu->n_counter) 879 if (n_ev > ppmu->n_counter)
869 return -1; 880 return -1;
@@ -884,15 +895,23 @@ static int power_check_constraints(struct cpu_hw_events *cpuhw,
884 for (i = 0; i < n_ev; ++i) { 895 for (i = 0; i < n_ev; ++i) {
885 nv = (value | cpuhw->avalues[i][0]) + 896 nv = (value | cpuhw->avalues[i][0]) +
886 (value & cpuhw->avalues[i][0] & addf); 897 (value & cpuhw->avalues[i][0] & addf);
887 if ((((nv + tadd) ^ value) & mask) != 0 || 898
888 (((nv + tadd) ^ cpuhw->avalues[i][0]) & 899 if (((((nv + tadd) ^ value) & mask) & (~grp_mask)) != 0)
889 cpuhw->amasks[i][0]) != 0) 900 break;
901
902 if (((((nv + tadd) ^ cpuhw->avalues[i][0]) & cpuhw->amasks[i][0])
903 & (~grp_mask)) != 0)
890 break; 904 break;
905
891 value = nv; 906 value = nv;
892 mask |= cpuhw->amasks[i][0]; 907 mask |= cpuhw->amasks[i][0];
893 } 908 }
894 if (i == n_ev) 909 if (i == n_ev) {
895 return 0; /* all OK */ 910 if ((value & mask & grp_mask) != (mask & grp_val))
911 return -1;
912 else
913 return 0; /* all OK */
914 }
896 915
897 /* doesn't work, gather alternatives... */ 916 /* doesn't work, gather alternatives... */
898 if (!ppmu->get_alternatives) 917 if (!ppmu->get_alternatives)
@@ -2148,7 +2167,7 @@ static bool pmc_overflow(unsigned long val)
2148/* 2167/*
2149 * Performance monitor interrupt stuff 2168 * Performance monitor interrupt stuff
2150 */ 2169 */
2151static void perf_event_interrupt(struct pt_regs *regs) 2170static void __perf_event_interrupt(struct pt_regs *regs)
2152{ 2171{
2153 int i, j; 2172 int i, j;
2154 struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events); 2173 struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
@@ -2232,6 +2251,14 @@ static void perf_event_interrupt(struct pt_regs *regs)
2232 irq_exit(); 2251 irq_exit();
2233} 2252}
2234 2253
2254static void perf_event_interrupt(struct pt_regs *regs)
2255{
2256 u64 start_clock = sched_clock();
2257
2258 __perf_event_interrupt(regs);
2259 perf_sample_event_took(sched_clock() - start_clock);
2260}
2261
2235static int power_pmu_prepare_cpu(unsigned int cpu) 2262static int power_pmu_prepare_cpu(unsigned int cpu)
2236{ 2263{
2237 struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); 2264 struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu);