.. | .. |
---|
202 | 202 | } |
---|
203 | 203 | |
---|
204 | 204 | /* |
---|
205 | | - * Use IBS for precise event sampling: |
---|
| 205 | + * core pmu config -> IBS config |
---|
206 | 206 | * |
---|
207 | 207 | * perf record -a -e cpu-cycles:p ... # use ibs op counting cycle count |
---|
208 | 208 | * perf record -a -e r076:p ... # same as -e cpu-cycles:p |
---|
.. | .. |
---|
211 | 211 | * IbsOpCntCtl (bit 19) of IBS Execution Control Register (IbsOpCtl, |
---|
212 | 212 | * MSRC001_1033) is used to select either cycle or micro-ops counting |
---|
213 | 213 | * mode. |
---|
214 | | - * |
---|
215 | | - * The rip of IBS samples has skid 0. Thus, IBS supports precise |
---|
216 | | - * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the |
---|
217 | | - * rip is invalid when IBS was not able to record the rip correctly. |
---|
218 | | - * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then. |
---|
219 | | - * |
---|
220 | 214 | */ |
---|
221 | | -static int perf_ibs_precise_event(struct perf_event *event, u64 *config) |
---|
| 215 | +static int core_pmu_ibs_config(struct perf_event *event, u64 *config) |
---|
222 | 216 | { |
---|
223 | | - switch (event->attr.precise_ip) { |
---|
224 | | - case 0: |
---|
225 | | - return -ENOENT; |
---|
226 | | - case 1: |
---|
227 | | - case 2: |
---|
228 | | - break; |
---|
229 | | - default: |
---|
230 | | - return -EOPNOTSUPP; |
---|
231 | | - } |
---|
232 | | - |
---|
233 | 217 | switch (event->attr.type) { |
---|
234 | 218 | case PERF_TYPE_HARDWARE: |
---|
235 | 219 | switch (event->attr.config) { |
---|
.. | .. |
---|
255 | 239 | return -EOPNOTSUPP; |
---|
256 | 240 | } |
---|
257 | 241 | |
---|
| 242 | +/* |
---|
| 243 | + * The rip of IBS samples has skid 0. Thus, IBS supports precise |
---|
| 244 | + * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the |
---|
| 245 | + * rip is invalid when IBS was not able to record the rip correctly. |
---|
| 246 | + * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then. |
---|
| 247 | + */ |
---|
| 248 | +int forward_event_to_ibs(struct perf_event *event) |
---|
| 249 | +{ |
---|
| 250 | + u64 config = 0; |
---|
| 251 | + |
---|
| 252 | + if (!event->attr.precise_ip || event->attr.precise_ip > 2) |
---|
| 253 | + return -EOPNOTSUPP; |
---|
| 254 | + |
---|
| 255 | + if (!core_pmu_ibs_config(event, &config)) { |
---|
| 256 | + event->attr.type = perf_ibs_op.pmu.type; |
---|
| 257 | + event->attr.config = config; |
---|
| 258 | + } |
---|
| 259 | + return -ENOENT; |
---|
| 260 | +} |
---|
| 261 | + |
---|
258 | 262 | static int perf_ibs_init(struct perf_event *event) |
---|
259 | 263 | { |
---|
260 | 264 | struct hw_perf_event *hwc = &event->hw; |
---|
261 | 265 | struct perf_ibs *perf_ibs; |
---|
262 | 266 | u64 max_cnt, config; |
---|
263 | | - int ret; |
---|
264 | 267 | |
---|
265 | 268 | perf_ibs = get_ibs_pmu(event->attr.type); |
---|
266 | | - if (perf_ibs) { |
---|
267 | | - config = event->attr.config; |
---|
268 | | - } else { |
---|
269 | | - perf_ibs = &perf_ibs_op; |
---|
270 | | - ret = perf_ibs_precise_event(event, &config); |
---|
271 | | - if (ret) |
---|
272 | | - return ret; |
---|
273 | | - } |
---|
| 269 | + if (!perf_ibs) |
---|
| 270 | + return -ENOENT; |
---|
| 271 | + |
---|
| 272 | + config = event->attr.config; |
---|
274 | 273 | |
---|
275 | 274 | if (event->pmu != &perf_ibs->pmu) |
---|
276 | 275 | return -ENOENT; |
---|