Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1251528

Re: [PATCH V2 22/30] coresight: etm-perf: new PMU driver for ETM tracers

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

Show all headers | View raw


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 | NextPrevious in thread | Next in thread | Find similar | Unroll thread


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