Commit b0b2072df3b544f56b90173c2cde7a374c51546b

Authored by Stephane Eranian
Committed by Ingo Molnar
1 parent e5f4d3394a

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, &regs);
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 /*