Commit b0b2072df3b544f56b90173c2cde7a374c51546b
Committed by
Ingo Molnar
1 parent
e5f4d3394a
Exists in
master
and in
7 other branches
perf_events: Fix BTS interrupt handling to avoid being dazed by NMI (v2)
Fix a bug introduced with commit de725de and the change in the meaning of the return value of intel_pmu_handle_irq(). With the current code, when you are using the BTS, you get 'dazed by NMI' each time the BTS buffer fills up. BTS does interrupt on the PMU vector, thus NMI. You need to take this into account in the return value of the function. This version fixes initial patch which was missing changes to perf_event_intel_ds.c. Signed-off-by: Stephane Eranian <eranian@google.com> Acked-by: Don Zickus <dzickus@redhat.com> Cc: peterz@infradead.org Cc: paulus@samba.org Cc: davem@davemloft.net Cc: fweisbec@gmail.com Cc: perfmon2-devel@lists.sf.net Cc: eranian@gmail.com Cc: robert.richter@amd.com LKML-Reference: <4c8a1686.aae9d80a.5aa4.5e35@mx.google.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 2 changed files with 9 additions and 8 deletions Side-by-side Diff
arch/x86/kernel/cpu/perf_event_intel.c
... | ... | @@ -713,18 +713,18 @@ |
713 | 713 | struct cpu_hw_events *cpuc; |
714 | 714 | int bit, loops; |
715 | 715 | u64 status; |
716 | - int handled = 0; | |
716 | + int handled; | |
717 | 717 | |
718 | 718 | perf_sample_data_init(&data, 0); |
719 | 719 | |
720 | 720 | cpuc = &__get_cpu_var(cpu_hw_events); |
721 | 721 | |
722 | 722 | intel_pmu_disable_all(); |
723 | - intel_pmu_drain_bts_buffer(); | |
723 | + handled = intel_pmu_drain_bts_buffer(); | |
724 | 724 | status = intel_pmu_get_status(); |
725 | 725 | if (!status) { |
726 | 726 | intel_pmu_enable_all(0); |
727 | - return 0; | |
727 | + return handled; | |
728 | 728 | } |
729 | 729 | |
730 | 730 | loops = 0; |
arch/x86/kernel/cpu/perf_event_intel_ds.c
... | ... | @@ -214,7 +214,7 @@ |
214 | 214 | update_debugctlmsr(debugctlmsr); |
215 | 215 | } |
216 | 216 | |
217 | -static void intel_pmu_drain_bts_buffer(void) | |
217 | +static int intel_pmu_drain_bts_buffer(void) | |
218 | 218 | { |
219 | 219 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
220 | 220 | struct debug_store *ds = cpuc->ds; |
221 | 221 | |
222 | 222 | |
... | ... | @@ -231,16 +231,16 @@ |
231 | 231 | struct pt_regs regs; |
232 | 232 | |
233 | 233 | if (!event) |
234 | - return; | |
234 | + return 0; | |
235 | 235 | |
236 | 236 | if (!ds) |
237 | - return; | |
237 | + return 0; | |
238 | 238 | |
239 | 239 | at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; |
240 | 240 | top = (struct bts_record *)(unsigned long)ds->bts_index; |
241 | 241 | |
242 | 242 | if (top <= at) |
243 | - return; | |
243 | + return 0; | |
244 | 244 | |
245 | 245 | ds->bts_index = ds->bts_buffer_base; |
246 | 246 | |
... | ... | @@ -256,7 +256,7 @@ |
256 | 256 | perf_prepare_sample(&header, &data, event, ®s); |
257 | 257 | |
258 | 258 | if (perf_output_begin(&handle, event, header.size * (top - at), 1, 1)) |
259 | - return; | |
259 | + return 1; | |
260 | 260 | |
261 | 261 | for (; at < top; at++) { |
262 | 262 | data.ip = at->from; |
... | ... | @@ -270,6 +270,7 @@ |
270 | 270 | /* There's new data available. */ |
271 | 271 | event->hw.interrupts++; |
272 | 272 | event->pending_kill = POLL_IN; |
273 | + return 1; | |
273 | 274 | } |
274 | 275 | |
275 | 276 | /* |