diff options
| -rw-r--r-- | arch/x86/kernel/cpu/perf_counter.c | 253 | ||||
| -rw-r--r-- | include/linux/perf_counter.h | 15 | ||||
| -rw-r--r-- | init/Kconfig | 2 | ||||
| -rw-r--r-- | kernel/fork.c | 9 | ||||
| -rw-r--r-- | kernel/perf_counter.c | 185 | ||||
| -rw-r--r-- | tools/perf/Documentation/perf-report.txt | 15 | ||||
| -rw-r--r-- | tools/perf/Makefile | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-annotate.c | 24 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 13 | ||||
| -rw-r--r-- | tools/perf/builtin-report.c | 255 | ||||
| -rw-r--r-- | tools/perf/builtin-stat.c | 3 | ||||
| -rw-r--r-- | tools/perf/builtin-top.c | 6 | ||||
| -rw-r--r-- | tools/perf/perf.c | 77 | ||||
| -rw-r--r-- | tools/perf/perf.h | 8 | ||||
| -rw-r--r-- | tools/perf/util/cache.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/header.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/include/linux/kernel.h | 8 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 182 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.h | 5 | ||||
| -rw-r--r-- | tools/perf/util/string.h | 3 | ||||
| -rw-r--r-- | tools/perf/util/strlist.c | 20 | ||||
| -rw-r--r-- | tools/perf/util/strlist.h | 11 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 145 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/util.h | 2 |
25 files changed, 948 insertions, 299 deletions
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index 36c3dc7b8991..a7aa8f900954 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
| @@ -66,6 +66,52 @@ static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters) = { | |||
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | /* | 68 | /* |
| 69 | * Not sure about some of these | ||
| 70 | */ | ||
| 71 | static const u64 p6_perfmon_event_map[] = | ||
| 72 | { | ||
| 73 | [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, | ||
| 74 | [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, | ||
| 75 | [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0000, | ||
| 76 | [PERF_COUNT_HW_CACHE_MISSES] = 0x0000, | ||
| 77 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | ||
| 78 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | ||
| 79 | [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, | ||
| 80 | }; | ||
| 81 | |||
| 82 | static u64 p6_pmu_event_map(int event) | ||
| 83 | { | ||
| 84 | return p6_perfmon_event_map[event]; | ||
| 85 | } | ||
| 86 | |||
| 87 | /* | ||
| 88 | * Counter setting that is specified not to count anything. | ||
| 89 | * We use this to effectively disable a counter. | ||
| 90 | * | ||
| 91 | * L2_RQSTS with 0 MESI unit mask. | ||
| 92 | */ | ||
| 93 | #define P6_NOP_COUNTER 0x0000002EULL | ||
| 94 | |||
| 95 | static u64 p6_pmu_raw_event(u64 event) | ||
| 96 | { | ||
| 97 | #define P6_EVNTSEL_EVENT_MASK 0x000000FFULL | ||
| 98 | #define P6_EVNTSEL_UNIT_MASK 0x0000FF00ULL | ||
| 99 | #define P6_EVNTSEL_EDGE_MASK 0x00040000ULL | ||
| 100 | #define P6_EVNTSEL_INV_MASK 0x00800000ULL | ||
| 101 | #define P6_EVNTSEL_COUNTER_MASK 0xFF000000ULL | ||
| 102 | |||
| 103 | #define P6_EVNTSEL_MASK \ | ||
| 104 | (P6_EVNTSEL_EVENT_MASK | \ | ||
| 105 | P6_EVNTSEL_UNIT_MASK | \ | ||
| 106 | P6_EVNTSEL_EDGE_MASK | \ | ||
| 107 | P6_EVNTSEL_INV_MASK | \ | ||
| 108 | P6_EVNTSEL_COUNTER_MASK) | ||
| 109 | |||
| 110 | return event & P6_EVNTSEL_MASK; | ||
| 111 | } | ||
| 112 | |||
| 113 | |||
| 114 | /* | ||
| 69 | * Intel PerfMon v3. Used on Core2 and later. | 115 | * Intel PerfMon v3. Used on Core2 and later. |
| 70 | */ | 116 | */ |
| 71 | static const u64 intel_perfmon_event_map[] = | 117 | static const u64 intel_perfmon_event_map[] = |
| @@ -666,6 +712,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
| 666 | { | 712 | { |
| 667 | struct perf_counter_attr *attr = &counter->attr; | 713 | struct perf_counter_attr *attr = &counter->attr; |
| 668 | struct hw_perf_counter *hwc = &counter->hw; | 714 | struct hw_perf_counter *hwc = &counter->hw; |
| 715 | u64 config; | ||
| 669 | int err; | 716 | int err; |
| 670 | 717 | ||
| 671 | if (!x86_pmu_initialized()) | 718 | if (!x86_pmu_initialized()) |
| @@ -718,14 +765,40 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
| 718 | 765 | ||
| 719 | if (attr->config >= x86_pmu.max_events) | 766 | if (attr->config >= x86_pmu.max_events) |
| 720 | return -EINVAL; | 767 | return -EINVAL; |
| 768 | |||
| 721 | /* | 769 | /* |
| 722 | * The generic map: | 770 | * The generic map: |
| 723 | */ | 771 | */ |
| 724 | hwc->config |= x86_pmu.event_map(attr->config); | 772 | config = x86_pmu.event_map(attr->config); |
| 773 | |||
| 774 | if (config == 0) | ||
| 775 | return -ENOENT; | ||
| 776 | |||
| 777 | if (config == -1LL) | ||
| 778 | return -EINVAL; | ||
| 779 | |||
| 780 | hwc->config |= config; | ||
| 725 | 781 | ||
| 726 | return 0; | 782 | return 0; |
| 727 | } | 783 | } |
| 728 | 784 | ||
| 785 | static void p6_pmu_disable_all(void) | ||
| 786 | { | ||
| 787 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
| 788 | u64 val; | ||
| 789 | |||
| 790 | if (!cpuc->enabled) | ||
| 791 | return; | ||
| 792 | |||
| 793 | cpuc->enabled = 0; | ||
| 794 | barrier(); | ||
| 795 | |||
| 796 | /* p6 only has one enable register */ | ||
| 797 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
| 798 | val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
| 799 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
| 800 | } | ||
| 801 | |||
| 729 | static void intel_pmu_disable_all(void) | 802 | static void intel_pmu_disable_all(void) |
| 730 | { | 803 | { |
| 731 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); | 804 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); |
| @@ -767,6 +840,23 @@ void hw_perf_disable(void) | |||
| 767 | return x86_pmu.disable_all(); | 840 | return x86_pmu.disable_all(); |
| 768 | } | 841 | } |
| 769 | 842 | ||
| 843 | static void p6_pmu_enable_all(void) | ||
| 844 | { | ||
| 845 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
| 846 | unsigned long val; | ||
| 847 | |||
| 848 | if (cpuc->enabled) | ||
| 849 | return; | ||
| 850 | |||
| 851 | cpuc->enabled = 1; | ||
| 852 | barrier(); | ||
| 853 | |||
| 854 | /* p6 only has one enable register */ | ||
| 855 | rdmsrl(MSR_P6_EVNTSEL0, val); | ||
| 856 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | ||
| 857 | wrmsrl(MSR_P6_EVNTSEL0, val); | ||
| 858 | } | ||
| 859 | |||
| 770 | static void intel_pmu_enable_all(void) | 860 | static void intel_pmu_enable_all(void) |
| 771 | { | 861 | { |
| 772 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | 862 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); |
| @@ -784,13 +874,13 @@ static void amd_pmu_enable_all(void) | |||
| 784 | barrier(); | 874 | barrier(); |
| 785 | 875 | ||
| 786 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { | 876 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { |
| 877 | struct perf_counter *counter = cpuc->counters[idx]; | ||
| 787 | u64 val; | 878 | u64 val; |
| 788 | 879 | ||
| 789 | if (!test_bit(idx, cpuc->active_mask)) | 880 | if (!test_bit(idx, cpuc->active_mask)) |
| 790 | continue; | 881 | continue; |
| 791 | rdmsrl(MSR_K7_EVNTSEL0 + idx, val); | 882 | |
| 792 | if (val & ARCH_PERFMON_EVENTSEL0_ENABLE) | 883 | val = counter->hw.config; |
| 793 | continue; | ||
| 794 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; | 884 | val |= ARCH_PERFMON_EVENTSEL0_ENABLE; |
| 795 | wrmsrl(MSR_K7_EVNTSEL0 + idx, val); | 885 | wrmsrl(MSR_K7_EVNTSEL0 + idx, val); |
| 796 | } | 886 | } |
| @@ -819,1 | |||
