diff options
author | Markus Metzger <markus.t.metzger@intel.com> | 2009-07-21 09:56:48 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-08-09 07:04:14 -0400 |
commit | 30dd568c912602b7dbd609a45d053e01b13422bb (patch) | |
tree | 96e970d91b3ef06301ca0f03bc4b1a0068b06122 | |
parent | 183f3b0887083d36c8a25cd5e3518906415d1889 (diff) |
x86, perf_counter, bts: Add BTS support to perfcounters
Implement a performance counter with:
attr.type = PERF_TYPE_HARDWARE
attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS
attr.sample_period = 1
Using branch trace store (BTS) on x86 hardware, if available.
The from and to address for each branch can be sampled using:
PERF_SAMPLE_IP for the from address
PERF_SAMPLE_ADDR for the to address
[ v2: address review feedback, fix bugs ]
Signed-off-by: Markus Metzger <markus.t.metzger@intel.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/include/asm/perf_counter.h | 10 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_counter.c | 325 | ||||
-rw-r--r-- | include/linux/perf_counter.h | 2 | ||||
-rw-r--r-- | kernel/perf_counter.c | 10 |
4 files changed, 340 insertions, 7 deletions
diff --git a/arch/x86/include/asm/perf_counter.h b/arch/x86/include/asm/perf_counter.h index fa64e401589d..e7b7c938ae27 100644 --- a/arch/x86/include/asm/perf_counter.h +++ b/arch/x86/include/asm/perf_counter.h | |||
@@ -84,6 +84,16 @@ union cpuid10_edx { | |||
84 | #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b | 84 | #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b |
85 | #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) | 85 | #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) |
86 | 86 | ||
87 | /* | ||
88 | * We model BTS tracing as another fixed-mode PMC. | ||
89 | * | ||
90 | * We choose a value in the middle of the fixed counter range, since lower | ||
91 | * values are used by actual fixed counters and higher values are used | ||
92 | * to indicate other overflow conditions in the PERF_GLOBAL_STATUS msr. | ||
93 | */ | ||
94 | #define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16) | ||
95 | |||
96 | |||
87 | #ifdef CONFIG_PERF_COUNTERS | 97 | #ifdef CONFIG_PERF_COUNTERS |
88 | extern void init_hw_perf_counters(void); | 98 | extern void init_hw_perf_counters(void); |
89 | extern void perf_counters_lapic_init(void); | 99 | extern void perf_counters_lapic_init(void); |
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index a7aa8f900954..b237c181aa41 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
@@ -6,6 +6,7 @@ | |||
6 | * Copyright (C) 2009 Jaswinder Singh Rajput | 6 | * Copyright (C) 2009 Jaswinder Singh Rajput |
7 | * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter | 7 | * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter |
8 | * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> | 8 | * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> |
9 | * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com> | ||
9 | * | 10 | * |
10 | * For licencing details see kernel-base/COPYING | 11 | * For licencing details see kernel-base/COPYING |
11 | */ | 12 | */ |
@@ -20,6 +21,7 @@ | |||
20 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
21 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
22 | #include <linux/highmem.h> | 23 | #include <linux/highmem.h> |
24 | #include <linux/cpu.h> | ||
23 | 25 | ||
24 | #include <asm/apic.h> | 26 | #include <asm/apic.h> |
25 | #include <asm/stacktrace.h> | 27 | #include <asm/stacktrace.h> |
@@ -27,12 +29,52 @@ | |||
27 | 29 | ||
28 | static u64 perf_counter_mask __read_mostly; | 30 | static u64 perf_counter_mask __read_mostly; |
29 | 31 | ||
32 | /* The maximal number of PEBS counters: */ | ||
33 | #define MAX_PEBS_COUNTERS 4 | ||
34 | |||
35 | /* The size of a BTS record in bytes: */ | ||
36 | #define BTS_RECORD_SIZE 24 | ||
37 | |||
38 | /* The size of a per-cpu BTS buffer in bytes: */ | ||
39 | #define BTS_BUFFER_SIZE (BTS_RECORD_SIZE * 1024) | ||
40 | |||
41 | /* The BTS overflow threshold in bytes from the end of the buffer: */ | ||
42 | #define BTS_OVFL_TH (BTS_RECORD_SIZE * 64) | ||
43 | |||
44 | |||
45 | /* | ||
46 | * Bits in the debugctlmsr controlling branch tracing. | ||
47 | */ | ||
48 | #define X86_DEBUGCTL_TR (1 << 6) | ||
49 | #define X86_DEBUGCTL_BTS (1 << 7) | ||
50 | #define X86_DEBUGCTL_BTINT (1 << 8) | ||
51 | #define X86_DEBUGCTL_BTS_OFF_OS (1 << 9) | ||
52 | #define X86_DEBUGCTL_BTS_OFF_USR (1 << 10) | ||
53 | |||
54 | /* | ||
55 | * A debug store configuration. | ||
56 | * | ||
57 | * We only support architectures that use 64bit fields. | ||
58 | */ | ||
59 | struct debug_store { | ||
60 | u64 bts_buffer_base; | ||
61 | u64 bts_index; | ||
62 | u64 bts_absolute_maximum; | ||
63 | u64 bts_interrupt_threshold; | ||
64 | u64 pebs_buffer_base; | ||
65 | u64 pebs_index; | ||
66 | u64 pebs_absolute_maximum; | ||
67 | u64 pebs_interrupt_threshold; | ||
68 | u64 pebs_counter_reset[MAX_PEBS_COUNTERS]; | ||
69 | }; | ||
70 | |||
30 | struct cpu_hw_counters { | 71 | struct cpu_hw_counters { |
31 | struct perf_counter *counters[X86_PMC_IDX_MAX]; | 72 | struct perf_counter *counters[X86_PMC_IDX_MAX]; |
32 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 73 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
33 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 74 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
34 | unsigned long interrupts; | 75 | unsigned long interrupts; |
35 | int enabled; | 76 | int enabled; |
77 | struct debug_store *ds; | ||
36 | }; | 78 | }; |
37 | 79 | ||
38 | /* | 80 | /* |
@@ -57,6 +99,8 @@ struct x86_pmu { | |||
57 | u64 counter_mask; | 99 | u64 counter_mask; |
58 | u64 max_period; | 100 | u64 max_period; |
59 | u64 intel_ctrl; | 101 | u64 intel_ctrl; |
102 | void (*enable_bts)(u64 config); | ||
103 | void (*disable_bts)(void); | ||
60 | }; | 104 | }; |
61 | 105 | ||
62 | static struct x86_pmu x86_pmu __read_mostly; | 106 | static struct x86_pmu x86_pmu __read_mostly; |
@@ -576,6 +620,9 @@ x86_perf_counter_update(struct perf_counter *counter, | |||
576 | u64 prev_raw_count, new_raw_count; | 620 | u64 prev_raw_count, new_raw_count; |
577 | s64 delta; | 621 | s64 delta; |
578 | 622 | ||
623 | if (idx == X86_PMC_IDX_FIXED_BTS) | ||
624 | return 0; | ||
625 | |||
579 | /* | 626 | /* |
580 | * Careful: an NMI might modify the previous counter value. | 627 | * Careful: an NMI might modify the previous counter value. |
581 | * | 628 | * |
@@ -659,10 +706,109 @@ static void release_pmc_hardware(void) | |||
659 | enable_lapic_nmi_watchdog(); | 706 | enable_lapic_nmi_watchdog(); |
660 | } | 707 | } |
661 | 708 | ||
709 | static inline bool bts_available(void) | ||
710 | { | ||
711 | return x86_pmu.enable_bts != NULL; | ||
712 | } | ||
713 | |||
714 | static inline void init_debug_store_on_cpu(int cpu) | ||
715 | { | ||
716 | struct debug_store *ds = per_cpu(cpu_hw_counters, cpu).ds; | ||
717 | |||
718 | if (!ds) | ||
719 | return; | ||
720 | |||
721 | wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, | ||
722 | (u32)((u64)(long)ds), (u32)((u64)(long)ds >> 32)); | ||
723 | } | ||
724 | |||
725 | static inline void fini_debug_store_on_cpu(int cpu) | ||
726 | { | ||
727 | if (!per_cpu(cpu_hw_counters, cpu).ds) | ||
728 | return; | ||
729 | |||
730 | wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); | ||
731 | } | ||
732 | |||
733 | static void release_bts_hardware(void) | ||
734 | { | ||
735 | int cpu; | ||
736 | |||
737 | if (!bts_available()) | ||
738 | return; | ||
739 | |||
740 | get_online_cpus(); | ||
741 | |||
742 | for_each_online_cpu(cpu) | ||
743 | fini_debug_store_on_cpu(cpu); | ||
744 | |||
745 | for_each_possible_cpu(cpu) { | ||
746 | struct debug_store *ds = per_cpu(cpu_hw_counters, cpu).ds; | ||
747 | |||
748 | if (!ds) | ||
749 | continue; | ||
750 | |||
751 | per_cpu(cpu_hw_counters, cpu).ds = NULL; | ||
752 | |||
753 | kfree((void *)(long)ds->bts_buffer_base); | ||
754 | kfree(ds); | ||
755 | } | ||
756 | |||
757 | put_online_cpus(); | ||
758 | } | ||
759 | |||
760 | static int reserve_bts_hardware(void) | ||
761 | { | ||
762 | int cpu, err = 0; | ||
763 | |||
764 | if (!bts_available()) | ||
765 | return -EOPNOTSUPP; | ||
766 | |||
767 | get_online_cpus(); | ||
768 | |||
769 | for_each_possible_cpu(cpu) { | ||
770 | struct debug_store *ds; | ||
771 | void *buffer; | ||
772 | |||
773 | err = -ENOMEM; | ||
774 | buffer = kzalloc(BTS_BUFFER_SIZE, GFP_KERNEL); | ||
775 | if (unlikely(!buffer)) | ||
776 | break; | ||
777 | |||
778 | ds = kzalloc(sizeof(*ds), GFP_KERNEL); | ||
779 | if (unlikely(!ds)) { | ||
780 | kfree(buffer); | ||
781 | break; | ||
782 | } | ||
783 | |||
784 | ds->bts_buffer_base = (u64)(long)buffer; | ||
785 | ds->bts_index = ds->bts_buffer_base; | ||
786 | ds->bts_absolute_maximum = | ||
787 | ds->bts_buffer_base + BTS_BUFFER_SIZE; | ||
788 | ds->bts_interrupt_threshold = | ||
789 | ds->bts_absolute_maximum - BTS_OVFL_TH; | ||
790 | |||
791 | per_cpu(cpu_hw_counters, cpu).ds = ds; | ||
792 | err = 0; | ||
793 | } | ||
794 | |||
795 | if (err) | ||
796 | release_bts_hardware(); | ||
797 | else { | ||
798 | for_each_online_cpu(cpu) | ||
799 | init_debug_store_on_cpu(cpu); | ||
800 | } | ||
801 | |||
802 | put_online_cpus(); | ||
803 | |||
804 | return err; | ||
805 | } | ||
806 | |||
662 | static void hw_perf_counter_destroy(struct perf_counter *counter) | 807 | static void hw_perf_counter_destroy(struct perf_counter *counter) |
663 | { | 808 | { |
664 | if (atomic_dec_and_mutex_lock(&active_counters, &pmc_reserve_mutex)) { | 809 | if (atomic_dec_and_mutex_lock(&active_counters, &pmc_reserve_mutex)) { |
665 | release_pmc_hardware(); | 810 | release_pmc_hardware(); |
811 | release_bts_hardware(); | ||
666 | mutex_unlock(&pmc_reserve_mutex); | 812 | mutex_unlock(&pmc_reserve_mutex); |
667 | } | 813 | } |
668 | } | 814 | } |
@@ -705,6 +851,42 @@ set_ext_hw_attr(struct hw_perf_counter *hwc, struct perf_counter_attr *attr) | |||
705 | return 0; | 851 | return 0; |
706 | } | 852 | } |
707 | 853 | ||
854 | static void intel_pmu_enable_bts(u64 config) | ||
855 | { | ||
856 | unsigned long debugctlmsr; | ||
857 | |||
858 | debugctlmsr = get_debugctlmsr(); | ||
859 | |||
860 | debugctlmsr |= X86_DEBUGCTL_TR; | ||
861 | debugctlmsr |= X86_DEBUGCTL_BTS; | ||
862 | debugctlmsr |= X86_DEBUGCTL_BTINT; | ||
863 | |||
864 | if (!(config & ARCH_PERFMON_EVENTSEL_OS)) | ||
865 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; | ||
866 | |||
867 | if (!(config & ARCH_PERFMON_EVENTSEL_USR)) | ||
868 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; | ||
869 | |||
870 | update_debugctlmsr(debugctlmsr); | ||
871 | } | ||
872 | |||
873 | static void intel_pmu_disable_bts(void) | ||
874 | { | ||
875 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
876 | unsigned long debugctlmsr; | ||
877 | |||
878 | if (!cpuc->ds) | ||
879 | return; | ||
880 | |||
881 | debugctlmsr = get_debugctlmsr(); | ||
882 | |||
883 | debugctlmsr &= | ||
884 | ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | | ||
885 | X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); | ||
886 | |||
887 | update_debugctlmsr(debugctlmsr); | ||
888 | } | ||
889 | |||
708 | /* | 890 | /* |
709 | * Setup the hardware configuration for a given attr_type | 891 | * Setup the hardware configuration for a given attr_type |
710 | */ | 892 | */ |
@@ -721,9 +903,13 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
721 | err = 0; | 903 | err = 0; |
722 | if (!atomic_inc_not_zero(&active_counters)) { | 904 | if (!atomic_inc_not_zero(&active_counters)) { |
723 | mutex_lock(&pmc_reserve_mutex); | 905 | mutex_lock(&pmc_reserve_mutex); |
724 | if (atomic_read(&active_counters) == 0 && !reserve_pmc_hardware()) | 906 | if (atomic_read(&active_counters) == 0) { |
725 | err = -EBUSY; | 907 | if (!reserve_pmc_hardware()) |
726 | else | 908 | err = -EBUSY; |
909 | else | ||
910 | reserve_bts_hardware(); | ||
911 | } | ||
912 | if (!err) | ||
727 | atomic_inc(&active_counters); | 913 | atomic_inc(&active_counters); |
728 | mutex_unlock(&pmc_reserve_mutex); | 914 | mutex_unlock(&pmc_reserve_mutex); |
729 | } | 915 | } |
@@ -801,7 +987,18 @@ static void p6_pmu_disable_all(void) | |||
801 | 987 | ||
802 | static void intel_pmu_disable_all(void) | 988 | static void intel_pmu_disable_all(void) |
803 | { | 989 | { |
990 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
991 | |||
992 | if (!cpuc->enabled) | ||
993 | return; | ||
994 | |||
995 | cpuc->enabled = 0; | ||
996 | barrier(); | ||
997 | |||
804 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); | 998 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); |
999 | |||
1000 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) | ||
1001 | intel_pmu_disable_bts(); | ||
805 | } | 1002 | } |
806 | 1003 | ||
807 | static void amd_pmu_disable_all(void) | 1004 | static void amd_pmu_disable_all(void) |
@@ -859,7 +1056,25 @@ static void p6_pmu_enable_all(void) | |||
859 | 1056 | ||
860 | static void intel_pmu_enable_all(void) | 1057 | static void intel_pmu_enable_all(void) |
861 | { | 1058 | { |
1059 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
1060 | |||
1061 | if (cpuc->enabled) | ||
1062 | return; | ||
1063 | |||
1064 | cpuc->enabled = 1; | ||
1065 | barrier(); | ||
1066 | |||
862 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | 1067 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); |
1068 | |||
1069 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { | ||
1070 | struct perf_counter *counter = | ||
1071 | cpuc->counters[X86_PMC_IDX_FIXED_BTS]; | ||
1072 | |||
1073 | if (WARN_ON_ONCE(!counter)) | ||
1074 | return; | ||
1075 | |||
1076 | intel_pmu_enable_bts(counter->hw.config); | ||
1077 | } | ||
863 | } | 1078 | } |
864 | 1079 | ||
865 | static void amd_pmu_enable_all(void) | 1080 | static void amd_pmu_enable_all(void) |
@@ -946,6 +1161,11 @@ p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) | |||
946 | static inline void | 1161 | static inline void |
947 | intel_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) | 1162 | intel_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) |
948 | { | 1163 | { |
1164 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
1165 | intel_pmu_disable_bts(); | ||
1166 | return; | ||
1167 | } | ||
1168 | |||
949 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 1169 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
950 | intel_pmu_disable_fixed(hwc, idx); | 1170 | intel_pmu_disable_fixed(hwc, idx); |
951 | return; | 1171 | return; |
@@ -974,6 +1194,9 @@ x86_perf_counter_set_period(struct perf_counter *counter, | |||
974 | s64 period = hwc->sample_period; | 1194 | s64 period = hwc->sample_period; |
975 | int err, ret = 0; | 1195 | int err, ret = 0; |
976 | 1196 | ||
1197 | if (idx == X86_PMC_IDX_FIXED_BTS) | ||
1198 | return 0; | ||
1199 | |||
977 | /* | 1200 | /* |
978 | * If we are way outside a reasoable range then just skip forward: | 1201 | * If we are way outside a reasoable range then just skip forward: |
979 | */ | 1202 | */ |
@@ -1056,6 +1279,14 @@ static void p6_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) | |||
1056 | 1279 | ||
1057 | static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) | 1280 | static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) |
1058 | { | 1281 | { |
1282 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
1283 | if (!__get_cpu_var(cpu_hw_counters).enabled) | ||
1284 | return; | ||
1285 | |||
1286 | intel_pmu_enable_bts(hwc->config); | ||
1287 | return; | ||
1288 | } | ||
1289 | |||
1059 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 1290 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
1060 | intel_pmu_enable_fixed(hwc, idx); | 1291 | intel_pmu_enable_fixed(hwc, idx); |
1061 | return; | 1292 | return; |
@@ -1077,11 +1308,16 @@ fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc) | |||
1077 | { | 1308 | { |
1078 | unsigned int event; | 1309 | unsigned int event; |
1079 | 1310 | ||
1311 | event = hwc->config & ARCH_PERFMON_EVENT_MASK; | ||
1312 | |||
1313 | if (unlikely((event == | ||
1314 | x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && | ||
1315 | (hwc->sample_period == 1))) | ||
1316 | return X86_PMC_IDX_FIXED_BTS; | ||
1317 | |||
1080 | if (!x86_pmu.num_counters_fixed) | 1318 | if (!x86_pmu.num_counters_fixed) |
1081 | return -1; | 1319 | return -1; |
1082 | 1320 | ||
1083 | event = hwc->config & ARCH_PERFMON_EVENT_MASK; | ||
1084 | |||
1085 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) | 1321 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) |
1086 | return X86_PMC_IDX_FIXED_INSTRUCTIONS; | 1322 | return X86_PMC_IDX_FIXED_INSTRUCTIONS; |
1087 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES))) | 1323 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES))) |
@@ -1102,7 +1338,25 @@ static int x86_pmu_enable(struct perf_counter *counter) | |||
1102 | int idx; | 1338 | int idx; |
1103 | 1339 | ||
1104 | idx = fixed_mode_idx(counter, hwc); | 1340 | idx = fixed_mode_idx(counter, hwc); |
1105 | if (idx >= 0) { | 1341 | if (idx == X86_PMC_IDX_FIXED_BTS) { |
1342 | /* | ||
1343 | * Try to use BTS for branch tracing. If that is not | ||
1344 | * available, try to get a generic counter. | ||
1345 | */ | ||
1346 | if (unlikely(!cpuc->ds)) | ||
1347 | goto try_generic; | ||
1348 | |||
1349 | /* | ||
1350 | * Try to get the fixed counter, if that is already taken | ||
1351 | * then try to get a generic counter: | ||
1352 | */ | ||
1353 | if (test_and_set_bit(idx, cpuc->used_mask)) | ||
1354 | goto try_generic; | ||
1355 | |||
1356 | hwc->config_base = 0; | ||
1357 | hwc->counter_base = 0; | ||
1358 | hwc->idx = idx; | ||
1359 | } else if (idx >= 0) { | ||
1106 | /* | 1360 | /* |
1107 | * Try to get the fixed counter, if that is already taken | 1361 | * Try to get the fixed counter, if that is already taken |
1108 | * then try to get a generic counter: | 1362 | * then try to get a generic counter: |
@@ -1213,6 +1467,45 @@ void perf_counter_print_debug(void) | |||
1213 | local_irq_restore(flags); | 1467 | local_irq_restore(flags); |
1214 | } | 1468 | } |
1215 | 1469 | ||
1470 | static void intel_pmu_drain_bts_buffer(struct cpu_hw_counters *cpuc, | ||
1471 | struct perf_sample_data *data) | ||
1472 | { | ||
1473 | struct debug_store *ds = cpuc->ds; | ||
1474 | struct bts_record { | ||
1475 | u64 from; | ||
1476 | u64 to; | ||
1477 | u64 flags; | ||
1478 | }; | ||
1479 | struct perf_counter *counter = cpuc->counters[X86_PMC_IDX_FIXED_BTS]; | ||
1480 | unsigned long orig_ip = data->regs->ip; | ||
1481 | u64 at; | ||
1482 | |||
1483 | if (!counter) | ||
1484 | return; | ||
1485 | |||
1486 | if (!ds) | ||
1487 | return; | ||
1488 | |||
1489 | for (at = ds->bts_buffer_base; | ||
1490 | at < ds->bts_index; | ||
1491 | at += sizeof(struct bts_record)) { | ||
1492 | struct bts_record *rec = (struct bts_record *)(long)at; | ||
1493 | |||
1494 | data->regs->ip = rec->from; | ||
1495 | data->addr = rec->to; | ||
1496 | |||
1497 | perf_counter_output(counter, 1, data); | ||
1498 | } | ||
1499 | |||
1500 | ds->bts_index = ds->bts_buffer_base; | ||
1501 | |||
1502 | data->regs->ip = orig_ip; | ||
1503 | data->addr = 0; | ||
1504 | |||
1505 | /* There's new data available. */ | ||
1506 | counter->pending_kill = POLL_IN; | ||
1507 | } | ||
1508 | |||
1216 | static void x86_pmu_disable(struct perf_counter *counter) | 1509 | static void x86_pmu_disable(struct perf_counter *counter) |
1217 | { | 1510 | { |
1218 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | 1511 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); |
@@ -1237,6 +1530,15 @@ static void x86_pmu_disable(struct perf_counter *counter) | |||
1237 | * that we are disabling: | 1530 | * that we are disabling: |
1238 | */ | 1531 | */ |
1239 | x86_perf_counter_update(counter, hwc, idx); | 1532 | x86_perf_counter_update(counter, hwc, idx); |
1533 | |||
1534 | /* Drain the remaining BTS records. */ | ||
1535 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
1536 | struct perf_sample_data data; | ||
1537 | struct pt_regs regs; | ||
1538 | |||
1539 | data.regs = ®s; | ||
1540 | intel_pmu_drain_bts_buffer(cpuc, &data); | ||
1541 | } | ||
1240 | cpuc->counters[idx] = NULL; | 1542 | cpuc->counters[idx] = NULL; |
1241 | clear_bit(idx, cpuc->used_mask); | 1543 | clear_bit(idx, cpuc->used_mask); |
1242 | 1544 | ||
@@ -1264,6 +1566,7 @@ static int intel_pmu_save_and_restart(struct perf_counter *counter) | |||
1264 | 1566 | ||
1265 | static void intel_pmu_reset(void) | 1567 | static void intel_pmu_reset(void) |
1266 | { | 1568 | { |
1569 | struct debug_store *ds = __get_cpu_var(cpu_hw_counters).ds; | ||
1267 | unsigned long flags; | 1570 | unsigned long flags; |
1268 | int idx; | 1571 | int idx; |
1269 | 1572 | ||
@@ -1281,6 +1584,8 @@ static void intel_pmu_reset(void) | |||
1281 | for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) { | 1584 | for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) { |
1282 | checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); | 1585 | checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); |
1283 | } | 1586 | } |
1587 | if (ds) | ||
1588 | ds->bts_index = ds->bts_buffer_base; | ||
1284 | 1589 | ||
1285 | local_irq_restore(flags); | 1590 | local_irq_restore(flags); |
1286 | } | 1591 | } |
@@ -1346,6 +1651,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) | |||
1346 | cpuc = &__get_cpu_var(cpu_hw_counters); | 1651 | cpuc = &__get_cpu_var(cpu_hw_counters); |
1347 | 1652 | ||
1348 | perf_disable(); | 1653 | perf_disable(); |
1654 | intel_pmu_drain_bts_buffer(cpuc, &data); | ||
1349 | status = intel_pmu_get_status(); | 1655 | status = intel_pmu_get_status(); |
1350 | if (!status) { | 1656 | if (!status) { |
1351 | perf_enable(); | 1657 | perf_enable(); |
@@ -1547,6 +1853,8 @@ static struct x86_pmu intel_pmu = { | |||
1547 | * the generic counter period: | 1853 | * the generic counter period: |
1548 | */ | 1854 | */ |
1549 | .max_period = (1ULL << 31) - 1, | 1855 | .max_period = (1ULL << 31) - 1, |
1856 | .enable_bts = intel_pmu_enable_bts, | ||
1857 | .disable_bts = intel_pmu_disable_bts, | ||
1550 | }; | 1858 | }; |
1551 | 1859 | ||
1552 | static struct x86_pmu amd_pmu = { | 1860 | static struct x86_pmu amd_pmu = { |
@@ -1936,3 +2244,8 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
1936 | 2244 | ||
1937 | return entry; | 2245 | return entry; |
1938 | } | 2246 | } |
2247 | |||
2248 | void hw_perf_counter_setup_online(int cpu) | ||
2249 | { | ||
2250 | init_debug_store_on_cpu(cpu); | ||
2251 | } | ||
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 2aabe43c1d04..0a6f3209c9de 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -692,6 +692,8 @@ struct perf_sample_data { | |||
692 | 692 | ||
693 | extern int perf_counter_overflow(struct perf_counter *counter, int nmi, | 693 | extern int perf_counter_overflow(struct perf_counter *counter, int nmi, |
694 | struct perf_sample_data *data); | 694 | struct perf_sample_data *data); |
695 | extern void perf_counter_output(struct perf_counter *counter, int nmi, | ||
696 | struct perf_sample_data *data); | ||
695 | 697 | ||
696 | /* | 698 | /* |
697 | * Return 1 for a software counter, 0 for a hardware counter | 699 | * Return 1 for a software counter, 0 for a hardware counter |
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 546e62d62941..bf8110b35c51 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -88,6 +88,7 @@ void __weak hw_perf_disable(void) { barrier(); } | |||
88 | void __weak hw_perf_enable(void) { barrier(); } | 88 | void __weak hw_perf_enable(void) { barrier(); } |
89 | 89 | ||
90 | void __weak hw_perf_counter_setup(int cpu) { barrier(); } | 90 | void __weak hw_perf_counter_setup(int cpu) { barrier(); } |
91 | void __weak hw_perf_counter_setup_online(int cpu) { barrier(); } | ||
91 | 92 | ||
92 | int __weak | 93 | int __weak |
93 | hw_perf_group_sched_in(struct perf_counter *group_leader, | 94 | hw_perf_group_sched_in(struct perf_counter *group_leader, |
@@ -2630,7 +2631,7 @@ static u32 perf_counter_tid(struct perf_counter *counter, struct task_struct *p) | |||
2630 | return task_pid_nr_ns(p, counter->ns); | 2631 | return task_pid_nr_ns(p, counter->ns); |
2631 | } | 2632 | } |
2632 | 2633 | ||
2633 | static void perf_counter_output(struct perf_counter *counter, int nmi, | 2634 | void perf_counter_output(struct perf_counter *counter, int nmi, |
2634 | struct perf_sample_data *data) | 2635 | struct perf_sample_data *data) |
2635 | { | 2636 | { |
2636 | int ret; | 2637 | int ret; |
@@ -4566,6 +4567,11 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) | |||
4566 | perf_counter_init_cpu(cpu); | 4567 | perf_counter_init_cpu(cpu); |
4567 | break; | 4568 | break; |
4568 | 4569 | ||
4570 | case CPU_ONLINE: | ||
4571 | case CPU_ONLINE_FROZEN: | ||
4572 | hw_perf_counter_setup_online(cpu); | ||
4573 | break; | ||
4574 | |||
4569 | case CPU_DOWN_PREPARE: | 4575 | case CPU_DOWN_PREPARE: |
4570 | case CPU_DOWN_PREPARE_FROZEN: | 4576 | case CPU_DOWN_PREPARE_FROZEN: |
4571 | perf_counter_exit_cpu(cpu); | 4577 | perf_counter_exit_cpu(cpu); |
@@ -4590,6 +4596,8 @@ void __init perf_counter_init(void) | |||
4590 | { | 4596 | { |
4591 | perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE, | 4597 | perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE, |
4592 | (void *)(long)smp_processor_id()); | 4598 | (void *)(long)smp_processor_id()); |
4599 | perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE, | ||
4600 | (void *)(long)smp_processor_id()); | ||
4593 | register_cpu_notifier(&perf_cpu_nb); | 4601 | register_cpu_notifier(&perf_cpu_nb); |
4594 | } | 4602 | } |
4595 | 4603 | ||