]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Dec 2024 08:23:19 +0000 (09:23 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Dec 2024 08:23:19 +0000 (09:23 +0100)
added patches:
perf-x86-intel-pt-fix-buffer-full-but-size-is-0-case.patch

queue-5.4/perf-x86-intel-pt-fix-buffer-full-but-size-is-0-case.patch [new file with mode: 0644]
queue-5.4/series

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 (file)
index 0000000..09b3541
--- /dev/null
@@ -0,0 +1,121 @@
+From 5b590160d2cf776b304eb054afafea2bd55e3620 Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+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 <adrian.hunter@intel.com>
+
+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 <adrian.hunter@intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: stable@vger.kernel.org
+Link: https://lkml.kernel.org/r/20241022155920.17511-2-adrian.hunter@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
index 3b9cdf50f7aaeed66ae32d50fd9535d562729927..ed3150be600618be4d72ae6959f987ddbae298d3 100644 (file)
@@ -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