aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>2016-09-06 09:23:52 -0400
committerIngo Molnar <mingo@kernel.org>2016-09-10 05:15:38 -0400
commit4d4c474124649198d9b0a065c06f9362cf18e14e (patch)
tree083b459c3189cf850794b9f0d53fe0eb8af5652d
parenta9a94401c2b5805c71e39427b1af1bf1b9f67cd0 (diff)
perf/x86/intel/bts: Fix BTS PMI detection
Since BTS doesn't have a dedicated PMI status bit, the driver needs to take extra care to check for the condition that triggers it to avoid spurious NMI warnings. Regardless of the local BTS context state, the only way of knowing that the NMI is ours is to compare the write pointer against the interrupt threshold. Reported-by: Vince Weaver <vincent.weaver@maine.edu> Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: vince@deater.net Link: http://lkml.kernel.org/r/20160906132353.19887-5-alexander.shishkin@linux.intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/events/intel/bts.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c
index 61e1d713b114..9233edf993e1 100644
--- a/arch/x86/events/intel/bts.c
+++ b/arch/x86/events/intel/bts.c
@@ -446,26 +446,37 @@ bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle)
446 446
447int intel_bts_interrupt(void) 447int intel_bts_interrupt(void)
448{ 448{
449 struct debug_store *ds = this_cpu_ptr(&cpu_hw_events)->ds;
449 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx); 450 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
450 struct perf_event *event = bts->handle.event; 451 struct perf_event *event = bts->handle.event;
451 struct bts_buffer *buf; 452 struct bts_buffer *buf;
452 s64 old_head; 453 s64 old_head;
453 int err = -ENOSPC; 454 int err = -ENOSPC, handled = 0;
455
456 /*
457 * The only surefire way of knowing if this NMI is ours is by checking
458 * the write ptr against the PMI threshold.
459 */
460 if (ds->bts_index >= ds->bts_interrupt_threshold)
461 handled = 1;
454 462
455 /* 463 /*
456 * this is wrapped in intel_bts_enable_local/intel_bts_disable_local, 464 * this is wrapped in intel_bts_enable_local/intel_bts_disable_local,
457 * so we can only be INACTIVE or STOPPED 465 * so we can only be INACTIVE or STOPPED
458 */ 466 */
459 if (READ_ONCE(bts->state) == BTS_STATE_STOPPED) 467 if (READ_ONCE(bts->state) == BTS_STATE_STOPPED)
460 return 0; 468 return handled;
461 469
462 buf = perf_get_aux(&bts->handle); 470 buf = perf_get_aux(&bts->handle);
471 if (!buf)
472 return handled;
473
463 /* 474 /*
464 * Skip snapshot counters: they don't use the interrupt, but 475 * Skip snapshot counters: they don't use the interrupt, but
465 * there's no other way of telling, because the pointer will 476 * there's no other way of telling, because the pointer will
466 * keep moving 477 * keep moving
467 */ 478 */
468 if (!buf || buf->snapshot) 479 if (buf->snapshot)
469 return 0; 480 return 0;
470 481
471 old_head = local_read(&buf->head); 482 old_head = local_read(&buf->head);
@@ -473,7 +484,7 @@ int intel_bts_interrupt(void)
473 484
474 /* no new data */ 485 /* no new data */
475 if (old_head == local_read(&buf->head)) 486 if (old_head == local_read(&buf->head))
476 return 0; 487 return handled;
477 488
478 perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0), 489 perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
479 !!local_xchg(&buf->lost, 0)); 490 !!local_xchg(&buf->lost, 0));