diff options
Diffstat (limited to 'arch/powerpc/perf/core-book3s.c')
-rw-r--r-- | arch/powerpc/perf/core-book3s.c | 39 |
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) {} | |||
130 | static void pmao_restore_workaround(bool ebb) { } | 131 | static void pmao_restore_workaround(bool ebb) { } |
131 | #endif /* CONFIG_PPC32 */ | 132 | #endif /* CONFIG_PPC32 */ |
132 | 133 | ||
134 | bool is_sier_available(void) | ||
135 | { | ||
136 | if (ppmu->flags & PPMU_HAS_SIER) | ||
137 | return true; | ||
138 | |||
139 | return false; | ||
140 | } | ||
141 | |||
133 | static bool regs_use_siar(struct pt_regs *regs) | 142 | static 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 | */ |
2151 | static void perf_event_interrupt(struct pt_regs *regs) | 2170 | static 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 | ||
2254 | static 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 | |||
2235 | static int power_pmu_prepare_cpu(unsigned int cpu) | 2262 | static 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); |