Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1251528
| From | Alexander Shishkin <alexander.shishkin@linux.intel.com> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | Re: [PATCH V2 22/30] coresight: etm-perf: new PMU driver for ETM tracers |
| Date | 2015-10-20 11:40 +0200 |
| Message-ID | <qlByH-87B-29@gated-at.bofh.it> (permalink) |
| References | <ql0St-4NE-3@gated-at.bofh.it> <ql0Sv-4NE-45@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
Mathieu Poirier <mathieu.poirier@linaro.org> writes:
> +static void *etm_setup_aux(struct perf_event *event, void **pages,
> + int nr_pages, bool overwrite)
> +{
> + int cpu;
> + cpumask_t *mask;
> + struct etm_event_data *event_data = NULL;
> + struct coresight_device *csdev;
> +
> + event_data = alloc_event_data(event->cpu);
> + if (!event_data)
> + return NULL;
> +
> + mask = &event_data->mask;
> +
> + if (event->cpu != -1)
> + cpumask_set_cpu(event->cpu, mask);
> + else
> + cpumask_copy(mask, cpu_online_mask);
> +
> + for_each_cpu(cpu, mask) {
> + struct coresight_device *sink;
> +
> + csdev = per_cpu(csdev_src, cpu);
> + if (!csdev)
> + goto err;
> +
> + /* Get the tracer's config from perf */
> + if (!source_ops(csdev)->perf_get_config)
> + goto err;
> +
> + event_data->source_config[cpu] =
> + source_ops(csdev)->perf_get_config(csdev, event);
> +
> + if (!event_data->source_config[cpu])
> + goto err;
> +
> + /*
> + * Get a handle on the sink buffer associated
> + * with this tracer.
> + */
> + event_data->sink[cpu] = (void *)etm_event_build_path(cpu, true);
There are several problems here. What is created/allocated during
setup_aux(), has to be undone in free_aux(), however, the effect of
build_path() will only be undone in the event::destroy() path. So if the
user unmaps the aux buffer and then maps it again, we'll go ahead and
try to build the path again. (Btw, coresight_build_paths() and other
non-static functions and especially exported ones are really lacking
documentation at the moment).
It really looks like this has to be done in pmu::add(), so that the
source<=>sink connection exists only while the event is scheduled and
otherwise other events are free to connect their sources to these
sinks. And at pmu::del() the connection has to be torn down. This way we
can have a sensible multisession support. That is, provided my
understanding of the coresight driver architecture is correct.
Also, you won't have to configure things on multiple cpus for cpu==-1 if
you keep the source<=>sink connection only between pmu::add() and
pmu::del(), as an event can only be scheduled on one cpu at a time,
which should make things simpler.
> +
> + if (!event_data->sink[cpu])
> + goto err;
> +
> + sink = event_data->sink[cpu];
> +
> + if (!sink_ops(sink)->setup_aux)
> + goto err;
> +
> + /* Finally get the AUX specific data from the sink buffer */
> + event_data->sink_config[cpu] =
> + sink_ops(sink)->setup_aux(sink, cpu, pages,
> + nr_pages, overwrite);
Now this is a sensible thing to do. I understand that you'll have to
know which sink you're using so that you can pick the right sink_ops and
build an appropriate configuration, but perhaps it also makes sense to
release it once you got the sink_config.
> +static void etm_event_stop(struct perf_event *event, int mode)
> +{
> + int cpu = smp_processor_id();
> + struct coresight_device *csdev = per_cpu(csdev_src, cpu);
> +
> + if (event->hw.state == PERF_HES_STOPPED)
> + return;
> +
> + if (!csdev)
> + return;
> +
> + /* stop tracer */
> + if (!source_ops(csdev)->perf_disable)
> + return;
This really shouldn't happen. It makes sense to make sure that we have
all the callbacks that we rely on in pmu::event_init() or pmu::add() and
refuse to start if we don't, but at this point we really shouldn't end
up in a situation where we suddenly don't have one of the callbacks.
> + if (source_ops(csdev)->perf_disable(csdev))
> + return;
This has a similar problem. I'd say that this callback should not be
able to fail and return anything other than success.
> + /* tell the core */
> + event->hw.state = PERF_HES_STOPPED;
> +
> +
> + if (mode & PERF_EF_UPDATE) {
> + struct coresight_device *sink;
> + struct perf_output_handle *handle = this_cpu_ptr(&ctx_handle);
> + struct etm_event_data *event_data = perf_get_aux(handle);
> +
> + if (WARN_ON_ONCE(handle->event != event))
> + return;
> +
> + if (WARN_ON_ONCE(!event_data))
> + return;
> +
> + sink = event_data->sink[cpu];
> + if (WARN_ON_ONCE(!sink))
> + return;
> +
> + /* update trace information */
> + if (!sink_ops(sink)->update_buffer)
> + return;
> +
> + sink_ops(sink)->update_buffer(sink, handle,
> + event_data->sink_config[cpu]);
> + }
> +}
> +
> +static void etm_event_start(struct perf_event *event, int flags)
> +{
> + int cpu = smp_processor_id();
> + struct coresight_device *csdev = per_cpu(csdev_src, cpu);
> +
> + if (!csdev)
> + goto fail;
> +
> + /* tell the perf core the event is alive */
> + event->hw.state = 0;
> +
> + if (!source_ops(csdev)->perf_enable)
> + goto fail;
Same here.
> +
> + if (source_ops(csdev)->perf_enable(csdev))
> + goto fail;
This may fail, I suppose.
> +
> + return;
> +
> +fail:
> + event->hw.state = PERF_HES_STOPPED;
> +}
> +
> +static void etm_event_del(struct perf_event *event, int mode)
> +{
> + int cpu = smp_processor_id();
> + struct coresight_device *sink;
> + struct perf_output_handle *handle = this_cpu_ptr(&ctx_handle);
> + struct etm_event_data *event_data = perf_get_aux(handle);
> +
> + if (WARN_ON_ONCE(!event_data))
> + return;
> +
> + sink = event_data->sink[cpu];
> + if (!sink)
> + return;
This also shouldn't be able to prevent us from stopping the event.
> +
> + etm_event_stop(event, PERF_EF_UPDATE);
> +
> + if (!sink_ops(sink)->reset_buffer)
> + return;
> +
> + sink_ops(sink)->reset_buffer(sink, handle,
> + event_data->sink_config[cpu]);
> +}
> +
> +static int etm_event_add(struct perf_event *event, int mode)
> +{
> +
> + int ret = -EBUSY, cpu = smp_processor_id();
> + struct etm_event_data *event_data;
> + struct perf_output_handle *handle = this_cpu_ptr(&ctx_handle);
> + struct hw_perf_event *hwc = &event->hw;
> + struct coresight_device *csdev = per_cpu(csdev_src, cpu);
> + struct coresight_device *sink;
> +
> + if (handle->event)
> + goto out;
> +
> + event_data = perf_aux_output_begin(handle, event);
> + ret = -EINVAL;
> + if (WARN_ON_ONCE(!event_data))
> + goto fail_stop;
> +
> + sink = event_data->sink[cpu];
So if you're able to fetch the sink right here and release it in
_del(). Of course, this being a hot path and an atomic context needs to
be taken into account.
Regards,
--
Alex
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[PATCH V2 00/30] Coresight integration with perf Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 18/30] coresight: etb10: moving to local atomic operations Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 30/30] perf tools: adding coresight etm PMU record capabilities Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 19/30] coresight: etb10: implementing the setup_aux() API Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
Re: [PATCH V2 19/30] coresight: etb10: implementing the setup_aux() API Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2015-10-19 15:50 +0200
Re: [PATCH V2 19/30] coresight: etb10: implementing the setup_aux() API Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-20 18:50 +0200
Re: [PATCH V2 19/30] coresight: etb10: implementing the setup_aux() API Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2015-10-20 13:50 +0200
[PATCH V2 07/30] coresight: etm3x: moving etm_drvdata::enable to atomic field Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 05/30] coresight: etm3x: set progbit to stop trace collection Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 22/30] coresight: etm-perf: new PMU driver for ETM tracers Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
Re: [PATCH V2 22/30] coresight: etm-perf: new PMU driver for ETM tracers Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2015-10-19 17:50 +0200
Re: [PATCH V2 22/30] coresight: etm-perf: new PMU driver for ETM tracers Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-20 18:50 +0200
Re: [PATCH V2 22/30] coresight: etm-perf: new PMU driver for ETM tracers Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2015-10-20 11:40 +0200
Re: [PATCH V2 22/30] coresight: etm-perf: new PMU driver for ETM tracers Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-20 21:20 +0200
[PATCH V2 25/30] perf tools: adding perf_session to *info_prive_size() Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 10/30] coresight: etm3x: consolidating initial config Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 26/30] perf tools: making source devices path broadly accessible Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 21/30] coresight: etb10: implementing buffer update API Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:30 +0200
[PATCH V2 15/30] coresight: making coresight_build_paths() public Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
[PATCH V2 08/30] coresight: etm3x: implementing 'cpu_id()' API Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
[PATCH V2 17/30] perf: changing pmu::setup_aux() parameter to include event Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
Re: [PATCH V2 17/30] perf: changing pmu::setup_aux() parameter to include event Alexander Shishkin <alexander.shishkin@linux.intel.com> - 2015-10-19 15:40 +0200
[PATCH V2 06/30] coresight: clearly labeling source operarions Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
[PATCH V2 12/30] coresight: etm3x: adding perf_get/set_config() API Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
[PATCH V2 03/30] coresight: etm3x: unlocking tracers in default arch init Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
[PATCH V2 11/30] coresight: etm3x: implementing user/kernel mode tracing Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
[PATCH V2 09/30] coresight: etm3x: changing default trace configuration Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
[PATCH V2 01/30] coresight: etm3x: moving etm_readl/writel to header file Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
Re: [PATCH V2 01/30] coresight: etm3x: moving etm_readl/writel to header file Greg KH <gregkh@linuxfoundation.org> - 2015-10-19 20:40 +0200
[PATCH V2 13/30] coresight: etm3x: implementing perf_enable/disable() API Mathieu Poirier <mathieu.poirier@linaro.org> - 2015-10-18 20:40 +0200
csiph-web