Skip to content

Commit 973f47a

Browse files
Leo-YanSuzuki K Poulose
authored andcommitted
coresight: perf: Update buffer on AUX pause
Due to sinks like ETR and ETB don't support interrupt handling, the hardware trace data might be lost for continuous running tasks. This commit takes advantage of the AUX pause for updating trace buffer to mitigate the trace data losing issue. The per CPU sink has its own interrupt handling. Thus, there will be a race condition between the updating buffer in NMI and sink's interrupt handler. To avoid the race condition, this commit disallows updating buffer on AUX pause for the per CPU sink. Currently, this is only applied for TRBE. Signed-off-by: Leo Yan <[email protected]> Reviewed-by: James Clark <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d5f7e4b commit 973f47a

File tree

1 file changed

+41
-2
lines changed

1 file changed

+41
-2
lines changed

drivers/hwtracing/coresight/coresight-etm-perf.c

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,14 +574,53 @@ static void etm_event_start(struct perf_event *event, int flags)
574574
return;
575575
}
576576

577-
static void etm_event_pause(struct coresight_device *csdev,
577+
static void etm_event_pause(struct perf_event *event,
578+
struct coresight_device *csdev,
578579
struct etm_ctxt *ctxt)
579580
{
581+
int cpu = smp_processor_id();
582+
struct coresight_device *sink;
583+
struct perf_output_handle *handle = &ctxt->handle;
584+
struct coresight_path *path;
585+
unsigned long size;
586+
580587
if (!ctxt->event_data)
581588
return;
582589

583590
/* Stop tracer */
584591
coresight_pause_source(csdev);
592+
593+
path = etm_event_cpu_path(ctxt->event_data, cpu);
594+
sink = coresight_get_sink(path);
595+
if (WARN_ON_ONCE(!sink))
596+
return;
597+
598+
/*
599+
* The per CPU sink has own interrupt handling, it might have
600+
* race condition with updating buffer on AUX trace pause if
601+
* it is invoked from NMI. To avoid the race condition,
602+
* disallows updating buffer for the per CPU sink case.
603+
*/
604+
if (coresight_is_percpu_sink(sink))
605+
return;
606+
607+
if (WARN_ON_ONCE(handle->event != event))
608+
return;
609+
610+
if (!sink_ops(sink)->update_buffer)
611+
return;
612+
613+
size = sink_ops(sink)->update_buffer(sink, handle,
614+
ctxt->event_data->snk_config);
615+
if (READ_ONCE(handle->event)) {
616+
if (!size)
617+
return;
618+
619+
perf_aux_output_end(handle, size);
620+
perf_aux_output_begin(handle, event);
621+
} else {
622+
WARN_ON_ONCE(size);
623+
}
585624
}
586625

587626
static void etm_event_stop(struct perf_event *event, int mode)
@@ -595,7 +634,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
595634
struct coresight_path *path;
596635

597636
if (mode & PERF_EF_PAUSE)
598-
return etm_event_pause(csdev, ctxt);
637+
return etm_event_pause(event, csdev, ctxt);
599638

600639
/*
601640
* If we still have access to the event_data via handle,

0 commit comments

Comments
 (0)