Skip to content

Commit daa864b

Browse files
Stephane EranianIngo Molnar
authored andcommitted
perf/x86/pebs: Fix handling of PEBS buffer overflows
This patch solves a race condition between PEBS and the PMU handler. In case multiple PEBS events are sampled at the same time, it is possible to have GLOBAL_STATUS bit 62 set indicating PEBS buffer overflow and also seeing at most 3 PEBS counters having their bits set in the status register. This is a sign that there was at least one PEBS record pending at the time of the PMU interrupt. PEBS counters must only be processed via the drain_pebs() calls, and not via the regular sample processing loop coming after that the function, otherwise phony regular samples may be generated in the sampling buffer not marked with the EXACT tag. Another possibility is to have one PEBS event and at least one non-PEBS event whic hoverflows while PEBS has armed. In this case, bit 62 of GLOBAL_STATUS will not be set, yet the overflow status bit for the PEBS counter will be on Skylake. To avoid this problem, we systematically ignore the PEBS-enabled counters from the GLOBAL_STATUS mask and we always process PEBS events via drain_pebs(). The problem manifested itself by having non-exact samples when sampling only PEBS events, i.e., the PERF_SAMPLE_RECORD would not have the EXACT flag set. Note that this problem is only present on Skylake processor. This fix is harmless on older processors. Reported-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Stephane Eranian <eranian@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vince Weaver <vincent.weaver@maine.edu> Link: http://lkml.kernel.org/r/1482395366-8992-1-git-send-email-eranian@google.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 0375691 commit daa864b

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

arch/x86/events/intel/core.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,22 +2110,34 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
21102110
GLOBAL_STATUS_LBRS_FROZEN);
21112111
if (!status)
21122112
goto done;
2113+
/*
2114+
* In case multiple PEBS events are sampled at the same time,
2115+
* it is possible to have GLOBAL_STATUS bit 62 set indicating
2116+
* PEBS buffer overflow and also seeing at most 3 PEBS counters
2117+
* having their bits set in the status register. This is a sign
2118+
* that there was at least one PEBS record pending at the time
2119+
* of the PMU interrupt. PEBS counters must only be processed
2120+
* via the drain_pebs() calls and not via the regular sample
2121+
* processing loop coming after that the function, otherwise
2122+
* phony regular samples may be generated in the sampling buffer
2123+
* not marked with the EXACT tag. Another possibility is to have
2124+
* one PEBS event and at least one non-PEBS event whic hoverflows
2125+
* while PEBS has armed. In this case, bit 62 of GLOBAL_STATUS will
2126+
* not be set, yet the overflow status bit for the PEBS counter will
2127+
* be on Skylake.
2128+
*
2129+
* To avoid this problem, we systematically ignore the PEBS-enabled
2130+
* counters from the GLOBAL_STATUS mask and we always process PEBS
2131+
* events via drain_pebs().
2132+
*/
2133+
status &= ~cpuc->pebs_enabled;
21132134

21142135
/*
21152136
* PEBS overflow sets bit 62 in the global status register
21162137
*/
21172138
if (__test_and_clear_bit(62, (unsigned long *)&status)) {
21182139
handled++;
21192140
x86_pmu.drain_pebs(regs);
2120-
/*
2121-
* There are cases where, even though, the PEBS ovfl bit is set
2122-
* in GLOBAL_OVF_STATUS, the PEBS events may also have their
2123-
* overflow bits set for their counters. We must clear them
2124-
* here because they have been processed as exact samples in
2125-
* the drain_pebs() routine. They must not be processed again
2126-
* in the for_each_bit_set() loop for regular samples below.
2127-
*/
2128-
status &= ~cpuc->pebs_enabled;
21292141
status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
21302142
}
21312143

0 commit comments

Comments
 (0)