diff options
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event.c')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 183 |
1 files changed, 99 insertions, 84 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 42aafd11e170..60398a0d947c 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -133,8 +133,8 @@ struct x86_pmu { | |||
133 | int (*handle_irq)(struct pt_regs *); | 133 | int (*handle_irq)(struct pt_regs *); |
134 | void (*disable_all)(void); | 134 | void (*disable_all)(void); |
135 | void (*enable_all)(void); | 135 | void (*enable_all)(void); |
136 | void (*enable)(struct hw_perf_event *, int); | 136 | void (*enable)(struct perf_event *); |
137 | void (*disable)(struct hw_perf_event *, int); | 137 | void (*disable)(struct perf_event *); |
138 | unsigned eventsel; | 138 | unsigned eventsel; |
139 | unsigned perfctr; | 139 | unsigned perfctr; |
140 | u64 (*event_map)(int); | 140 | u64 (*event_map)(int); |
@@ -157,6 +157,11 @@ struct x86_pmu { | |||
157 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, | 157 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, |
158 | struct perf_event *event); | 158 | struct perf_event *event); |
159 | struct event_constraint *event_constraints; | 159 | struct event_constraint *event_constraints; |
160 | |||
161 | void (*cpu_prepare)(int cpu); | ||
162 | void (*cpu_starting)(int cpu); | ||
163 | void (*cpu_dying)(int cpu); | ||
164 | void (*cpu_dead)(int cpu); | ||
160 | }; | 165 | }; |
161 | 166 | ||
162 | static struct x86_pmu x86_pmu __read_mostly; | 167 | static struct x86_pmu x86_pmu __read_mostly; |
@@ -165,8 +170,7 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { | |||
165 | .enabled = 1, | 170 | .enabled = 1, |
166 | }; | 171 | }; |
167 | 172 | ||
168 | static int x86_perf_event_set_period(struct perf_event *event, | 173 | static int x86_perf_event_set_period(struct perf_event *event); |
169 | struct hw_perf_event *hwc, int idx); | ||
170 | 174 | ||
171 | /* | 175 | /* |
172 | * Generalized hw caching related hw_event table, filled | 176 | * Generalized hw caching related hw_event table, filled |
@@ -189,11 +193,12 @@ static u64 __read_mostly hw_cache_event_ids | |||
189 | * Returns the delta events processed. | 193 | * Returns the delta events processed. |
190 | */ | 194 | */ |
191 | static u64 | 195 | static u64 |
192 | x86_perf_event_update(struct perf_event *event, | 196 | x86_perf_event_update(struct perf_event *event) |
193 | struct hw_perf_event *hwc, int idx) | ||
194 | { | 197 | { |
198 | struct hw_perf_event *hwc = &event->hw; | ||
195 | int shift = 64 - x86_pmu.event_bits; | 199 | int shift = 64 - x86_pmu.event_bits; |
196 | u64 prev_raw_count, new_raw_count; | 200 | u64 prev_raw_count, new_raw_count; |
201 | int idx = hwc->idx; | ||
197 | s64 delta; | 202 | s64 delta; |
198 | 203 | ||
199 | if (idx == X86_PMC_IDX_FIXED_BTS) | 204 | if (idx == X86_PMC_IDX_FIXED_BTS) |
@@ -293,7 +298,7 @@ static inline bool bts_available(void) | |||
293 | return x86_pmu.enable_bts != NULL; | 298 | return x86_pmu.enable_bts != NULL; |
294 | } | 299 | } |
295 | 300 | ||
296 | static inline void init_debug_store_on_cpu(int cpu) | 301 | static void init_debug_store_on_cpu(int cpu) |
297 | { | 302 | { |
298 | struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; | 303 | struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; |
299 | 304 | ||
@@ -305,7 +310,7 @@ static inline void init_debug_store_on_cpu(int cpu) | |||
305 | (u32)((u64)(unsigned long)ds >> 32)); | 310 | (u32)((u64)(unsigned long)ds >> 32)); |
306 | } | 311 | } |
307 | 312 | ||
308 | static inline void fini_debug_store_on_cpu(int cpu) | 313 | static void fini_debug_store_on_cpu(int cpu) |
309 | { | 314 | { |
310 | if (!per_cpu(cpu_hw_events, cpu).ds) | 315 | if (!per_cpu(cpu_hw_events, cpu).ds) |
311 | return; | 316 | return; |
@@ -638,7 +643,7 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
638 | if (test_bit(hwc->idx, used_mask)) | 643 | if (test_bit(hwc->idx, used_mask)) |
639 | break; | 644 | break; |
640 | 645 | ||
641 | set_bit(hwc->idx, used_mask); | 646 | __set_bit(hwc->idx, used_mask); |
642 | if (assign) | 647 | if (assign) |
643 | assign[i] = hwc->idx; | 648 | assign[i] = hwc->idx; |
644 | } | 649 | } |
@@ -687,7 +692,7 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
687 | if (j == X86_PMC_IDX_MAX) | 692 | if (j == X86_PMC_IDX_MAX) |
688 | break; | 693 | break; |
689 | 694 | ||
690 | set_bit(j, used_mask); | 695 | __set_bit(j, used_mask); |
691 | 696 | ||
692 | if (assign) | 697 | if (assign) |
693 | assign[i] = j; | 698 | assign[i] = j; |
@@ -780,6 +785,7 @@ static inline int match_prev_assignment(struct hw_perf_event *hwc, | |||
780 | hwc->last_tag == cpuc->tags[i]; | 785 | hwc->last_tag == cpuc->tags[i]; |
781 | } | 786 | } |
782 | 787 | ||
788 | static int x86_pmu_start(struct perf_event *event); | ||
783 | static void x86_pmu_stop(struct perf_event *event); | 789 | static void x86_pmu_stop(struct perf_event *event); |
784 | 790 | ||
785 | void hw_perf_enable(void) | 791 | void hw_perf_enable(void) |
@@ -796,6 +802,7 @@ void hw_perf_enable(void) | |||
796 | return; | 802 | return; |
797 | 803 | ||
798 | if (cpuc->n_added) { | 804 | if (cpuc->n_added) { |
805 | int n_running = cpuc->n_events - cpuc->n_added; | ||
799 | /* | 806 | /* |
800 | * apply assignment obtained either from | 807 | * apply assignment obtained either from |
801 | * hw_perf_group_sched_in() or x86_pmu_enable() | 808 | * hw_perf_group_sched_in() or x86_pmu_enable() |
@@ -803,8 +810,7 @@ void hw_perf_enable(void) | |||
803 | * step1: save events moving to new counters | 810 | * step1: save events moving to new counters |
804 | * step2: reprogram moved events into new counters | 811 | * step2: reprogram moved events into new counters |
805 | */ | 812 | */ |
806 | for (i = 0; i < cpuc->n_events; i++) { | 813 | for (i = 0; i < n_running; i++) { |
807 | |||
808 | event = cpuc->event_list[i]; | 814 | event = cpuc->event_list[i]; |
809 | hwc = &event->hw; | 815 | hwc = &event->hw; |
810 | 816 | ||
@@ -819,29 +825,18 @@ void hw_perf_enable(void) | |||
819 | continue; | 825 | continue; |
820 | 826 | ||
821 | x86_pmu_stop(event); | 827 | x86_pmu_stop(event); |
822 | |||
823 | hwc->idx = -1; | ||
824 | } | 828 | } |
825 | 829 | ||
826 | for (i = 0; i < cpuc->n_events; i++) { | 830 | for (i = 0; i < cpuc->n_events; i++) { |
827 | |||
828 | event = cpuc->event_list[i]; | 831 | event = cpuc->event_list[i]; |
829 | hwc = &event->hw; | 832 | hwc = &event->hw; |
830 | 833 | ||
831 | if (hwc->idx == -1) { | 834 | if (!match_prev_assignment(hwc, cpuc, i)) |
832 | x86_assign_hw_event(event, cpuc, i); | 835 | x86_assign_hw_event(event, cpuc, i); |
833 | x86_perf_event_set_period(event, hwc, hwc->idx); | 836 | else if (i < n_running) |
834 | } | 837 | continue; |
835 | /* | ||
836 | * need to mark as active because x86_pmu_disable() | ||
837 | * clear active_mask and events[] yet it preserves | ||
838 | * idx | ||
839 | */ | ||
840 | set_bit(hwc->idx, cpuc->active_mask); | ||
841 | cpuc->events[hwc->idx] = event; | ||
842 | 838 | ||
843 | x86_pmu.enable(hwc, hwc->idx); | 839 | x86_pmu_start(event); |
844 | perf_event_update_userpage(event); | ||
845 | } | 840 | } |
846 | cpuc->n_added = 0; | 841 | cpuc->n_added = 0; |
847 | perf_events_lapic_init(); | 842 | perf_events_lapic_init(); |
@@ -853,15 +848,16 @@ void hw_perf_enable(void) | |||
853 | x86_pmu.enable_all(); | 848 | x86_pmu.enable_all(); |
854 | } | 849 | } |
855 | 850 | ||
856 | static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) | 851 | static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc) |
857 | { | 852 | { |
858 | (void)checking_wrmsrl(hwc->config_base + idx, | 853 | (void)checking_wrmsrl(hwc->config_base + hwc->idx, |
859 | hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE); | 854 | hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE); |
860 | } | 855 | } |
861 | 856 | ||
862 | static inline void x86_pmu_disable_event(struct hw_perf_event *hwc, int idx) | 857 | static inline void x86_pmu_disable_event(struct perf_event *event) |
863 | { | 858 | { |
864 | (void)checking_wrmsrl(hwc->config_base + idx, hwc->config); | 859 | struct hw_perf_event *hwc = &event->hw; |
860 | (void)checking_wrmsrl(hwc->config_base + hwc->idx, hwc->config); | ||
865 | } | 861 | } |
866 | 862 | ||
867 | static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); | 863 | static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); |
@@ -871,12 +867,12 @@ static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); | |||
871 | * To be called with the event disabled in hw: | 867 | * To be called with the event disabled in hw: |
872 | */ | 868 | */ |
873 | static int | 869 | static int |
874 | x86_perf_event_set_period(struct perf_event *event, | 870 | x86_perf_event_set_period(struct perf_event *event) |
875 | struct hw_perf_event *hwc, int idx) | ||
876 | { | 871 | { |
872 | struct hw_perf_event *hwc = &event->hw; | ||
877 | s64 left = atomic64_read(&hwc->period_left); | 873 | s64 left = atomic64_read(&hwc->period_left); |
878 | s64 period = hwc->sample_period; | 874 | s64 period = hwc->sample_period; |
879 | int err, ret = 0; | 875 | int err, ret = 0, idx = hwc->idx; |
880 | 876 | ||
881 | if (idx == X86_PMC_IDX_FIXED_BTS) | 877 | if (idx == X86_PMC_IDX_FIXED_BTS) |
882 | return 0; | 878 | return 0; |
@@ -922,11 +918,11 @@ x86_perf_event_set_period(struct perf_event *event, | |||
922 | return ret; | 918 | return ret; |
923 | } | 919 | } |
924 | 920 | ||
925 | static void x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) | 921 | static void x86_pmu_enable_event(struct perf_event *event) |
926 | { | 922 | { |
927 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 923 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
928 | if (cpuc->enabled) | 924 | if (cpuc->enabled) |
929 | __x86_pmu_enable_event(hwc, idx); | 925 | __x86_pmu_enable_event(&event->hw); |
930 | } | 926 | } |
931 | 927 | ||
932 | /* | 928 | /* |
@@ -962,34 +958,32 @@ static int x86_pmu_enable(struct perf_event *event) | |||
962 | memcpy(cpuc->assign, assign, n*sizeof(int)); | 958 | memcpy(cpuc->assign, assign, n*sizeof(int)); |
963 | 959 | ||
964 | cpuc->n_events = n; | 960 | cpuc->n_events = n; |
965 | cpuc->n_added = n - n0; | 961 | cpuc->n_added += n - n0; |
966 | 962 | ||
967 | return 0; | 963 | return 0; |
968 | } | 964 | } |
969 | 965 | ||
970 | static int x86_pmu_start(struct perf_event *event) | 966 | static int x86_pmu_start(struct perf_event *event) |
971 | { | 967 | { |
972 | struct hw_perf_event *hwc = &event->hw; | 968 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
969 | int idx = event->hw.idx; | ||
973 | 970 | ||
974 | if (hwc->idx == -1) | 971 | if (idx == -1) |
975 | return -EAGAIN; | 972 | return -EAGAIN; |
976 | 973 | ||
977 | x86_perf_event_set_period(event, hwc, hwc->idx); | 974 | x86_perf_event_set_period(event); |
978 | x86_pmu.enable(hwc, hwc->idx); | 975 | cpuc->events[idx] = event; |
976 | __set_bit(idx, cpuc->active_mask); | ||
977 | x86_pmu.enable(event); | ||
978 | perf_event_update_userpage(event); | ||
979 | 979 | ||
980 | return 0; | 980 | return 0; |
981 | } | 981 | } |
982 | 982 | ||
983 | static void x86_pmu_unthrottle(struct perf_event *event) | 983 | static void x86_pmu_unthrottle(struct perf_event *event) |
984 | { | 984 | { |
985 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 985 | int ret = x86_pmu_start(event); |
986 | struct hw_perf_event *hwc = &event->hw; | 986 | WARN_ON_ONCE(ret); |
987 | |||
988 | if (WARN_ON_ONCE(hwc->idx >= X86_PMC_IDX_MAX || | ||
989 | cpuc->events[hwc->idx] != event)) | ||
990 | return; | ||
991 | |||
992 | x86_pmu.enable(hwc, hwc->idx); | ||
993 | } | 987 | } |
994 | 988 | ||
995 | void perf_event_print_debug(void) | 989 | void perf_event_print_debug(void) |
@@ -1049,18 +1043,16 @@ static void x86_pmu_stop(struct perf_event *event) | |||
1049 | struct hw_perf_event *hwc = &event->hw; | 1043 | struct hw_perf_event *hwc = &event->hw; |
1050 | int idx = hwc->idx; | 1044 | int idx = hwc->idx; |
1051 | 1045 | ||
1052 | /* | 1046 | if (!__test_and_clear_bit(idx, cpuc->active_mask)) |
1053 | * Must be done before we disable, otherwise the nmi handler | 1047 | return; |
1054 | * could reenable again: | 1048 | |
1055 | */ | 1049 | x86_pmu.disable(event); |
1056 | clear_bit(idx, cpuc->active_mask); | ||
1057 | x86_pmu.disable(hwc, idx); | ||
1058 | 1050 | ||
1059 | /* | 1051 | /* |
1060 | * Drain the remaining delta count out of a event | 1052 | * Drain the remaining delta count out of a event |
1061 | * that we are disabling: | 1053 | * that we are disabling: |
1062 | */ | 1054 | */ |
1063 | x86_perf_event_update(event, hwc, idx); | 1055 | x86_perf_event_update(event); |
1064 | 1056 | ||
1065 | cpuc->events[idx] = NULL; | 1057 | cpuc->events[idx] = NULL; |
1066 | } | 1058 | } |
@@ -1108,7 +1100,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) | |||
1108 | event = cpuc->events[idx]; | 1100 | event = cpuc->events[idx]; |
1109 | hwc = &event->hw; | 1101 | hwc = &event->hw; |
1110 | 1102 | ||
1111 | val = x86_perf_event_update(event, hwc, idx); | 1103 | val = x86_perf_event_update(event); |
1112 | if (val & (1ULL << (x86_pmu.event_bits - 1))) | 1104 | if (val & (1ULL << (x86_pmu.event_bits - 1))) |
1113 | continue; | 1105 | continue; |
1114 | 1106 | ||
@@ -1118,11 +1110,11 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) | |||
1118 | handled = 1; | 1110 | handled = 1; |
1119 | data.period = event->hw.last_period; | 1111 | data.period = event->hw.last_period; |
1120 | 1112 | ||
1121 | if (!x86_perf_event_set_period(event, hwc, idx)) | 1113 | if (!x86_perf_event_set_period(event)) |
1122 | continue; | 1114 | continue; |
1123 | 1115 | ||
1124 | if (perf_event_overflow(event, 1, &data, regs)) | 1116 | if (perf_event_overflow(event, 1, &data, regs)) |
1125 | x86_pmu.disable(hwc, idx); | 1117 | x86_pmu_stop(event); |
1126 | } | 1118 | } |
1127 | 1119 | ||
1128 | if (handled) | 1120 | if (handled) |
@@ -1309,7 +1301,7 @@ int hw_perf_group_sched_in(struct perf_event *leader, | |||
1309 | memcpy(cpuc->assign, assign, n0*sizeof(int)); | 1301 | memcpy(cpuc->assign, assign, n0*sizeof(int)); |
1310 | 1302 | ||
1311 | cpuc->n_events = n0; | 1303 | cpuc->n_events = n0; |
1312 | cpuc->n_added = n1; | 1304 | cpuc->n_added += n1; |
1313 | ctx->nr_active += n1; | 1305 | ctx->nr_active += n1; |
1314 | 1306 | ||
1315 | /* | 1307 | /* |
@@ -1337,6 +1329,39 @@ undo: | |||
1337 | #include "perf_event_p6.c" | 1329 | #include "perf_event_p6.c" |
1338 | #include "perf_event_intel.c" | 1330 | #include "perf_event_intel.c" |
1339 | 1331 | ||
1332 | static int __cpuinit | ||
1333 | x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) | ||
1334 | { | ||
1335 | unsigned int cpu = (long)hcpu; | ||
1336 | |||
1337 | switch (action & ~CPU_TASKS_FROZEN) { | ||
1338 | case CPU_UP_PREPARE: | ||
1339 | if (x86_pmu.cpu_prepare) | ||
1340 | x86_pmu.cpu_prepare(cpu); | ||
1341 | break; | ||
1342 | |||
1343 | case CPU_STARTING: | ||
1344 | if (x86_pmu.cpu_starting) | ||
1345 | x86_pmu.cpu_starting(cpu); | ||
1346 | break; | ||
1347 | |||
1348 | case CPU_DYING: | ||
1349 | if (x86_pmu.cpu_dying) | ||
1350 | x86_pmu.cpu_dying(cpu); | ||
1351 | break; | ||
1352 | |||
1353 | case CPU_DEAD: | ||
1354 | if (x86_pmu.cpu_dead) | ||
1355 | x86_pmu.cpu_dead(cpu); | ||
1356 | break; | ||
1357 | |||
1358 | default: | ||
1359 | break; | ||
1360 | } | ||
1361 | |||
1362 | return NOTIFY_OK; | ||
1363 | } | ||
1364 | |||
1340 | static void __init pmu_check_apic(void) | 1365 | static void __init pmu_check_apic(void) |
1341 | { | 1366 | { |
1342 | if (cpu_has_apic) | 1367 | if (cpu_has_apic) |
@@ -1415,11 +1440,13 @@ void __init init_hw_perf_events(void) | |||
1415 | pr_info("... max period: %016Lx\n", x86_pmu.max_period); | 1440 | pr_info("... max period: %016Lx\n", x86_pmu.max_period); |
1416 | pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); | 1441 | pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); |
1417 | pr_info("... event mask: %016Lx\n", perf_event_mask); | 1442 | pr_info("... event mask: %016Lx\n", perf_event_mask); |
1443 | |||
1444 | perf_cpu_notifier(x86_pmu_notifier); | ||
1418 | } | 1445 | } |
1419 | 1446 | ||
1420 | static inline void x86_pmu_read(struct perf_event *event) | 1447 | static inline void x86_pmu_read(struct perf_event *event) |
1421 | { | 1448 | { |
1422 | x86_perf_event_update(event, &event->hw, event->hw.idx); | 1449 | x86_perf_event_update(event); |
1423 | } | 1450 | } |
1424 | 1451 | ||
1425 | static const struct pmu pmu = { | 1452 | static const struct pmu pmu = { |
@@ -1675,28 +1702,16 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
1675 | return entry; | 1702 | return entry; |
1676 | } | 1703 | } |
1677 | 1704 | ||
1678 | void hw_perf_event_setup_online(int cpu) | 1705 | #ifdef CONFIG_EVENT_TRACING |
1706 | void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) | ||
1679 | { | 1707 | { |
1680 | init_debug_store_on_cpu(cpu); | 1708 | regs->ip = ip; |
1681 | 1709 | /* | |
1682 | switch (boot_cpu_data.x86_vendor) { | 1710 | * perf_arch_fetch_caller_regs adds another call, we need to increment |
1683 | case X86_VENDOR_AMD: | 1711 | * the skip level |
1684 | amd_pmu_cpu_online(cpu); | 1712 | */ |
1685 | break; | 1713 | regs->bp = rewind_frame_pointer(skip + 1); |
1686 | default: | 1714 | regs->cs = __KERNEL_CS; |
1687 | return; | 1715 | local_save_flags(regs->flags); |
1688 | } | ||
1689 | } | ||
1690 | |||
1691 | void hw_perf_event_setup_offline(int cpu) | ||
1692 | { | ||
1693 | init_debug_store_on_cpu(cpu); | ||
1694 | |||
1695 | switch (boot_cpu_data.x86_vendor) { | ||
1696 | case X86_VENDOR_AMD: | ||
1697 | amd_pmu_cpu_offline(cpu); | ||
1698 | break; | ||
1699 | default: | ||
1700 | return; | ||
1701 | } | ||
1702 | } | 1716 | } |
1717 | #endif | ||