From: Greg Kroah-Hartman Date: Thu, 12 Dec 2024 08:23:19 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v5.4.287~52 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b687be4d512816258a1c35207ffba83c08b4b0cf;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: perf-x86-intel-pt-fix-buffer-full-but-size-is-0-case.patch --- diff --git a/queue-5.4/perf-x86-intel-pt-fix-buffer-full-but-size-is-0-case.patch b/queue-5.4/perf-x86-intel-pt-fix-buffer-full-but-size-is-0-case.patch new file mode 100644 index 00000000000..09b35413088 --- /dev/null +++ b/queue-5.4/perf-x86-intel-pt-fix-buffer-full-but-size-is-0-case.patch @@ -0,0 +1,121 @@ +From 5b590160d2cf776b304eb054afafea2bd55e3620 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Tue, 22 Oct 2024 18:59:07 +0300 +Subject: perf/x86/intel/pt: Fix buffer full but size is 0 case + +From: Adrian Hunter + +commit 5b590160d2cf776b304eb054afafea2bd55e3620 upstream. + +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: 52ca9ced3f70 ("perf/x86/intel/pt: Add Intel PT PMU driver") +Signed-off-by: Adrian Hunter +Signed-off-by: Peter Zijlstra (Intel) +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/20241022155920.17511-2-adrian.hunter@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/events/intel/pt.c | 11 ++++++++--- + arch/x86/events/intel/pt.h | 2 ++ + 2 files changed, 10 insertions(+), 3 deletions(-) + +--- a/arch/x86/events/intel/pt.c ++++ b/arch/x86/events/intel/pt.c +@@ -782,11 +782,13 @@ static void pt_buffer_advance(struct pt_ + buf->cur_idx++; + + if (buf->cur_idx == buf->cur->last) { +- if (buf->cur == buf->last) ++ if (buf->cur == buf->last) { + buf->cur = buf->first; +- else ++ buf->wrapped = true; ++ } else { + buf->cur = list_entry(buf->cur->list.next, struct topa, + list); ++ } + buf->cur_idx = 0; + } + } +@@ -800,8 +802,11 @@ static void pt_buffer_advance(struct pt_ + static void pt_update_head(struct pt *pt) + { + struct pt_buffer *buf = perf_get_aux(&pt->handle); ++ bool wrapped = buf->wrapped; + u64 topa_idx, base, old; + ++ buf->wrapped = false; ++ + /* offset of the first region in this table from the beginning of buf */ + base = buf->cur->offset + buf->output_off; + +@@ -814,7 +819,7 @@ static void pt_update_head(struct pt *pt + } else { + old = (local64_xchg(&buf->head, base) & + ((buf->nr_pages << PAGE_SHIFT) - 1)); +- if (base < old) ++ if (base < old || (base == old && wrapped)) + base += buf->nr_pages << PAGE_SHIFT; + + local_add(base - old, &buf->data_size); +--- a/arch/x86/events/intel/pt.h ++++ b/arch/x86/events/intel/pt.h +@@ -64,6 +64,7 @@ struct pt_pmu { + * @lost: if data was lost/truncated + * @head: logical write offset inside the buffer + * @snapshot: if this is for a snapshot/overwrite counter ++ * @wrapped: buffer advance wrapped back to the first topa table + * @stop_pos: STOP topa entry index + * @intr_pos: INT topa entry index + * @stop_te: STOP topa entry pointer +@@ -80,6 +81,7 @@ struct pt_buffer { + local_t data_size; + local64_t head; + bool snapshot; ++ bool wrapped; + long stop_pos, intr_pos; + struct topa_entry *stop_te, *intr_te; + void **data_pages; diff --git a/queue-5.4/series b/queue-5.4/series index 3b9cdf50f7a..ed3150be600 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -309,3 +309,4 @@ misc-eeprom-eeprom_93cx6-add-quirk-for-extra-read-cl.patch xdp-simplify-devmap-cleanup.patch bpf-fix-oob-devmap-writes-when-deleting-elements.patch revert-unicode-don-t-special-case-ignorable-code-points.patch +perf-x86-intel-pt-fix-buffer-full-but-size-is-0-case.patch