Message ID | 20231215064242.36251-1-adrian.hunter@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | None | expand |
On 15/12/2023 06:42, Adrian Hunter wrote: > For discussion only, un-tested... > If anyone wants to test Coresight, the diff below is required to get the most basic use case working. It also probably needs more thought and some edge case handling: diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index 596c01e37624..bd0767356277 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -556,7 +556,8 @@ static void etm_event_stop(struct perf_event *event, int mode) struct etm_event_data *event_data; struct list_head *path; - if (mode & PERF_EF_PAUSE && !READ_ONCE(ctxt->pr_allowed)) + if ((mode & PERF_EF_PAUSE && !READ_ONCE(ctxt->pr_allowed)) || + event->hw.state == PERF_HES_STOPPED) return; WRITE_ONCE(ctxt->pr_allowed, 0); @@ -573,9 +574,6 @@ static void etm_event_stop(struct perf_event *event, int mode) /* Clear the event_data as this ETM is stopping the trace. */ ctxt->event_data = NULL; - if (event->hw.state == PERF_HES_STOPPED) - goto out_pr_allowed; - /* We must have a valid event_data for a running event */ if (WARN_ON(!event_data)) return; @@ -586,7 +584,7 @@ static void etm_event_stop(struct perf_event *event, int mode) * nothing needs to be torn down other than outputting a * zero sized record. */ - if (handle->event && (mode & PERF_EF_UPDATE) && + if (handle->event && (mode & (PERF_EF_UPDATE | PERF_EF_PAUSE)) && !cpumask_test_cpu(cpu, &event_data->mask)) { event->hw.state = PERF_HES_STOPPED; perf_aux_output_end(handle, 0); @@ -616,7 +614,7 @@ static void etm_event_stop(struct perf_event *event, int mode) * handle due to lack of buffer space), we don't * have to do anything here. */ - if (handle->event && (mode & PERF_EF_UPDATE)) { + if (handle->event && (mode & (PERF_EF_UPDATE | PERF_EF_PAUSE))) { if (WARN_ON_ONCE(handle->event != event)) return; @@ -646,7 +644,6 @@ static void etm_event_stop(struct perf_event *event, int mode) /* Disabling the path make its elements available to other sessions */ coresight_disable_path(path); -out_pr_allowed: if (mode & PERF_EF_PAUSE) WRITE_ONCE(ctxt->pr_allowed, 1); } @@ -656,7 +653,7 @@ static int etm_event_add(struct perf_event *event, int mode) int ret = 0; struct hw_perf_event *hwc = &event->hw; - if (mode & PERF_EF_START && !READ_ONCE(event->aux_paused)) { + if (mode & PERF_EF_START) { etm_event_start(event, 0); if (hwc->state & PERF_HES_STOPPED) ret = -EINVAL;
On 20/12/23 17:59, James Clark wrote: > > > On 15/12/2023 06:42, Adrian Hunter wrote: >> For discussion only, un-tested... >> > > If anyone wants to test Coresight, the diff below is required to get the > most basic use case working. It also probably needs more thought and > some edge case handling: Makes sense to me > > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c > index 596c01e37624..bd0767356277 100644 > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c > @@ -556,7 +556,8 @@ static void etm_event_stop(struct perf_event *event, int mode) > struct etm_event_data *event_data; > struct list_head *path; > > - if (mode & PERF_EF_PAUSE && !READ_ONCE(ctxt->pr_allowed)) > + if ((mode & PERF_EF_PAUSE && !READ_ONCE(ctxt->pr_allowed)) || > + event->hw.state == PERF_HES_STOPPED) > return; > > WRITE_ONCE(ctxt->pr_allowed, 0); > @@ -573,9 +574,6 @@ static void etm_event_stop(struct perf_event *event, int mode) > /* Clear the event_data as this ETM is stopping the trace. */ > ctxt->event_data = NULL; > > - if (event->hw.state == PERF_HES_STOPPED) > - goto out_pr_allowed; > - > /* We must have a valid event_data for a running event */ > if (WARN_ON(!event_data)) > return; > @@ -586,7 +584,7 @@ static void etm_event_stop(struct perf_event *event, int mode) > * nothing needs to be torn down other than outputting a > * zero sized record. > */ > - if (handle->event && (mode & PERF_EF_UPDATE) && > + if (handle->event && (mode & (PERF_EF_UPDATE | PERF_EF_PAUSE)) && > !cpumask_test_cpu(cpu, &event_data->mask)) { > event->hw.state = PERF_HES_STOPPED; > perf_aux_output_end(handle, 0); > @@ -616,7 +614,7 @@ static void etm_event_stop(struct perf_event *event, int mode) > * handle due to lack of buffer space), we don't > * have to do anything here. > */ > - if (handle->event && (mode & PERF_EF_UPDATE)) { > + if (handle->event && (mode & (PERF_EF_UPDATE | PERF_EF_PAUSE))) { > if (WARN_ON_ONCE(handle->event != event)) > return; > > @@ -646,7 +644,6 @@ static void etm_event_stop(struct perf_event *event, int mode) > /* Disabling the path make its elements available to other sessions */ > coresight_disable_path(path); > > -out_pr_allowed: > if (mode & PERF_EF_PAUSE) > WRITE_ONCE(ctxt->pr_allowed, 1); > } > @@ -656,7 +653,7 @@ static int etm_event_add(struct perf_event *event, int mode) > int ret = 0; > struct hw_perf_event *hwc = &event->hw; > > - if (mode & PERF_EF_START && !READ_ONCE(event->aux_paused)) { > + if (mode & PERF_EF_START) { > etm_event_start(event, 0); > if (hwc->state & PERF_HES_STOPPED) > ret = -EINVAL;
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index 5ca6278baff4..7a69e6417ed4 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -45,6 +45,7 @@ static bool etm_perf_up; struct etm_ctxt { struct perf_output_handle handle; struct etm_event_data *event_data; + int pr_allowed; }; static DEFINE_PER_CPU(struct etm_ctxt, etm_ctxt); @@ -452,6 +453,13 @@ static void etm_event_start(struct perf_event *event, int flags) struct list_head *path; u64 hw_id; + if (flags & PERF_EF_RESUME) { + if (!READ_ONCE(ctxt->pr_allowed)) + return; + } else if (READ_ONCE(event->aux_paused)) { + goto out_pr_allowed; + } + if (!csdev) goto fail; @@ -514,6 +522,8 @@ static void etm_event_start(struct perf_event *event, int flags) event->hw.state = 0; /* Save the event_data for this ETM */ ctxt->event_data = event_data; +out_pr_allowed: + WRITE_ONCE(ctxt->pr_allowed, 1); return; fail_disable_path: @@ -530,6 +540,7 @@ static void etm_event_start(struct perf_event *event, int flags) } fail: event->hw.state = PERF_HES_STOPPED; + WRITE_ONCE(ctxt->pr_allowed, 0); return; } @@ -543,6 +554,11 @@ static void etm_event_stop(struct perf_event *event, int mode) struct etm_event_data *event_data; struct list_head *path; + if (mode & PERF_EF_PAUSE && !READ_ONCE(ctxt->pr_allowed)) + return; + + WRITE_ONCE(ctxt->pr_allowed, 0); + /* * If we still have access to the event_data via handle, * confirm that we haven't messed up the tracking. @@ -556,7 +572,7 @@ static void etm_event_stop(struct perf_event *event, int mode) ctxt->event_data = NULL; if (event->hw.state == PERF_HES_STOPPED) - return; + goto out_pr_allowed; /* We must have a valid event_data for a running event */ if (WARN_ON(!event_data)) @@ -627,6 +643,10 @@ static void etm_event_stop(struct perf_event *event, int mode) /* Disabling the path make its elements available to other sessions */ coresight_disable_path(path); + +out_pr_allowed: + if (mode & PERF_EF_PAUSE) + WRITE_ONCE(ctxt->pr_allowed, 1); } static int etm_event_add(struct perf_event *event, int mode) @@ -634,7 +654,7 @@ static int etm_event_add(struct perf_event *event, int mode) int ret = 0; struct hw_perf_event *hwc = &event->hw; - if (mode & PERF_EF_START) { + if (mode & PERF_EF_START && !READ_ONCE(event->aux_paused)) { etm_event_start(event, 0); if (hwc->state & PERF_HES_STOPPED) ret = -EINVAL; @@ -886,8 +906,9 @@ int __init etm_perf_init(void) { int ret; - etm_pmu.capabilities = (PERF_PMU_CAP_EXCLUSIVE | - PERF_PMU_CAP_ITRACE); + etm_pmu.capabilities = PERF_PMU_CAP_EXCLUSIVE | + PERF_PMU_CAP_ITRACE | + PERF_PMU_CAP_AUX_PAUSE; etm_pmu.attr_groups = etm_pmu_attr_groups; etm_pmu.task_ctx_nr = perf_sw_context;
For discussion only, un-tested... Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- Changes in V3: 'mode' -> 'flags' so it at least compiles .../hwtracing/coresight/coresight-etm-perf.c | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-)