diff options
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 12 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_p4.c | 6 |
3 files changed, 18 insertions, 2 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 24fa1718ddb9..9d3f485e5dd0 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -11,6 +11,8 @@ ifdef CONFIG_FUNCTION_TRACER | |||
| 11 | CFLAGS_REMOVE_tsc.o = -pg | 11 | CFLAGS_REMOVE_tsc.o = -pg |
| 12 | CFLAGS_REMOVE_rtc.o = -pg | 12 | CFLAGS_REMOVE_rtc.o = -pg |
| 13 | CFLAGS_REMOVE_paravirt-spinlocks.o = -pg | 13 | CFLAGS_REMOVE_paravirt-spinlocks.o = -pg |
| 14 | CFLAGS_REMOVE_pvclock.o = -pg | ||
| 15 | CFLAGS_REMOVE_kvmclock.o = -pg | ||
| 14 | CFLAGS_REMOVE_ftrace.o = -pg | 16 | CFLAGS_REMOVE_ftrace.o = -pg |
| 15 | CFLAGS_REMOVE_early_printk.o = -pg | 17 | CFLAGS_REMOVE_early_printk.o = -pg |
| 16 | endif | 18 | endif |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 0fb17050360f..6526a86616a7 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
| @@ -102,6 +102,7 @@ struct cpu_hw_events { | |||
| 102 | */ | 102 | */ |
| 103 | struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ | 103 | struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ |
| 104 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 104 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
| 105 | unsigned long running[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | ||
| 105 | int enabled; | 106 | int enabled; |
| 106 | 107 | ||
| 107 | int n_events; | 108 | int n_events; |
| @@ -1034,6 +1035,7 @@ static void x86_pmu_start(struct perf_event *event, int flags) | |||
| 1034 | 1035 | ||
| 1035 | cpuc->events[idx] = event; | 1036 | cpuc->events[idx] = event; |
| 1036 | __set_bit(idx, cpuc->active_mask); | 1037 | __set_bit(idx, cpuc->active_mask); |
| 1038 | __set_bit(idx, cpuc->running); | ||
| 1037 | x86_pmu.enable(event); | 1039 | x86_pmu.enable(event); |
| 1038 | perf_event_update_userpage(event); | 1040 | perf_event_update_userpage(event); |
| 1039 | } | 1041 | } |
| @@ -1159,8 +1161,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) | |||
| 1159 | cpuc = &__get_cpu_var(cpu_hw_events); | 1161 | cpuc = &__get_cpu_var(cpu_hw_events); |
| 1160 | 1162 | ||
| 1161 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { | 1163 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { |
| 1162 | if (!test_bit(idx, cpuc->active_mask)) | 1164 | if (!test_bit(idx, cpuc->active_mask)) { |
| 1165 | /* | ||
| 1166 | * Though we deactivated the counter some cpus | ||
| 1167 | * might still deliver spurious interrupts still | ||
| 1168 | * in flight. Catch them: | ||
| 1169 | */ | ||
| 1170 | if (__test_and_clear_bit(idx, cpuc->running)) | ||
| 1171 | handled++; | ||
| 1163 | continue; | 1172 | continue; |
| 1173 | } | ||
| 1164 | 1174 | ||
| 1165 | event = cpuc->events[idx]; | 1175 | event = cpuc->events[idx]; |
| 1166 | hwc = &event->hw; | 1176 | hwc = &event->hw; |
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index c70c878ee02a..81400b93e694 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c | |||
| @@ -904,8 +904,12 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) | |||
| 904 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { | 904 | for (idx = 0; idx < x86_pmu.num_counters; idx++) { |
| 905 | int overflow; | 905 | int overflow; |
| 906 | 906 | ||
| 907 | if (!test_bit(idx, cpuc->active_mask)) | 907 | if (!test_bit(idx, cpuc->active_mask)) { |
| 908 | /* catch in-flight IRQs */ | ||
| 909 | if (__test_and_clear_bit(idx, cpuc->running)) | ||
| 910 | handled++; | ||
| 908 | continue; | 911 | continue; |
| 912 | } | ||
| 909 | 913 | ||
| 910 | event = cpuc->events[idx]; | 914 | event = cpuc->events[idx]; |
| 911 | hwc = &event->hw; | 915 | hwc = &event->hw; |
