diff options
Diffstat (limited to 'arch/powerpc/perf/power8-pmu.c')
-rw-r--r-- | arch/powerpc/perf/power8-pmu.c | 256 |
1 files changed, 3 insertions, 253 deletions
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index 4303e9b91e43..5fde2b192fec 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c | |||
@@ -30,250 +30,6 @@ enum { | |||
30 | #define POWER8_MMCRA_IFM2 0x0000000080000000UL | 30 | #define POWER8_MMCRA_IFM2 0x0000000080000000UL |
31 | #define POWER8_MMCRA_IFM3 0x00000000C0000000UL | 31 | #define POWER8_MMCRA_IFM3 0x00000000C0000000UL |
32 | 32 | ||
33 | static inline bool event_is_fab_match(u64 event) | ||
34 | { | ||
35 | /* Only check pmc, unit and pmcxsel, ignore the edge bit (0) */ | ||
36 | event &= 0xff0fe; | ||
37 | |||
38 | /* PM_MRK_FAB_RSP_MATCH & PM_MRK_FAB_RSP_MATCH_CYC */ | ||
39 | return (event == 0x30056 || event == 0x4f052); | ||
40 | } | ||
41 | |||
42 | static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp) | ||
43 | { | ||
44 | unsigned int unit, pmc, cache, ebb; | ||
45 | unsigned long mask, value; | ||
46 | |||
47 | mask = value = 0; | ||
48 | |||
49 | if (event & ~EVENT_VALID_MASK) | ||
50 | return -1; | ||
51 | |||
52 | pmc = (event >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; | ||
53 | unit = (event >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; | ||
54 | cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK; | ||
55 | ebb = (event >> EVENT_EBB_SHIFT) & EVENT_EBB_MASK; | ||
56 | |||
57 | if (pmc) { | ||
58 | u64 base_event; | ||
59 | |||
60 | if (pmc > 6) | ||
61 | return -1; | ||
62 | |||
63 | /* Ignore Linux defined bits when checking event below */ | ||
64 | base_event = event & ~EVENT_LINUX_MASK; | ||
65 | |||
66 | if (pmc >= 5 && base_event != PM_RUN_INST_CMPL && | ||
67 | base_event != PM_RUN_CYC) | ||
68 | return -1; | ||
69 | |||
70 | mask |= CNST_PMC_MASK(pmc); | ||
71 | value |= CNST_PMC_VAL(pmc); | ||
72 | } | ||
73 | |||
74 | if (pmc <= 4) { | ||
75 | /* | ||
76 | * Add to number of counters in use. Note this includes events with | ||
77 | * a PMC of 0 - they still need a PMC, it's just assigned later. | ||
78 | * Don't count events on PMC 5 & 6, there is only one valid event | ||
79 | * on each of those counters, and they are handled above. | ||
80 | */ | ||
81 | mask |= CNST_NC_MASK; | ||
82 | value |= CNST_NC_VAL; | ||
83 | } | ||
84 | |||
85 | if (unit >= 6 && unit <= 9) { | ||
86 | /* | ||
87 | * L2/L3 events contain a cache selector field, which is | ||
88 | * supposed to be programmed into MMCRC. However MMCRC is only | ||
89 | * HV writable, and there is no API for guest kernels to modify | ||
90 | * it. The solution is for the hypervisor to initialise the | ||
91 | * field to zeroes, and for us to only ever allow events that | ||
92 | * have a cache selector of zero. The bank selector (bit 3) is | ||
93 | * irrelevant, as long as the rest of the value is 0. | ||
94 | */ | ||
95 | if (cache & 0x7) | ||
96 | return -1; | ||
97 | |||
98 | } else if (event & EVENT_IS_L1) { | ||
99 | mask |= CNST_L1_QUAL_MASK; | ||
100 | value |= CNST_L1_QUAL_VAL(cache); | ||
101 | } | ||
102 | |||
103 | if (event & EVENT_IS_MARKED) { | ||
104 | mask |= CNST_SAMPLE_MASK; | ||
105 | value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, | ||
110 | * the threshold control bits are used for the match value. | ||
111 | */ | ||
112 | if (event_is_fab_match(event)) { | ||
113 | mask |= CNST_FAB_MATCH_MASK; | ||
114 | value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT); | ||
115 | } else { | ||
116 | /* | ||
117 | * Check the mantissa upper two bits are not zero, unless the | ||
118 | * exponent is also zero. See the THRESH_CMP_MANTISSA doc. | ||
119 | */ | ||
120 | unsigned int cmp, exp; | ||
121 | |||
122 | cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK; | ||
123 | exp = cmp >> 7; | ||
124 | |||
125 | if (exp && (cmp & 0x60) == 0) | ||
126 | return -1; | ||
127 | |||
128 | mask |= CNST_THRESH_MASK; | ||
129 | value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); | ||
130 | } | ||
131 | |||
132 | if (!pmc && ebb) | ||
133 | /* EBB events must specify the PMC */ | ||
134 | return -1; | ||
135 | |||
136 | if (event & EVENT_WANTS_BHRB) { | ||
137 | if (!ebb) | ||
138 | /* Only EBB events can request BHRB */ | ||
139 | return -1; | ||
140 | |||
141 | mask |= CNST_IFM_MASK; | ||
142 | value |= CNST_IFM_VAL(event >> EVENT_IFM_SHIFT); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * All events must agree on EBB, either all request it or none. | ||
147 | * EBB events are pinned & exclusive, so this should never actually | ||
148 | * hit, but we leave it as a fallback in case. | ||
149 | */ | ||
150 | mask |= CNST_EBB_VAL(ebb); | ||
151 | value |= CNST_EBB_MASK; | ||
152 | |||
153 | *maskp = mask; | ||
154 | *valp = value; | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int power8_compute_mmcr(u64 event[], int n_ev, | ||
160 | unsigned int hwc[], unsigned long mmcr[], | ||
161 | struct perf_event *pevents[]) | ||
162 | { | ||
163 | unsigned long mmcra, mmcr1, mmcr2, unit, combine, psel, cache, val; | ||
164 | unsigned int pmc, pmc_inuse; | ||
165 | int i; | ||
166 | |||
167 | pmc_inuse = 0; | ||
168 | |||
169 | /* First pass to count resource use */ | ||
170 | for (i = 0; i < n_ev; ++i) { | ||
171 | pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; | ||
172 | if (pmc) | ||
173 | pmc_inuse |= 1 << pmc; | ||
174 | } | ||
175 | |||
176 | /* In continuous sampling mode, update SDAR on TLB miss */ | ||
177 | mmcra = MMCRA_SDAR_MODE_TLB; | ||
178 | mmcr1 = mmcr2 = 0; | ||
179 | |||
180 | /* Second pass: assign PMCs, set all MMCR1 fields */ | ||
181 | for (i = 0; i < n_ev; ++i) { | ||
182 | pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; | ||
183 | unit = (event[i] >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; | ||
184 | combine = (event[i] >> EVENT_COMBINE_SHIFT) & EVENT_COMBINE_MASK; | ||
185 | psel = event[i] & EVENT_PSEL_MASK; | ||
186 | |||
187 | if (!pmc) { | ||
188 | for (pmc = 1; pmc <= 4; ++pmc) { | ||
189 | if (!(pmc_inuse & (1 << pmc))) | ||
190 | break; | ||
191 | } | ||
192 | |||
193 | pmc_inuse |= 1 << pmc; | ||
194 | } | ||
195 | |||
196 | if (pmc <= 4) { | ||
197 | mmcr1 |= unit << MMCR1_UNIT_SHIFT(pmc); | ||
198 | mmcr1 |= combine << MMCR1_COMBINE_SHIFT(pmc); | ||
199 | mmcr1 |= psel << MMCR1_PMCSEL_SHIFT(pmc); | ||
200 | } | ||
201 | |||
202 | if (event[i] & EVENT_IS_L1) { | ||
203 | cache = event[i] >> EVENT_CACHE_SEL_SHIFT; | ||
204 | mmcr1 |= (cache & 1) << MMCR1_IC_QUAL_SHIFT; | ||
205 | cache >>= 1; | ||
206 | mmcr1 |= (cache & 1) << MMCR1_DC_QUAL_SHIFT; | ||
207 | } | ||
208 | |||
209 | if (event[i] & EVENT_IS_MARKED) { | ||
210 | mmcra |= MMCRA_SAMPLE_ENABLE; | ||
211 | |||
212 | val = (event[i] >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK; | ||
213 | if (val) { | ||
214 | mmcra |= (val & 3) << MMCRA_SAMP_MODE_SHIFT; | ||
215 | mmcra |= (val >> 2) << MMCRA_SAMP_ELIG_SHIFT; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, | ||
221 | * the threshold bits are used for the match value. | ||
222 | */ | ||
223 | if (event_is_fab_match(event[i])) { | ||
224 | mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) & | ||
225 | EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT; | ||
226 | } else { | ||
227 | val = (event[i] >> EVENT_THR_CTL_SHIFT) & EVENT_THR_CTL_MASK; | ||
228 | mmcra |= val << MMCRA_THR_CTL_SHIFT; | ||
229 | val = (event[i] >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK; | ||
230 | mmcra |= val << MMCRA_THR_SEL_SHIFT; | ||
231 | val = (event[i] >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK; | ||
232 | mmcra |= val << MMCRA_THR_CMP_SHIFT; | ||
233 | } | ||
234 | |||
235 | if (event[i] & EVENT_WANTS_BHRB) { | ||
236 | val = (event[i] >> EVENT_IFM_SHIFT) & EVENT_IFM_MASK; | ||
237 | mmcra |= val << MMCRA_IFM_SHIFT; | ||
238 | } | ||
239 | |||
240 | if (pevents[i]->attr.exclude_user) | ||
241 | mmcr2 |= MMCR2_FCP(pmc); | ||
242 | |||
243 | if (pevents[i]->attr.exclude_hv) | ||
244 | mmcr2 |= MMCR2_FCH(pmc); | ||
245 | |||
246 | if (pevents[i]->attr.exclude_kernel) { | ||
247 | if (cpu_has_feature(CPU_FTR_HVMODE)) | ||
248 | mmcr2 |= MMCR2_FCH(pmc); | ||
249 | else | ||
250 | mmcr2 |= MMCR2_FCS(pmc); | ||
251 | } | ||
252 | |||
253 | hwc[i] = pmc - 1; | ||
254 | } | ||
255 | |||
256 | /* Return MMCRx values */ | ||
257 | mmcr[0] = 0; | ||
258 | |||
259 | /* pmc_inuse is 1-based */ | ||
260 | if (pmc_inuse & 2) | ||
261 | mmcr[0] = MMCR0_PMC1CE; | ||
262 | |||
263 | if (pmc_inuse & 0x7c) | ||
264 | mmcr[0] |= MMCR0_PMCjCE; | ||
265 | |||
266 | /* If we're not using PMC 5 or 6, freeze them */ | ||
267 | if (!(pmc_inuse & 0x60)) | ||
268 | mmcr[0] |= MMCR0_FC56; | ||
269 | |||
270 | mmcr[1] = mmcr1; | ||
271 | mmcr[2] = mmcra; | ||
272 | mmcr[3] = mmcr2; | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | /* Table of alternatives, sorted by column 0 */ | 33 | /* Table of alternatives, sorted by column 0 */ |
278 | static const unsigned int event_alternatives[][MAX_ALT] = { | 34 | static const unsigned int event_alternatives[][MAX_ALT] = { |
279 | { PM_MRK_ST_CMPL, PM_MRK_ST_CMPL_ALT }, | 35 | { PM_MRK_ST_CMPL, PM_MRK_ST_CMPL_ALT }, |
@@ -354,12 +110,6 @@ static int power8_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
354 | return num_alt; | 110 | return num_alt; |
355 | } | 111 | } |
356 | 112 | ||
357 | static void power8_disable_pmc(unsigned int pmc, unsigned long mmcr[]) | ||
358 | { | ||
359 | if (pmc <= 3) | ||
360 | mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1)); | ||
361 | } | ||
362 | |||
363 | GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC); | 113 | GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC); |
364 | GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_GCT_NOSLOT_CYC); | 114 | GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_GCT_NOSLOT_CYC); |
365 | GENERIC_EVENT_ATTR(stalled-cycles-backend, PM_CMPLU_STALL); | 115 | GENERIC_EVENT_ATTR(stalled-cycles-backend, PM_CMPLU_STALL); |
@@ -632,12 +382,12 @@ static struct power_pmu power8_pmu = { | |||
632 | .max_alternatives = MAX_ALT + 1, | 382 | .max_alternatives = MAX_ALT + 1, |
633 | .add_fields = ISA207_ADD_FIELDS, | 383 | .add_fields = ISA207_ADD_FIELDS, |
634 | .test_adder = ISA207_TEST_ADDER, | 384 | .test_adder = ISA207_TEST_ADDER, |
635 | .compute_mmcr = power8_compute_mmcr, | 385 | .compute_mmcr = isa207_compute_mmcr, |
636 | .config_bhrb = power8_config_bhrb, | 386 | .config_bhrb = power8_config_bhrb, |
637 | .bhrb_filter_map = power8_bhrb_filter_map, | 387 | .bhrb_filter_map = power8_bhrb_filter_map, |
638 | .get_constraint = power8_get_constraint, | 388 | .get_constraint = isa207_get_constraint, |
639 | .get_alternatives = power8_get_alternatives, | 389 | .get_alternatives = power8_get_alternatives, |
640 | .disable_pmc = power8_disable_pmc, | 390 | .disable_pmc = isa207_disable_pmc, |
641 | .flags = PPMU_HAS_SIER | PPMU_ARCH_207S, | 391 | .flags = PPMU_HAS_SIER | PPMU_ARCH_207S, |
642 | .n_generic = ARRAY_SIZE(power8_generic_events), | 392 | .n_generic = ARRAY_SIZE(power8_generic_events), |
643 | .generic_events = power8_generic_events, | 393 | .generic_events = power8_generic_events, |