Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ed70cf3 authored by Alexander Shishkin's avatar Alexander Shishkin Committed by Ingo Molnar
Browse files

perf/x86/pt, coresight: Clean up address filter structure



This is a cosmetic patch that deals with the address filter structure's
ambiguous fields 'filter' and 'range'. The former stands to mean that the
filter's *action* should be to filter the traces to its address range if
it's set or stop tracing if it's unset. This is confusing and hard on the
eyes, so this patch replaces it with 'action' enum. The 'range' field is
completely redundant (meaning that the filter is an address range as
opposed to a single address trigger), as we can use zero size to mean the
same thing.

Signed-off-by: default avatarAlexander Shishkin <alexander.shishkin@linux.intel.com>
Acked-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: Will Deacon <will.deacon@arm.com>
Link: http://lkml.kernel.org/r/20180329120648.11902-1-alexander.shishkin@linux.intel.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 2d074918
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -1186,8 +1186,12 @@ static int pt_event_addr_filters_validate(struct list_head *filters)
	int range = 0;

	list_for_each_entry(filter, filters, entry) {
		/* PT doesn't support single address triggers */
		if (!filter->range || !filter->size)
		/*
		 * PT doesn't support single address triggers and
		 * 'start' filters.
		 */
		if (!filter->size ||
		    filter->action == PERF_ADDR_FILTER_ACTION_START)
			return -EOPNOTSUPP;

		if (!filter->inode) {
@@ -1227,7 +1231,10 @@ static void pt_event_addr_filters_sync(struct perf_event *event)

		filters->filter[range].msr_a  = msr_a;
		filters->filter[range].msr_b  = msr_b;
		filters->filter[range].config = filter->filter ? 1 : 2;
		if (filter->action == PERF_ADDR_FILTER_ACTION_FILTER)
			filters->filter[range].config = 1;
		else
			filters->filter[range].config = 2;
		range++;
	}

+26 −33
Original line number Diff line number Diff line
@@ -393,35 +393,26 @@ static int etm_addr_filters_validate(struct list_head *filters)
		if (++index > ETM_ADDR_CMP_MAX)
			return -EOPNOTSUPP;

		/* filter::size==0 means single address trigger */
		if (filter->size) {
			/*
		 * As taken from the struct perf_addr_filter documentation:
		 *	@range:	1: range, 0: address
		 *
		 * At this time we don't allow range and start/stop filtering
		 * to cohabitate, they have to be mutually exclusive.
			 * The existing code relies on START/STOP filters
			 * being address filters.
			 */
		if ((filter->range == 1) && address)
			return -EOPNOTSUPP;

		if ((filter->range == 0) && range)
			if (filter->action == PERF_ADDR_FILTER_ACTION_START ||
			    filter->action == PERF_ADDR_FILTER_ACTION_STOP)
				return -EOPNOTSUPP;

		/*
		 * For range filtering, the second address in the address
		 * range comparator needs to be higher than the first.
		 * Invalid otherwise.
		 */
		if (filter->range && filter->size == 0)
			return -EINVAL;
			range = true;
		} else
			address = true;

		/*
		 * Everything checks out with this filter, record what we've
		 * received before moving on to the next one.
		 * At this time we don't allow range and start/stop filtering
		 * to cohabitate, they have to be mutually exclusive.
		 */
		if (filter->range)
			range = true;
		else
			address = true;
		if (range && address)
			return -EOPNOTSUPP;
	}

	return 0;
@@ -441,18 +432,20 @@ static void etm_addr_filters_sync(struct perf_event *event)
		stop = start + filter->size;
		etm_filter = &filters->etm_filter[i];

		if (filter->range == 1) {
		switch (filter->action) {
		case PERF_ADDR_FILTER_ACTION_FILTER:
			etm_filter->start_addr = start;
			etm_filter->stop_addr = stop;
			etm_filter->type = ETM_ADDR_TYPE_RANGE;
		} else {
			if (filter->filter == 1) {
			break;
		case PERF_ADDR_FILTER_ACTION_START:
			etm_filter->start_addr = start;
			etm_filter->type = ETM_ADDR_TYPE_START;
			} else {
			break;
		case PERF_ADDR_FILTER_ACTION_STOP:
			etm_filter->stop_addr = stop;
			etm_filter->type = ETM_ADDR_TYPE_STOP;
			}
			break;
		}
		i++;
	}
+9 −5
Original line number Diff line number Diff line
@@ -449,14 +449,19 @@ struct pmu {
	int (*filter_match)		(struct perf_event *event); /* optional */
};

enum perf_addr_filter_action_t {
	PERF_ADDR_FILTER_ACTION_STOP = 0,
	PERF_ADDR_FILTER_ACTION_START,
	PERF_ADDR_FILTER_ACTION_FILTER,
};

/**
 * struct perf_addr_filter - address range filter definition
 * @entry:	event's filter list linkage
 * @inode:	object file's inode for file-based filters
 * @offset:	filter range offset
 * @size:	filter range size
 * @range:	1: range, 0: address
 * @filter:	1: filter/start, 0: stop
 * @size:	filter range size (size==0 means single address trigger)
 * @action:	filter/start/stop
 *
 * This is a hardware-agnostic filter configuration as specified by the user.
 */
@@ -465,8 +470,7 @@ struct perf_addr_filter {
	struct inode		*inode;
	unsigned long		offset;
	unsigned long		size;
	unsigned int		range	: 1,
				filter	: 1;
	enum perf_addr_filter_action_t	action;
};

/**
+18 −8
Original line number Diff line number Diff line
@@ -8803,7 +8803,8 @@ static void perf_event_addr_filters_apply(struct perf_event *event)
 *  * for kernel addresses: <start address>[/<size>]
 *  * for object files:     <start address>[/<size>]@</path/to/object/file>
 *
 * if <size> is not specified, the range is treated as a single address.
 * if <size> is not specified or is zero, the range is treated as a single
 * address; not valid for ACTION=="filter".
 */
enum {
	IF_ACT_NONE = -1,
@@ -8853,6 +8854,11 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
		return -ENOMEM;

	while ((start = strsep(&fstr, " ,\n")) != NULL) {
		static const enum perf_addr_filter_action_t actions[] = {
			[IF_ACT_FILTER]	= PERF_ADDR_FILTER_ACTION_FILTER,
			[IF_ACT_START]	= PERF_ADDR_FILTER_ACTION_START,
			[IF_ACT_STOP]	= PERF_ADDR_FILTER_ACTION_STOP,
		};
		ret = -EINVAL;

		if (!*start)
@@ -8869,12 +8875,11 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
		switch (token) {
		case IF_ACT_FILTER:
		case IF_ACT_START:
			filter->filter = 1;

		case IF_ACT_STOP:
			if (state != IF_STATE_ACTION)
				goto fail;

			filter->action = actions[token];
			state = IF_STATE_SOURCE;
			break;

@@ -8887,15 +8892,12 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
			if (state != IF_STATE_SOURCE)
				goto fail;

			if (token == IF_SRC_FILE || token == IF_SRC_KERNEL)
				filter->range = 1;

			*args[0].to = 0;
			ret = kstrtoul(args[0].from, 0, &filter->offset);
			if (ret)
				goto fail;

			if (filter->range) {
			if (token == IF_SRC_KERNEL || token == IF_SRC_FILE) {
				*args[1].to = 0;
				ret = kstrtoul(args[1].from, 0, &filter->size);
				if (ret)
@@ -8903,7 +8905,7 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
			}

			if (token == IF_SRC_FILE || token == IF_SRC_FILEADDR) {
				int fpos = filter->range ? 2 : 1;
				int fpos = token == IF_SRC_FILE ? 2 : 1;

				filename = match_strdup(&args[fpos]);
				if (!filename) {
@@ -8929,6 +8931,14 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
			if (kernel && event->attr.exclude_kernel)
				goto fail;

			/*
			 * ACTION "filter" must have a non-zero length region
			 * specified.
			 */
			if (filter->action == PERF_ADDR_FILTER_ACTION_FILTER &&
			    !filter->size)
				goto fail;

			if (!kernel) {
				if (!filename)
					goto fail;