.. | .. |
---|
255 | 255 | return -EOPNOTSUPP; |
---|
256 | 256 | } |
---|
257 | 257 | |
---|
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 | | - |
---|
267 | 258 | static int perf_ibs_init(struct perf_event *event) |
---|
268 | 259 | { |
---|
269 | 260 | struct hw_perf_event *hwc = &event->hw; |
---|
.. | .. |
---|
283 | 274 | |
---|
284 | 275 | if (event->pmu != &perf_ibs->pmu) |
---|
285 | 276 | return -ENOENT; |
---|
286 | | - |
---|
287 | | - if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp)) |
---|
288 | | - return -EINVAL; |
---|
289 | 277 | |
---|
290 | 278 | if (config & ~perf_ibs->config_mask) |
---|
291 | 279 | return -EINVAL; |
---|
.. | .. |
---|
324 | 312 | hwc->config_base = perf_ibs->msr; |
---|
325 | 313 | hwc->config = config; |
---|
326 | 314 | |
---|
| 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 | + |
---|
327 | 325 | return 0; |
---|
328 | 326 | } |
---|
329 | 327 | |
---|
.. | .. |
---|
353 | 351 | * and the lower 7 bits of CurCnt are randomized. |
---|
354 | 352 | * Otherwise CurCnt has the full 27-bit current counter value. |
---|
355 | 353 | */ |
---|
356 | | - if (config & IBS_OP_VAL) |
---|
| 354 | + if (config & IBS_OP_VAL) { |
---|
357 | 355 | 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) { |
---|
359 | 359 | count = (config & IBS_OP_CUR_CNT) >> 32; |
---|
| 360 | + } |
---|
360 | 361 | |
---|
361 | 362 | return count; |
---|
362 | 363 | } |
---|
.. | .. |
---|
417 | 418 | struct hw_perf_event *hwc = &event->hw; |
---|
418 | 419 | struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu); |
---|
419 | 420 | struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu); |
---|
420 | | - u64 period; |
---|
| 421 | + u64 period, config = 0; |
---|
421 | 422 | |
---|
422 | 423 | if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) |
---|
423 | 424 | return; |
---|
.. | .. |
---|
426 | 427 | hwc->state = 0; |
---|
427 | 428 | |
---|
428 | 429 | 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 | + |
---|
429 | 436 | /* |
---|
430 | 437 | * Set STARTED before enabling the hardware, such that a subsequent NMI |
---|
431 | 438 | * must observe it. |
---|
432 | 439 | */ |
---|
433 | 440 | set_bit(IBS_STARTED, pcpu->state); |
---|
434 | 441 | 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); |
---|
436 | 443 | |
---|
437 | 444 | perf_event_update_userpage(event); |
---|
438 | 445 | } |
---|
.. | .. |
---|
549 | 556 | .start = perf_ibs_start, |
---|
550 | 557 | .stop = perf_ibs_stop, |
---|
551 | 558 | .read = perf_ibs_read, |
---|
| 559 | + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, |
---|
552 | 560 | }, |
---|
553 | 561 | .msr = MSR_AMD64_IBSFETCHCTL, |
---|
554 | 562 | .config_mask = IBS_FETCH_CONFIG_MASK, |
---|
.. | .. |
---|
573 | 581 | .start = perf_ibs_start, |
---|
574 | 582 | .stop = perf_ibs_stop, |
---|
575 | 583 | .read = perf_ibs_read, |
---|
| 584 | + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, |
---|
576 | 585 | }, |
---|
577 | 586 | .msr = MSR_AMD64_IBSOPCTL, |
---|
578 | 587 | .config_mask = IBS_OP_CONFIG_MASK, |
---|
.. | .. |
---|
599 | 608 | struct perf_ibs_data ibs_data; |
---|
600 | 609 | int offset, size, check_rip, offset_max, throttle = 0; |
---|
601 | 610 | unsigned int msr; |
---|
602 | | - u64 *buf, *config, period; |
---|
| 611 | + u64 *buf, *config, period, new_config = 0; |
---|
603 | 612 | |
---|
604 | 613 | if (!test_bit(IBS_STARTED, pcpu->state)) { |
---|
605 | 614 | fail: |
---|
.. | .. |
---|
693 | 702 | data.raw = &raw; |
---|
694 | 703 | } |
---|
695 | 704 | |
---|
| 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 | + |
---|
696 | 713 | throttle = perf_event_overflow(event, &data, ®s); |
---|
697 | 714 | out: |
---|
698 | 715 | if (throttle) { |
---|
699 | 716 | perf_ibs_stop(event, 0); |
---|
700 | 717 | } 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; |
---|
702 | 727 | |
---|
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); |
---|
708 | 729 | } |
---|
709 | 730 | |
---|
710 | 731 | perf_event_update_userpage(event); |
---|
.. | .. |
---|
761 | 782 | return ret; |
---|
762 | 783 | } |
---|
763 | 784 | |
---|
764 | | -static __init void perf_event_ibs_init(void) |
---|
| 785 | +static __init int perf_event_ibs_init(void) |
---|
765 | 786 | { |
---|
766 | 787 | struct attribute **attr = ibs_op_format_attrs; |
---|
| 788 | + int ret; |
---|
767 | 789 | |
---|
768 | 790 | /* |
---|
769 | 791 | * Some chips fail to reset the fetch count when it is written; instead |
---|
.. | .. |
---|
775 | 797 | if (boot_cpu_data.x86 == 0x19 && boot_cpu_data.x86_model < 0x10) |
---|
776 | 798 | perf_ibs_fetch.fetch_ignore_if_zero_rip = 1; |
---|
777 | 799 | |
---|
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; |
---|
779 | 803 | |
---|
780 | 804 | if (ibs_caps & IBS_CAPS_OPCNT) { |
---|
781 | 805 | perf_ibs_op.config_mask |= IBS_OP_CNT_CTL; |
---|
782 | 806 | *attr++ = &format_attr_cnt_ctl.attr; |
---|
783 | 807 | } |
---|
784 | | - perf_ibs_pmu_init(&perf_ibs_op, "ibs_op"); |
---|
785 | 808 | |
---|
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 | + |
---|
787 | 823 | 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; |
---|
788 | 836 | } |
---|
789 | 837 | |
---|
790 | 838 | #else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */ |
---|
791 | 839 | |
---|
792 | | -static __init void perf_event_ibs_init(void) { } |
---|
| 840 | +static __init int perf_event_ibs_init(void) |
---|
| 841 | +{ |
---|
| 842 | + return 0; |
---|
| 843 | +} |
---|
793 | 844 | |
---|
794 | 845 | #endif |
---|
795 | 846 | |
---|
.. | .. |
---|
1059 | 1110 | x86_pmu_amd_ibs_starting_cpu, |
---|
1060 | 1111 | x86_pmu_amd_ibs_dying_cpu); |
---|
1061 | 1112 | |
---|
1062 | | - perf_event_ibs_init(); |
---|
1063 | | - |
---|
1064 | | - return 0; |
---|
| 1113 | + return perf_event_ibs_init(); |
---|
1065 | 1114 | } |
---|
1066 | 1115 | |
---|
1067 | 1116 | /* Since we need the pci subsystem to init ibs we can't do this earlier: */ |
---|