aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/perf/isa207-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/perf/isa207-common.c')
-rw-r--r--arch/powerpc/perf/isa207-common.c94
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
100static inline bool event_is_threshold(u64 event)
101{
102 return (event >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK;
103}
104
105static 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
100int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp) 122int 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
362static 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
378int 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}