Skip to content

Commit 4d4c474

Browse files
virtuosoIngo Molnar
authored andcommitted
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 <[email protected]> Signed-off-by: Alexander Shishkin <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent a9a9440 commit 4d4c474

File tree

1 file changed

+15
-4
lines changed
  • arch/x86/events/intel

1 file changed

+15
-4
lines changed

arch/x86/events/intel/bts.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,34 +446,45 @@ bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle)
446446

447447
int intel_bts_interrupt(void)
448448
{
449+
struct debug_store *ds = this_cpu_ptr(&cpu_hw_events)->ds;
449450
struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
450451
struct perf_event *event = bts->handle.event;
451452
struct bts_buffer *buf;
452453
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;
454462

455463
/*
456464
* this is wrapped in intel_bts_enable_local/intel_bts_disable_local,
457465
* so we can only be INACTIVE or STOPPED
458466
*/
459467
if (READ_ONCE(bts->state) == BTS_STATE_STOPPED)
460-
return 0;
468+
return handled;
461469

462470
buf = perf_get_aux(&bts->handle);
471+
if (!buf)
472+
return handled;
473+
463474
/*
464475
* Skip snapshot counters: they don't use the interrupt, but
465476
* there's no other way of telling, because the pointer will
466477
* keep moving
467478
*/
468-
if (!buf || buf->snapshot)
479+
if (buf->snapshot)
469480
return 0;
470481

471482
old_head = local_read(&buf->head);
472483
bts_update(bts);
473484

474485
/* no new data */
475486
if (old_head == local_read(&buf->head))
476-
return 0;
487+
return handled;
477488

478489
perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
479490
!!local_xchg(&buf->lost, 0));

0 commit comments

Comments
 (0)