hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/arch/x86/events/amd/ibs.c
....@@ -202,7 +202,7 @@
202202 }
203203
204204 /*
205
- * Use IBS for precise event sampling:
205
+ * core pmu config -> IBS config
206206 *
207207 * perf record -a -e cpu-cycles:p ... # use ibs op counting cycle count
208208 * perf record -a -e r076:p ... # same as -e cpu-cycles:p
....@@ -211,25 +211,9 @@
211211 * IbsOpCntCtl (bit 19) of IBS Execution Control Register (IbsOpCtl,
212212 * MSRC001_1033) is used to select either cycle or micro-ops counting
213213 * 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
- *
220214 */
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)
222216 {
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
-
233217 switch (event->attr.type) {
234218 case PERF_TYPE_HARDWARE:
235219 switch (event->attr.config) {
....@@ -255,22 +239,37 @@
255239 return -EOPNOTSUPP;
256240 }
257241
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
+
258262 static int perf_ibs_init(struct perf_event *event)
259263 {
260264 struct hw_perf_event *hwc = &event->hw;
261265 struct perf_ibs *perf_ibs;
262266 u64 max_cnt, config;
263
- int ret;
264267
265268 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;
274273
275274 if (event->pmu != &perf_ibs->pmu)
276275 return -ENOENT;