forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/arch/x86/events/amd/ibs.c
....@@ -255,15 +255,6 @@
255255 return -EOPNOTSUPP;
256256 }
257257
258
-static const struct perf_event_attr ibs_notsupp = {
259
- .exclude_user = 1,
260
- .exclude_kernel = 1,
261
- .exclude_hv = 1,
262
- .exclude_idle = 1,
263
- .exclude_host = 1,
264
- .exclude_guest = 1,
265
-};
266
-
267258 static int perf_ibs_init(struct perf_event *event)
268259 {
269260 struct hw_perf_event *hwc = &event->hw;
....@@ -283,9 +274,6 @@
283274
284275 if (event->pmu != &perf_ibs->pmu)
285276 return -ENOENT;
286
-
287
- if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp))
288
- return -EINVAL;
289277
290278 if (config & ~perf_ibs->config_mask)
291279 return -EINVAL;
....@@ -324,6 +312,16 @@
324312 hwc->config_base = perf_ibs->msr;
325313 hwc->config = config;
326314
315
+ /*
316
+ * rip recorded by IbsOpRip will not be consistent with rsp and rbp
317
+ * recorded as part of interrupt regs. Thus we need to use rip from
318
+ * interrupt regs while unwinding call stack. Setting _EARLY flag
319
+ * makes sure we unwind call-stack before perf sample rip is set to
320
+ * IbsOpRip.
321
+ */
322
+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
323
+ event->attr.sample_type |= __PERF_SAMPLE_CALLCHAIN_EARLY;
324
+
327325 return 0;
328326 }
329327
....@@ -353,10 +351,13 @@
353351 * and the lower 7 bits of CurCnt are randomized.
354352 * Otherwise CurCnt has the full 27-bit current counter value.
355353 */
356
- if (config & IBS_OP_VAL)
354
+ if (config & IBS_OP_VAL) {
357355 count = (config & IBS_OP_MAX_CNT) << 4;
358
- else if (ibs_caps & IBS_CAPS_RDWROPCNT)
356
+ if (ibs_caps & IBS_CAPS_OPCNTEXT)
357
+ count += config & IBS_OP_MAX_CNT_EXT_MASK;
358
+ } else if (ibs_caps & IBS_CAPS_RDWROPCNT) {
359359 count = (config & IBS_OP_CUR_CNT) >> 32;
360
+ }
360361
361362 return count;
362363 }
....@@ -417,7 +418,7 @@
417418 struct hw_perf_event *hwc = &event->hw;
418419 struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
419420 struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
420
- u64 period;
421
+ u64 period, config = 0;
421422
422423 if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
423424 return;
....@@ -426,13 +427,19 @@
426427 hwc->state = 0;
427428
428429 perf_ibs_set_period(perf_ibs, hwc, &period);
430
+ if (perf_ibs == &perf_ibs_op && (ibs_caps & IBS_CAPS_OPCNTEXT)) {
431
+ config |= period & IBS_OP_MAX_CNT_EXT_MASK;
432
+ period &= ~IBS_OP_MAX_CNT_EXT_MASK;
433
+ }
434
+ config |= period >> 4;
435
+
429436 /*
430437 * Set STARTED before enabling the hardware, such that a subsequent NMI
431438 * must observe it.
432439 */
433440 set_bit(IBS_STARTED, pcpu->state);
434441 clear_bit(IBS_STOPPING, pcpu->state);
435
- perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
442
+ perf_ibs_enable_event(perf_ibs, hwc, config);
436443
437444 perf_event_update_userpage(event);
438445 }
....@@ -549,6 +556,7 @@
549556 .start = perf_ibs_start,
550557 .stop = perf_ibs_stop,
551558 .read = perf_ibs_read,
559
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
552560 },
553561 .msr = MSR_AMD64_IBSFETCHCTL,
554562 .config_mask = IBS_FETCH_CONFIG_MASK,
....@@ -573,6 +581,7 @@
573581 .start = perf_ibs_start,
574582 .stop = perf_ibs_stop,
575583 .read = perf_ibs_read,
584
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
576585 },
577586 .msr = MSR_AMD64_IBSOPCTL,
578587 .config_mask = IBS_OP_CONFIG_MASK,
....@@ -599,7 +608,7 @@
599608 struct perf_ibs_data ibs_data;
600609 int offset, size, check_rip, offset_max, throttle = 0;
601610 unsigned int msr;
602
- u64 *buf, *config, period;
611
+ u64 *buf, *config, period, new_config = 0;
603612
604613 if (!test_bit(IBS_STARTED, pcpu->state)) {
605614 fail:
....@@ -693,18 +702,30 @@
693702 data.raw = &raw;
694703 }
695704
705
+ /*
706
+ * rip recorded by IbsOpRip will not be consistent with rsp and rbp
707
+ * recorded as part of interrupt regs. Thus we need to use rip from
708
+ * interrupt regs while unwinding call stack.
709
+ */
710
+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
711
+ data.callchain = perf_callchain(event, iregs);
712
+
696713 throttle = perf_event_overflow(event, &data, &regs);
697714 out:
698715 if (throttle) {
699716 perf_ibs_stop(event, 0);
700717 } else {
701
- period >>= 4;
718
+ if (perf_ibs == &perf_ibs_op) {
719
+ if (ibs_caps & IBS_CAPS_OPCNTEXT) {
720
+ new_config = period & IBS_OP_MAX_CNT_EXT_MASK;
721
+ period &= ~IBS_OP_MAX_CNT_EXT_MASK;
722
+ }
723
+ if ((ibs_caps & IBS_CAPS_RDWROPCNT) && (*config & IBS_OP_CNT_CTL))
724
+ new_config |= *config & IBS_OP_CUR_CNT_RAND;
725
+ }
726
+ new_config |= period >> 4;
702727
703
- if ((ibs_caps & IBS_CAPS_RDWROPCNT) &&
704
- (*config & IBS_OP_CNT_CTL))
705
- period |= *config & IBS_OP_CUR_CNT_RAND;
706
-
707
- perf_ibs_enable_event(perf_ibs, hwc, period);
728
+ perf_ibs_enable_event(perf_ibs, hwc, new_config);
708729 }
709730
710731 perf_event_update_userpage(event);
....@@ -761,9 +782,10 @@
761782 return ret;
762783 }
763784
764
-static __init void perf_event_ibs_init(void)
785
+static __init int perf_event_ibs_init(void)
765786 {
766787 struct attribute **attr = ibs_op_format_attrs;
788
+ int ret;
767789
768790 /*
769791 * Some chips fail to reset the fetch count when it is written; instead
....@@ -775,21 +797,50 @@
775797 if (boot_cpu_data.x86 == 0x19 && boot_cpu_data.x86_model < 0x10)
776798 perf_ibs_fetch.fetch_ignore_if_zero_rip = 1;
777799
778
- perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
800
+ ret = perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
801
+ if (ret)
802
+ return ret;
779803
780804 if (ibs_caps & IBS_CAPS_OPCNT) {
781805 perf_ibs_op.config_mask |= IBS_OP_CNT_CTL;
782806 *attr++ = &format_attr_cnt_ctl.attr;
783807 }
784
- perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");
785808
786
- register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs");
809
+ if (ibs_caps & IBS_CAPS_OPCNTEXT) {
810
+ perf_ibs_op.max_period |= IBS_OP_MAX_CNT_EXT_MASK;
811
+ perf_ibs_op.config_mask |= IBS_OP_MAX_CNT_EXT_MASK;
812
+ perf_ibs_op.cnt_mask |= IBS_OP_MAX_CNT_EXT_MASK;
813
+ }
814
+
815
+ ret = perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");
816
+ if (ret)
817
+ goto err_op;
818
+
819
+ ret = register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs");
820
+ if (ret)
821
+ goto err_nmi;
822
+
787823 pr_info("perf: AMD IBS detected (0x%08x)\n", ibs_caps);
824
+ return 0;
825
+
826
+err_nmi:
827
+ perf_pmu_unregister(&perf_ibs_op.pmu);
828
+ free_percpu(perf_ibs_op.pcpu);
829
+ perf_ibs_op.pcpu = NULL;
830
+err_op:
831
+ perf_pmu_unregister(&perf_ibs_fetch.pmu);
832
+ free_percpu(perf_ibs_fetch.pcpu);
833
+ perf_ibs_fetch.pcpu = NULL;
834
+
835
+ return ret;
788836 }
789837
790838 #else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */
791839
792
-static __init void perf_event_ibs_init(void) { }
840
+static __init int perf_event_ibs_init(void)
841
+{
842
+ return 0;
843
+}
793844
794845 #endif
795846
....@@ -1059,9 +1110,7 @@
10591110 x86_pmu_amd_ibs_starting_cpu,
10601111 x86_pmu_amd_ibs_dying_cpu);
10611112
1062
- perf_event_ibs_init();
1063
-
1064
- return 0;
1113
+ return perf_event_ibs_init();
10651114 }
10661115
10671116 /* Since we need the pci subsystem to init ibs we can't do this earlier: */