diff options
Diffstat (limited to 'arch/powerpc/perf/isa207-common.c')
-rw-r--r-- | arch/powerpc/perf/isa207-common.c | 94 |
1 files changed, 75 insertions, 19 deletions
diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c index 50e598cf644b..e79fb5fb817d 100644 --- a/arch/powerpc/perf/isa207-common.c +++ b/arch/powerpc/perf/isa207-common.c | |||
@@ -97,6 +97,28 @@ static unsigned long combine_shift(unsigned long pmc) | |||
97 | return MMCR1_COMBINE_SHIFT(pmc); | 97 | return MMCR1_COMBINE_SHIFT(pmc); |
98 | } | 98 | } |
99 | 99 | ||
100 | static inline bool event_is_threshold(u64 event) | ||
101 | { | ||
102 | return (event >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK; | ||
103 | } | ||
104 | |||
105 | static bool is_thresh_cmp_valid(u64 event) | ||
106 | { | ||
107 | unsigned int cmp, exp; | ||
108 | |||
109 | /* | ||
110 | * Check the mantissa upper two bits are not zero, unless the | ||
111 | * exponent is also zero. See the THRESH_CMP_MANTISSA doc. | ||
112 | */ | ||
113 | cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK; | ||
114 | exp = cmp >> 7; | ||
115 | |||
116 | if (exp && (cmp & 0x60) == 0) | ||
117 | return false; | ||
118 | |||
119 | return true; | ||
120 | } | ||
121 | |||
100 | int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp) | 122 | int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp) |
101 | { | 123 | { |
102 | unsigned int unit, pmc, cache, ebb; | 124 | unsigned int unit, pmc, cache, ebb; |
@@ -163,28 +185,26 @@ int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp) | |||
163 | value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT); | 185 | value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT); |
164 | } | 186 | } |
165 | 187 | ||
166 | /* | 188 | if (cpu_has_feature(CPU_FTR_ARCH_300)) { |
167 | * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, | 189 | if (event_is_threshold(event) && is_thresh_cmp_valid(event)) { |
168 | * the threshold control bits are used for the match value. | 190 | mask |= CNST_THRESH_MASK; |
169 | */ | 191 | value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); |
170 | if (event_is_fab_match(event)) { | 192 | } |
171 | mask |= CNST_FAB_MATCH_MASK; | ||
172 | value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT); | ||
173 | } else { | 193 | } else { |
174 | /* | 194 | /* |
175 | * Check the mantissa upper two bits are not zero, unless the | 195 | * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, |
176 | * exponent is also zero. See the THRESH_CMP_MANTISSA doc. | 196 | * the threshold control bits are used for the match value. |
177 | */ | 197 | */ |
178 | unsigned int cmp, exp; | 198 | if (event_is_fab_match(event)) { |
179 | 199 | mask |= CNST_FAB_MATCH_MASK; | |
180 | cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK; | 200 | value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT); |
181 | exp = cmp >> 7; | 201 | } else { |
182 | 202 | if (!is_thresh_cmp_valid(event)) | |
183 | if (exp && (cmp & 0x60) == 0) | 203 | return -1; |
184 | return -1; | ||
185 | 204 | ||
186 | mask |= CNST_THRESH_MASK; | 205 | mask |= CNST_THRESH_MASK; |
187 | value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); | 206 | value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); |
207 | } | ||
188 | } | 208 | } |
189 | 209 | ||
190 | if (!pmc && ebb) | 210 | if (!pmc && ebb) |
@@ -279,7 +299,7 @@ int isa207_compute_mmcr(u64 event[], int n_ev, | |||
279 | * PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, | 299 | * PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, |
280 | * the threshold bits are used for the match value. | 300 | * the threshold bits are used for the match value. |
281 | */ | 301 | */ |
282 | if (event_is_fab_match(event[i])) { | 302 | if (!cpu_has_feature(CPU_FTR_ARCH_300) && event_is_fab_match(event[i])) { |
283 | mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) & | 303 | mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) & |
284 | EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT; | 304 | EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT; |
285 | } else { | 305 | } else { |
@@ -338,3 +358,39 @@ void isa207_disable_pmc(unsigned int pmc, unsigned long mmcr[]) | |||
338 | if (pmc <= 3) | 358 | if (pmc <= 3) |
339 | mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1)); | 359 | mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1)); |
340 | } | 360 | } |
361 | |||
362 | static int find_alternative(u64 event, const unsigned int ev_alt[][MAX_ALT], int size) | ||
363 | { | ||
364 | int i, j; | ||
365 | |||
366 | for (i = 0; i < size; ++i) { | ||
367 | if (event < ev_alt[i][0]) | ||
368 | break; | ||
369 | |||
370 | for (j = 0; j < MAX_ALT && ev_alt[i][j]; ++j) | ||
371 | if (event == ev_alt[i][j]) | ||
372 | return i; | ||
373 | } | ||
374 | |||
375 | return -1; | ||
376 | } | ||
377 | |||
378 | int isa207_get_alternatives(u64 event, u64 alt[], | ||
379 | const unsigned int ev_alt[][MAX_ALT], int size) | ||
380 | { | ||
381 | int i, j, num_alt = 0; | ||
382 | u64 alt_event; | ||
383 | |||
384 | alt[num_alt++] = event; | ||
385 | i = find_alternative(event, ev_alt, size); | ||
386 | if (i >= 0) { | ||
387 | /* Filter out the original event, it's already in alt[0] */ | ||
388 | for (j = 0; j < MAX_ALT; ++j) { | ||
389 | alt_event = ev_alt[i][j]; | ||
390 | if (alt_event && alt_event != event) | ||
391 | alt[num_alt++] = alt_event; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | return num_alt; | ||
396 | } | ||