diff options
| author | David S. Miller <davem@davemloft.net> | 2012-10-02 23:02:10 -0400 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-10-02 23:02:10 -0400 | 
| commit | 954f9ac43b87b44152b8c21163cefd466a87145e (patch) | |
| tree | 31c4197f975c66c96976948663e6ce844900b41a /tools/perf/builtin-test.c | |
| parent | 1b62ca7bf5775bed048032b7e779561e1fe66aa0 (diff) | |
| parent | 7fe0b14b725d6d09a1d9e1409bd465cb88b587f9 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
There's a Niagara 2 memcpy fix in this tree and I have
a Kconfig fix from Dave Jones which requires the sparc-next
changes which went upstream yesterday.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/perf/builtin-test.c')
| -rw-r--r-- | tools/perf/builtin-test.c | 353 | 
1 files changed, 337 insertions, 16 deletions
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 1d592f5cbea9..484f26cc0c00 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -14,11 +14,13 @@  #include "util/symbol.h"  #include "util/thread_map.h"  #include "util/pmu.h" +#include "event-parse.h"  #include "../../include/linux/hw_breakpoint.h"  #include <sys/mman.h> -static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) +static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused, +					   struct symbol *sym)  {  	bool *visited = symbol__priv(sym);  	*visited = true; @@ -294,7 +296,7 @@ static int test__open_syscall_event(void)  		goto out_thread_map_delete;  	} -	if (perf_evsel__open_per_thread(evsel, threads, false, NULL) < 0) { +	if (perf_evsel__open_per_thread(evsel, threads) < 0) {  		pr_debug("failed to open counter: %s, "  			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",  			 strerror(errno)); @@ -369,7 +371,7 @@ static int test__open_syscall_event_on_all_cpus(void)  		goto out_thread_map_delete;  	} -	if (perf_evsel__open(evsel, cpus, threads, false, NULL) < 0) { +	if (perf_evsel__open(evsel, cpus, threads) < 0) {  		pr_debug("failed to open counter: %s, "  			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",  			 strerror(errno)); @@ -533,7 +535,7 @@ static int test__basic_mmap(void)  		perf_evlist__add(evlist, evsels[i]); -		if (perf_evsel__open(evsels[i], cpus, threads, false, NULL) < 0) { +		if (perf_evsel__open(evsels[i], cpus, threads) < 0) {  			pr_debug("failed to open counter: %s, "  				 "tweak /proc/sys/kernel/perf_event_paranoid?\n",  				 strerror(errno)); @@ -562,7 +564,7 @@ static int test__basic_mmap(void)  			goto out_munmap;  		} -		err = perf_evlist__parse_sample(evlist, event, &sample, false); +		err = perf_evlist__parse_sample(evlist, event, &sample);  		if (err) {  			pr_err("Can't parse sample, err = %d\n", err);  			goto out_munmap; @@ -710,7 +712,7 @@ static int test__PERF_RECORD(void)  	/*  	 * Config the evsels, setting attr->comm on the first one, etc.  	 */ -	evsel = list_entry(evlist->entries.next, struct perf_evsel, node); +	evsel = perf_evlist__first(evlist);  	evsel->attr.sample_type |= PERF_SAMPLE_CPU;  	evsel->attr.sample_type |= PERF_SAMPLE_TID;  	evsel->attr.sample_type |= PERF_SAMPLE_TIME; @@ -737,7 +739,7 @@ static int test__PERF_RECORD(void)  	 * Call sys_perf_event_open on all the fds on all the evsels,  	 * grouping them if asked to.  	 */ -	err = perf_evlist__open(evlist, opts.group); +	err = perf_evlist__open(evlist);  	if (err < 0) {  		pr_debug("perf_evlist__open: %s\n", strerror(errno));  		goto out_delete_evlist; @@ -779,7 +781,7 @@ static int test__PERF_RECORD(void)  				if (type < PERF_RECORD_MAX)  					nr_events[type]++; -				err = perf_evlist__parse_sample(evlist, event, &sample, false); +				err = perf_evlist__parse_sample(evlist, event, &sample);  				if (err < 0) {  					if (verbose)  						perf_event__fprintf(event, stderr); @@ -996,7 +998,9 @@ static u64 mmap_read_self(void *addr)  /*   * If the RDPMC instruction faults then signal this back to the test parent task:   */ -static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used) +static void segfault_handler(int sig __maybe_unused, +			     siginfo_t *info __maybe_unused, +			     void *uc __maybe_unused)  {  	exit(-1);  } @@ -1023,14 +1027,16 @@ static int __test__rdpmc(void)  	fd = sys_perf_event_open(&attr, 0, -1, -1, 0);  	if (fd < 0) { -		die("Error: sys_perf_event_open() syscall returned " -		    "with %d (%s)\n", fd, strerror(errno)); +		pr_err("Error: sys_perf_event_open() syscall returned " +		       "with %d (%s)\n", fd, strerror(errno)); +		return -1;  	}  	addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);  	if (addr == (void *)(-1)) { -		die("Error: mmap() syscall returned " -		    "with (%s)\n", strerror(errno)); +		pr_err("Error: mmap() syscall returned with (%s)\n", +		       strerror(errno)); +		goto out_close;  	}  	for (n = 0; n < 6; n++) { @@ -1051,9 +1057,9 @@ static int __test__rdpmc(void)  	}  	munmap(addr, page_size); -	close(fd); -  	pr_debug("   "); +out_close: +	close(fd);  	if (!delta_sum)  		return -1; @@ -1092,6 +1098,309 @@ static int test__perf_pmu(void)  	return perf_pmu__test();  } +static int perf_evsel__roundtrip_cache_name_test(void) +{ +	char name[128]; +	int type, op, err = 0, ret = 0, i, idx; +	struct perf_evsel *evsel; +        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); + +        if (evlist == NULL) +                return -ENOMEM; + +	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { +		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { +			/* skip invalid cache type */ +			if (!perf_evsel__is_cache_op_valid(type, op)) +				continue; + +			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { +				__perf_evsel__hw_cache_type_op_res_name(type, op, i, +									name, sizeof(name)); +				err = parse_events(evlist, name, 0); +				if (err) +					ret = err; +			} +		} +	} + +	idx = 0; +	evsel = perf_evlist__first(evlist); + +	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { +		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { +			/* skip invalid cache type */ +			if (!perf_evsel__is_cache_op_valid(type, op)) +				continue; + +			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { +				__perf_evsel__hw_cache_type_op_res_name(type, op, i, +									name, sizeof(name)); +				if (evsel->idx != idx) +					continue; + +				++idx; + +				if (strcmp(perf_evsel__name(evsel), name)) { +					pr_debug("%s != %s\n", perf_evsel__name(evsel), name); +					ret = -1; +				} + +				evsel = perf_evsel__next(evsel); +			} +		} +	} + +	perf_evlist__delete(evlist); +	return ret; +} + +static int __perf_evsel__name_array_test(const char *names[], int nr_names) +{ +	int i, err; +	struct perf_evsel *evsel; +        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); + +        if (evlist == NULL) +                return -ENOMEM; + +	for (i = 0; i < nr_names; ++i) { +		err = parse_events(evlist, names[i], 0); +		if (err) { +			pr_debug("failed to parse event '%s', err %d\n", +				 names[i], err); +			goto out_delete_evlist; +		} +	} + +	err = 0; +	list_for_each_entry(evsel, &evlist->entries, node) { +		if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { +			--err; +			pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); +		} +	} + +out_delete_evlist: +	perf_evlist__delete(evlist); +	return err; +} + +#define perf_evsel__name_array_test(names) \ +	__perf_evsel__name_array_test(names, ARRAY_SIZE(names)) + +static int perf_evsel__roundtrip_name_test(void) +{ +	int err = 0, ret = 0; + +	err = perf_evsel__name_array_test(perf_evsel__hw_names); +	if (err) +		ret = err; + +	err = perf_evsel__name_array_test(perf_evsel__sw_names); +	if (err) +		ret = err; + +	err = perf_evsel__roundtrip_cache_name_test(); +	if (err) +		ret = err; + +	return ret; +} + +static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, +				  int size, bool should_be_signed) +{ +	struct format_field *field = perf_evsel__field(evsel, name); +	int is_signed; +	int ret = 0; + +	if (field == NULL) { +		pr_debug("%s: \"%s\" field not found!\n", evsel->name, name); +		return -1; +	} + +	is_signed = !!(field->flags | FIELD_IS_SIGNED); +	if (should_be_signed && !is_signed) { +		pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", +			 evsel->name, name, is_signed, should_be_signed); +		ret = -1; +	} + +	if (field->size != size) { +		pr_debug("%s: \"%s\" size (%d) should be %d!\n", +			 evsel->name, name, field->size, size); +		ret = -1; +	} + +	return ret; +} + +static int perf_evsel__tp_sched_test(void) +{ +	struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0); +	int ret = 0; + +	if (evsel == NULL) { +		pr_debug("perf_evsel__new\n"); +		return -1; +	} + +	if (perf_evsel__test_field(evsel, "prev_comm", 16, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "prev_pid", 4, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "prev_prio", 4, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "prev_state", 8, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "next_comm", 16, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "next_pid", 4, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "next_prio", 4, true)) +		ret = -1; + +	perf_evsel__delete(evsel); + +	evsel = perf_evsel__newtp("sched", "sched_wakeup", 0); + +	if (perf_evsel__test_field(evsel, "comm", 16, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "pid", 4, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "prio", 4, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "success", 4, true)) +		ret = -1; + +	if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) +		ret = -1; + +	return ret; +} + +static int test__syscall_open_tp_fields(void) +{ +	struct perf_record_opts opts = { +		.target = { +			.uid = UINT_MAX, +			.uses_mmap = true, +		}, +		.no_delay   = true, +		.freq	    = 1, +		.mmap_pages = 256, +		.raw_samples = true, +	}; +	const char *filename = "/etc/passwd"; +	int flags = O_RDONLY | O_DIRECTORY; +	struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); +	struct perf_evsel *evsel; +	int err = -1, i, nr_events = 0, nr_polls = 0; + +	if (evlist == NULL) { +		pr_debug("%s: perf_evlist__new\n", __func__); +		goto out; +	} + +	evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); +	if (evsel == NULL) { +		pr_debug("%s: perf_evsel__newtp\n", __func__); +		goto out_delete_evlist; +	} + +	perf_evlist__add(evlist, evsel); + +	err = perf_evlist__create_maps(evlist, &opts.target); +	if (err < 0) { +		pr_debug("%s: perf_evlist__create_maps\n", __func__); +		goto out_delete_evlist; +	} + +	perf_evsel__config(evsel, &opts, evsel); + +	evlist->threads->map[0] = getpid(); + +	err = perf_evlist__open(evlist); +	if (err < 0) { +		pr_debug("perf_evlist__open: %s\n", strerror(errno)); +		goto out_delete_evlist; +	} + +	err = perf_evlist__mmap(evlist, UINT_MAX, false); +	if (err < 0) { +		pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); +		goto out_delete_evlist; +	} + +	perf_evlist__enable(evlist); + +	/* + 	 * Generate the event: + 	 */ +	open(filename, flags); + +	while (1) { +		int before = nr_events; + +		for (i = 0; i < evlist->nr_mmaps; i++) { +			union perf_event *event; + +			while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { +				const u32 type = event->header.type; +				int tp_flags; +				struct perf_sample sample; + +				++nr_events; + +				if (type != PERF_RECORD_SAMPLE) +					continue; + +				err = perf_evsel__parse_sample(evsel, event, &sample); +				if (err) { +					pr_err("Can't parse sample, err = %d\n", err); +					goto out_munmap; +				} + +				tp_flags = perf_evsel__intval(evsel, &sample, "flags"); + +				if (flags != tp_flags) { +					pr_debug("%s: Expected flags=%#x, got %#x\n", +						 __func__, flags, tp_flags); +					goto out_munmap; +				} + +				goto out_ok; +			} +		} + +		if (nr_events == before) +			poll(evlist->pollfd, evlist->nr_fds, 10); + +		if (++nr_polls > 5) { +			pr_debug("%s: no events!\n", __func__); +			goto out_munmap; +		} +	} +out_ok: +	err = 0; +out_munmap: +	perf_evlist__munmap(evlist); +out_delete_evlist: +	perf_evlist__delete(evlist); +out: +	return err; +} +  static struct test {  	const char *desc;  	int (*func)(void); @@ -1135,6 +1444,18 @@ static struct test {  		.func = dso__test_data,  	},  	{ +		.desc = "roundtrip evsel->name check", +		.func = perf_evsel__roundtrip_name_test, +	}, +	{ +		.desc = "Check parsing of sched tracepoints fields", +		.func = perf_evsel__tp_sched_test, +	}, +	{ +		.desc = "Generate and check syscalls:sys_enter_open event fields", +		.func = test__syscall_open_tp_fields, +	}, +	{  		.func = NULL,  	},  }; @@ -1199,7 +1520,7 @@ static int perf_test__list(int argc, const char **argv)  	return 0;  } -int cmd_test(int argc, const char **argv, const char *prefix __used) +int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)  {  	const char * const test_usage[] = {  	"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",  | 
