Skip to content

Commit 5b59016

Browse files
ahunter6Peter Zijlstra
authored andcommitted
perf/x86/intel/pt: Fix buffer full but size is 0 case
If the trace data buffer becomes full, a truncated flag [T] is reported in PERF_RECORD_AUX. In some cases, the size reported is 0, even though data must have been added to make the buffer full. That happens when the buffer fills up from empty to full before the Intel PT driver has updated the buffer position. Then the driver calculates the new buffer position before calculating the data size. If the old and new positions are the same, the data size is reported as 0, even though it is really the whole buffer size. Fix by detecting when the buffer position is wrapped, and adjust the data size calculation accordingly. Example Use a very small buffer size (8K) and observe the size of truncated [T] data. Before the fix, it is possible to see records of 0 size. Before: $ perf record -m,8K -e intel_pt// uname Linux [ perf record: Woken up 2 times to write data ] [ perf record: Captured and wrote 0.105 MB perf.data ] $ perf script -D --no-itrace | grep AUX | grep -F '[T]' Warning: AUX data lost 2 times out of 3! 5 19462712368111 0x19710 [0x40]: PERF_RECORD_AUX offset: 0 size: 0 flags: 0x1 [T] 5 19462712700046 0x19ba8 [0x40]: PERF_RECORD_AUX offset: 0x170 size: 0xe90 flags: 0x1 [T] After: $ perf record -m,8K -e intel_pt// uname Linux [ perf record: Woken up 3 times to write data ] [ perf record: Captured and wrote 0.040 MB perf.data ] $ perf script -D --no-itrace | grep AUX | grep -F '[T]' Warning: AUX data lost 2 times out of 3! 1 113720802995 0x4948 [0x40]: PERF_RECORD_AUX offset: 0 size: 0x2000 flags: 0x1 [T] 1 113720979812 0x6b10 [0x40]: PERF_RECORD_AUX offset: 0x2000 size: 0x2000 flags: 0x1 [T] Fixes: 52ca9ce ("perf/x86/intel/pt: Add Intel PT PMU driver") Signed-off-by: Adrian Hunter <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent dd1a756 commit 5b59016

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

arch/x86/events/intel/pt.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -828,11 +828,13 @@ static void pt_buffer_advance(struct pt_buffer *buf)
828828
buf->cur_idx++;
829829

830830
if (buf->cur_idx == buf->cur->last) {
831-
if (buf->cur == buf->last)
831+
if (buf->cur == buf->last) {
832832
buf->cur = buf->first;
833-
else
833+
buf->wrapped = true;
834+
} else {
834835
buf->cur = list_entry(buf->cur->list.next, struct topa,
835836
list);
837+
}
836838
buf->cur_idx = 0;
837839
}
838840
}
@@ -846,8 +848,11 @@ static void pt_buffer_advance(struct pt_buffer *buf)
846848
static void pt_update_head(struct pt *pt)
847849
{
848850
struct pt_buffer *buf = perf_get_aux(&pt->handle);
851+
bool wrapped = buf->wrapped;
849852
u64 topa_idx, base, old;
850853

854+
buf->wrapped = false;
855+
851856
if (buf->single) {
852857
local_set(&buf->data_size, buf->output_off);
853858
return;
@@ -865,7 +870,7 @@ static void pt_update_head(struct pt *pt)
865870
} else {
866871
old = (local64_xchg(&buf->head, base) &
867872
((buf->nr_pages << PAGE_SHIFT) - 1));
868-
if (base < old)
873+
if (base < old || (base == old && wrapped))
869874
base += buf->nr_pages << PAGE_SHIFT;
870875

871876
local_add(base - old, &buf->data_size);

arch/x86/events/intel/pt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct pt_pmu {
6565
* @head: logical write offset inside the buffer
6666
* @snapshot: if this is for a snapshot/overwrite counter
6767
* @single: use Single Range Output instead of ToPA
68+
* @wrapped: buffer advance wrapped back to the first topa table
6869
* @stop_pos: STOP topa entry index
6970
* @intr_pos: INT topa entry index
7071
* @stop_te: STOP topa entry pointer
@@ -82,6 +83,7 @@ struct pt_buffer {
8283
local64_t head;
8384
bool snapshot;
8485
bool single;
86+
bool wrapped;
8587
long stop_pos, intr_pos;
8688
struct topa_entry *stop_te, *intr_te;
8789
void **data_pages;

0 commit comments

Comments
 (0)