diff options
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event_intel.c')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 95 |
1 files changed, 52 insertions, 43 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 977e7544738c..9c794ac87837 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifdef CONFIG_CPU_SUP_INTEL | 1 | #ifdef CONFIG_CPU_SUP_INTEL |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Intel PerfMon v3. Used on Core2 and later. | 4 | * Intel PerfMon, used on Core and later. |
5 | */ | 5 | */ |
6 | static const u64 intel_perfmon_event_map[] = | 6 | static const u64 intel_perfmon_event_map[] = |
7 | { | 7 | { |
@@ -27,8 +27,14 @@ static struct event_constraint intel_core_event_constraints[] = | |||
27 | 27 | ||
28 | static struct event_constraint intel_core2_event_constraints[] = | 28 | static struct event_constraint intel_core2_event_constraints[] = |
29 | { | 29 | { |
30 | FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | 30 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
31 | FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | 31 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
32 | /* | ||
33 | * Core2 has Fixed Counter 2 listed as CPU_CLK_UNHALTED.REF and event | ||
34 | * 0x013c as CPU_CLK_UNHALTED.BUS and specifies there is a fixed | ||
35 | * ratio between these counters. | ||
36 | */ | ||
37 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
32 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | 38 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ |
33 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | 39 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ |
34 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | 40 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ |
@@ -37,14 +43,16 @@ static struct event_constraint intel_core2_event_constraints[] = | |||
37 | INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */ | 43 | INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */ |
38 | INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ | 44 | INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ |
39 | INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */ | 45 | INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */ |
46 | INTEL_EVENT_CONSTRAINT(0xc9, 0x1), /* ITLB_MISS_RETIRED (T30-9) */ | ||
40 | INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */ | 47 | INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */ |
41 | EVENT_CONSTRAINT_END | 48 | EVENT_CONSTRAINT_END |
42 | }; | 49 | }; |
43 | 50 | ||
44 | static struct event_constraint intel_nehalem_event_constraints[] = | 51 | static struct event_constraint intel_nehalem_event_constraints[] = |
45 | { | 52 | { |
46 | FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | 53 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
47 | FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | 54 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
55 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
48 | INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */ | 56 | INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */ |
49 | INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ | 57 | INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ |
50 | INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ | 58 | INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ |
@@ -58,8 +66,9 @@ static struct event_constraint intel_nehalem_event_constraints[] = | |||
58 | 66 | ||
59 | static struct event_constraint intel_westmere_event_constraints[] = | 67 | static struct event_constraint intel_westmere_event_constraints[] = |
60 | { | 68 | { |
61 | FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | 69 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
62 | FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | 70 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
71 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
63 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | 72 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ |
64 | INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ | 73 | INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ |
65 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ | 74 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ |
@@ -68,8 +77,9 @@ static struct event_constraint intel_westmere_event_constraints[] = | |||
68 | 77 | ||
69 | static struct event_constraint intel_gen_event_constraints[] = | 78 | static struct event_constraint intel_gen_event_constraints[] = |
70 | { | 79 | { |
71 | FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ | 80 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
72 | FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ | 81 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
82 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
73 | EVENT_CONSTRAINT_END | 83 | EVENT_CONSTRAINT_END |
74 | }; | 84 | }; |
75 | 85 | ||
@@ -538,9 +548,9 @@ static inline void intel_pmu_ack_status(u64 ack) | |||
538 | } | 548 | } |
539 | 549 | ||
540 | static inline void | 550 | static inline void |
541 | intel_pmu_disable_fixed(struct hw_perf_event *hwc, int __idx) | 551 | intel_pmu_disable_fixed(struct hw_perf_event *hwc) |
542 | { | 552 | { |
543 | int idx = __idx - X86_PMC_IDX_FIXED; | 553 | int idx = hwc->idx - X86_PMC_IDX_FIXED; |
544 | u64 ctrl_val, mask; | 554 | u64 ctrl_val, mask; |
545 | 555 | ||
546 | mask = 0xfULL << (idx * 4); | 556 | mask = 0xfULL << (idx * 4); |
@@ -580,10 +590,9 @@ static void intel_pmu_drain_bts_buffer(void) | |||
580 | 590 | ||
581 | ds->bts_index = ds->bts_buffer_base; | 591 | ds->bts_index = ds->bts_buffer_base; |
582 | 592 | ||
593 | perf_sample_data_init(&data, 0); | ||
583 | 594 | ||
584 | data.period = event->hw.last_period; | 595 | data.period = event->hw.last_period; |
585 | data.addr = 0; | ||
586 | data.raw = NULL; | ||
587 | regs.ip = 0; | 596 | regs.ip = 0; |
588 | 597 | ||
589 | /* | 598 | /* |
@@ -612,26 +621,28 @@ static void intel_pmu_drain_bts_buffer(void) | |||
612 | } | 621 | } |
613 | 622 | ||
614 | static inline void | 623 | static inline void |
615 | intel_pmu_disable_event(struct hw_perf_event *hwc, int idx) | 624 | intel_pmu_disable_event(struct perf_event *event) |
616 | { | 625 | { |
617 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | 626 | struct hw_perf_event *hwc = &event->hw; |
627 | |||
628 | if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) { | ||
618 | intel_pmu_disable_bts(); | 629 | intel_pmu_disable_bts(); |
619 | intel_pmu_drain_bts_buffer(); | 630 | intel_pmu_drain_bts_buffer(); |
620 | return; | 631 | return; |
621 | } | 632 | } |
622 | 633 | ||
623 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 634 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
624 | intel_pmu_disable_fixed(hwc, idx); | 635 | intel_pmu_disable_fixed(hwc); |
625 | return; | 636 | return; |
626 | } | 637 | } |
627 | 638 | ||
628 | x86_pmu_disable_event(hwc, idx); | 639 | x86_pmu_disable_event(event); |
629 | } | 640 | } |
630 | 641 | ||
631 | static inline void | 642 | static inline void |
632 | intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx) | 643 | intel_pmu_enable_fixed(struct hw_perf_event *hwc) |
633 | { | 644 | { |
634 | int idx = __idx - X86_PMC_IDX_FIXED; | 645 | int idx = hwc->idx - X86_PMC_IDX_FIXED; |
635 | u64 ctrl_val, bits, mask; | 646 | u64 ctrl_val, bits, mask; |
636 | int err; | 647 | int err; |
637 | 648 | ||
@@ -661,9 +672,11 @@ intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx) | |||
661 | err = checking_wrmsrl(hwc->config_base, ctrl_val); | 672 | err = checking_wrmsrl(hwc->config_base, ctrl_val); |
662 | } | 673 | } |
663 | 674 | ||
664 | static void intel_pmu_enable_event(struct hw_perf_event *hwc, int idx) | 675 | static void intel_pmu_enable_event(struct perf_event *event) |
665 | { | 676 | { |
666 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | 677 | struct hw_perf_event *hwc = &event->hw; |
678 | |||
679 | if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) { | ||
667 | if (!__get_cpu_var(cpu_hw_events).enabled) | 680 | if (!__get_cpu_var(cpu_hw_events).enabled) |
668 | return; | 681 | return; |
669 | 682 | ||
@@ -672,11 +685,11 @@ static void intel_pmu_enable_event(struct hw_perf_event *hwc, int idx) | |||
672 | } | 685 | } |
673 | 686 | ||
674 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 687 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
675 | intel_pmu_enable_fixed(hwc, idx); | 688 | intel_pmu_enable_fixed(hwc); |
676 | return; | 689 | return; |
677 | } | 690 | } |
678 | 691 | ||
679 | __x86_pmu_enable_event(hwc, idx); | 692 | __x86_pmu_enable_event(hwc); |
680 | } | 693 | } |
681 | 694 | ||
682 | /* | 695 | /* |
@@ -685,14 +698,8 @@ static void intel_pmu_enable_event(struct hw_perf_event *hwc, int idx) | |||
685 | */ | 698 | */ |
686 | static int intel_pmu_save_and_restart(struct perf_event *event) | 699 | static int intel_pmu_save_and_restart(struct perf_event *event) |
687 | { | 700 | { |
688 | struct hw_perf_event *hwc = &event->hw; | 701 | x86_perf_event_update(event); |
689 | int idx = hwc->idx; | 702 | return x86_perf_event_set_period(event); |
690 | int ret; | ||
691 | |||
692 | x86_perf_event_update(event, hwc, idx); | ||
693 | ret = x86_perf_event_set_period(event, hwc, idx); | ||
694 | |||
695 | return ret; | ||
696 | } | 703 | } |
697 | 704 | ||
698 | static void intel_pmu_reset(void) | 705 | static void intel_pmu_reset(void) |
@@ -732,16 +739,15 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) | |||
732 | int bit, loops; | 739 | int bit, loops; |
733 | u64 ack, status; | 740 | u64 ack, status; |
734 | 741 | ||
735 | data.addr = 0; | 742 | perf_sample_data_init(&data, 0); |
736 | data.raw = NULL; | ||
737 | 743 | ||
738 | cpuc = &__get_cpu_var(cpu_hw_events); | 744 | cpuc = &__get_cpu_var(cpu_hw_events); |
739 | 745 | ||
740 | perf_disable(); | 746 | intel_pmu_disable_all(); |
741 | intel_pmu_drain_bts_buffer(); | 747 | intel_pmu_drain_bts_buffer(); |
742 | status = intel_pmu_get_status(); | 748 | status = intel_pmu_get_status(); |
743 | if (!status) { | 749 | if (!status) { |
744 | perf_enable(); | 750 | intel_pmu_enable_all(); |
745 | return 0; | 751 | return 0; |
746 | } | 752 | } |
747 | 753 | ||
@@ -751,8 +757,7 @@ again: | |||
751 | WARN_ONCE(1, "perfevents: irq loop stuck!\n"); | 757 | WARN_ONCE(1, "perfevents: irq loop stuck!\n"); |
752 | perf_event_print_debug(); | 758 | perf_event_print_debug(); |
753 | intel_pmu_reset(); | 759 | intel_pmu_reset(); |
754 | perf_enable(); | 760 | goto done; |
755 | return 1; | ||
756 | } | 761 | } |
757 | 762 | ||
758 | inc_irq_stat(apic_perf_irqs); | 763 | inc_irq_stat(apic_perf_irqs); |
@@ -760,7 +765,6 @@ again: | |||
760 | for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { | 765 | for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { |
761 | struct perf_event *event = cpuc->events[bit]; | 766 | struct perf_event *event = cpuc->events[bit]; |
762 | 767 | ||
763 | clear_bit(bit, (unsigned long *) &status); | ||
764 | if (!test_bit(bit, cpuc->active_mask)) | 768 | if (!test_bit(bit, cpuc->active_mask)) |
765 | continue; | 769 | continue; |
766 | 770 | ||
@@ -770,7 +774,7 @@ again: | |||
770 | data.period = event->hw.last_period; | 774 | data.period = event->hw.last_period; |
771 | 775 | ||
772 | if (perf_event_overflow(event, 1, &data, regs)) | 776 | if (perf_event_overflow(event, 1, &data, regs)) |
773 | intel_pmu_disable_event(&event->hw, bit); | 777 | x86_pmu_stop(event); |
774 | } | 778 | } |
775 | 779 | ||
776 | intel_pmu_ack_status(ack); | 780 | intel_pmu_ack_status(ack); |
@@ -782,8 +786,8 @@ again: | |||
782 | if (status) | 786 | if (status) |
783 | goto again; | 787 | goto again; |
784 | 788 | ||
785 | perf_enable(); | 789 | done: |
786 | 790 | intel_pmu_enable_all(); | |
787 | return 1; | 791 | return 1; |
788 | } | 792 | } |
789 | 793 | ||
@@ -862,7 +866,10 @@ static __initconst struct x86_pmu intel_pmu = { | |||
862 | .max_period = (1ULL << 31) - 1, | 866 | .max_period = (1ULL << 31) - 1, |
863 | .enable_bts = intel_pmu_enable_bts, | 867 | .enable_bts = intel_pmu_enable_bts, |
864 | .disable_bts = intel_pmu_disable_bts, | 868 | .disable_bts = intel_pmu_disable_bts, |
865 | .get_event_constraints = intel_get_event_constraints | 869 | .get_event_constraints = intel_get_event_constraints, |
870 | |||
871 | .cpu_starting = init_debug_store_on_cpu, | ||
872 | .cpu_dying = fini_debug_store_on_cpu, | ||
866 | }; | 873 | }; |
867 | 874 | ||
868 | static __init int intel_pmu_init(void) | 875 | static __init int intel_pmu_init(void) |
@@ -929,13 +936,14 @@ static __init int intel_pmu_init(void) | |||
929 | 936 | ||
930 | case 26: /* 45 nm nehalem, "Bloomfield" */ | 937 | case 26: /* 45 nm nehalem, "Bloomfield" */ |
931 | case 30: /* 45 nm nehalem, "Lynnfield" */ | 938 | case 30: /* 45 nm nehalem, "Lynnfield" */ |
939 | case 46: /* 45 nm nehalem-ex, "Beckton" */ | ||
932 | memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, | 940 | memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, |
933 | sizeof(hw_cache_event_ids)); | 941 | sizeof(hw_cache_event_ids)); |
934 | 942 | ||
935 | x86_pmu.event_constraints = intel_nehalem_event_constraints; | 943 | x86_pmu.event_constraints = intel_nehalem_event_constraints; |
936 | pr_cont("Nehalem/Corei7 events, "); | 944 | pr_cont("Nehalem/Corei7 events, "); |
937 | break; | 945 | break; |
938 | case 28: | 946 | case 28: /* Atom */ |
939 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, | 947 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, |
940 | sizeof(hw_cache_event_ids)); | 948 | sizeof(hw_cache_event_ids)); |
941 | 949 | ||
@@ -951,6 +959,7 @@ static __init int intel_pmu_init(void) | |||
951 | x86_pmu.event_constraints = intel_westmere_event_constraints; | 959 | x86_pmu.event_constraints = intel_westmere_event_constraints; |
952 | pr_cont("Westmere events, "); | 960 | pr_cont("Westmere events, "); |
953 | break; | 961 | break; |
962 | |||
954 | default: | 963 | default: |
955 | /* | 964 | /* |
956 | * default constraints for v2 and up | 965 | * default constraints for v2 and up |