UPSTREAM: coresight: tmc-etr: Fix updating buffer in not-snapshot mode.

(Upstream commit 13af88f312).

TMC etr always copies all available data to perf aux buffer, which
may exceed the available space in perf aux buffer. It isn't suitable
for not-snapshot mode, because:
1) It may overwrite previously written data.
2) It may make the perf_event_mmap_page->aux_head report having more
or less data than the reality.

So change to only copy the latest data fitting the available space in
perf aux buffer.

Signed-off-by: Yabin Cui <yabinc@google.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: https://lore.kernel.org/r/20190829202842.580-14-mathieu.poirier@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Bug: 140266694
Change-Id: Idcdd505c77637d0dc3329a1d145ddca20ca895da
Signed-off-by: Yabin Cui <yabinc@google.com>
This commit is contained in:
Yabin Cui
2019-08-29 14:28:38 -06:00
parent f071d3702c
commit c3595fdc72

View File

@@ -1406,9 +1406,10 @@ free_etr_perf_buffer:
* tmc_etr_sync_perf_buffer: Copy the actual trace data from the hardware
* buffer to the perf ring buffer.
*/
static void tmc_etr_sync_perf_buffer(struct etr_perf_buffer *etr_perf)
static void tmc_etr_sync_perf_buffer(struct etr_perf_buffer *etr_perf,
unsigned long to_copy)
{
long bytes, to_copy;
long bytes;
long pg_idx, pg_offset, src_offset;
unsigned long head = etr_perf->head;
char **dst_pages, *src_buf;
@@ -1418,8 +1419,7 @@ static void tmc_etr_sync_perf_buffer(struct etr_perf_buffer *etr_perf)
pg_idx = head >> PAGE_SHIFT;
pg_offset = head & (PAGE_SIZE - 1);
dst_pages = (char **)etr_perf->pages;
src_offset = etr_buf->offset;
to_copy = etr_buf->len;
src_offset = etr_buf->offset + etr_buf->len - to_copy;
while (to_copy > 0) {
/*
@@ -1430,6 +1430,8 @@ static void tmc_etr_sync_perf_buffer(struct etr_perf_buffer *etr_perf)
* 3) what is available in the destination page.
* in one iteration.
*/
if (src_offset >= etr_buf->size)
src_offset -= etr_buf->size;
bytes = tmc_etr_buf_get_data(etr_buf, src_offset, to_copy,
&src_buf);
if (WARN_ON_ONCE(bytes <= 0))
@@ -1450,8 +1452,6 @@ static void tmc_etr_sync_perf_buffer(struct etr_perf_buffer *etr_perf)
/* Move source pointers */
src_offset += bytes;
if (src_offset >= etr_buf->size)
src_offset -= etr_buf->size;
}
}
@@ -1497,7 +1497,11 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
spin_unlock_irqrestore(&drvdata->spinlock, flags);
size = etr_buf->len;
tmc_etr_sync_perf_buffer(etr_perf);
if (!etr_perf->snapshot && size > handle->size) {
size = handle->size;
lost = true;
}
tmc_etr_sync_perf_buffer(etr_perf, size);
/*
* In snapshot mode we simply increment the head by the number of byte