diff options
author | Michael Ellerman <mpe@ellerman.id.au> | 2014-07-23 03:31:40 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-07-28 00:11:33 -0400 |
commit | f929a4641b93c0a45f188022bb9675214b3070d6 (patch) | |
tree | 26696fca496506ab5d7c6aac12bc5d13b35260ab | |
parent | bd8bbd87f1e4226f576ddbc71d42541418d8f2d3 (diff) |
selftests/powerpc: Add test of per-event excludes
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | tools/testing/selftests/powerpc/pmu/Makefile | 2 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/pmu/per_event_excludes.c | 114 |
2 files changed, 115 insertions, 1 deletions
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile index 8595cfd7e41b..c9f4263906a5 100644 --- a/tools/testing/selftests/powerpc/pmu/Makefile +++ b/tools/testing/selftests/powerpc/pmu/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | noarg: | 1 | noarg: |
2 | $(MAKE) -C ../ | 2 | $(MAKE) -C ../ |
3 | 3 | ||
4 | PROGS := count_instructions l3_bank_test | 4 | PROGS := count_instructions l3_bank_test per_event_excludes |
5 | EXTRA_SOURCES := ../harness.c event.c lib.c | 5 | EXTRA_SOURCES := ../harness.c event.c lib.c |
6 | 6 | ||
7 | SUB_TARGETS = ebb | 7 | SUB_TARGETS = ebb |
diff --git a/tools/testing/selftests/powerpc/pmu/per_event_excludes.c b/tools/testing/selftests/powerpc/pmu/per_event_excludes.c new file mode 100644 index 000000000000..fddbbc9cae2f --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/per_event_excludes.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Copyright 2014, Michael Ellerman, IBM Corp. | ||
3 | * Licensed under GPLv2. | ||
4 | */ | ||
5 | |||
6 | #define _GNU_SOURCE | ||
7 | |||
8 | #include <elf.h> | ||
9 | #include <limits.h> | ||
10 | #include <stdio.h> | ||
11 | #include <stdbool.h> | ||
12 | #include <string.h> | ||
13 | #include <sys/prctl.h> | ||
14 | |||
15 | #include "event.h" | ||
16 | #include "lib.h" | ||
17 | #include "utils.h" | ||
18 | |||
19 | /* | ||
20 | * Test that per-event excludes work. | ||
21 | */ | ||
22 | |||
23 | static int per_event_excludes(void) | ||
24 | { | ||
25 | struct event *e, events[4]; | ||
26 | char *platform; | ||
27 | int i; | ||
28 | |||
29 | platform = (char *)get_auxv_entry(AT_BASE_PLATFORM); | ||
30 | FAIL_IF(!platform); | ||
31 | SKIP_IF(strcmp(platform, "power8") != 0); | ||
32 | |||
33 | /* | ||
34 | * We need to create the events disabled, otherwise the running/enabled | ||
35 | * counts don't match up. | ||
36 | */ | ||
37 | e = &events[0]; | ||
38 | event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
39 | PERF_TYPE_HARDWARE, "instructions"); | ||
40 | e->attr.disabled = 1; | ||
41 | |||
42 | e = &events[1]; | ||
43 | event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
44 | PERF_TYPE_HARDWARE, "instructions(k)"); | ||
45 | e->attr.disabled = 1; | ||
46 | e->attr.exclude_user = 1; | ||
47 | e->attr.exclude_hv = 1; | ||
48 | |||
49 | e = &events[2]; | ||
50 | event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
51 | PERF_TYPE_HARDWARE, "instructions(h)"); | ||
52 | e->attr.disabled = 1; | ||
53 | e->attr.exclude_user = 1; | ||
54 | e->attr.exclude_kernel = 1; | ||
55 | |||
56 | e = &events[3]; | ||
57 | event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS, | ||
58 | PERF_TYPE_HARDWARE, "instructions(u)"); | ||
59 | e->attr.disabled = 1; | ||
60 | e->attr.exclude_hv = 1; | ||
61 | e->attr.exclude_kernel = 1; | ||
62 | |||
63 | FAIL_IF(event_open(&events[0])); | ||
64 | |||
65 | /* | ||
66 | * The open here will fail if we don't have per event exclude support, | ||
67 | * because the second event has an incompatible set of exclude settings | ||
68 | * and we're asking for the events to be in a group. | ||
69 | */ | ||
70 | for (i = 1; i < 4; i++) | ||
71 | FAIL_IF(event_open_with_group(&events[i], events[0].fd)); | ||
72 | |||
73 | /* | ||
74 | * Even though the above will fail without per-event excludes we keep | ||
75 | * testing in order to be thorough. | ||
76 | */ | ||
77 | prctl(PR_TASK_PERF_EVENTS_ENABLE); | ||
78 | |||
79 | /* Spin for a while */ | ||
80 | for (i = 0; i < INT_MAX; i++) | ||
81 | asm volatile("" : : : "memory"); | ||
82 | |||
83 | prctl(PR_TASK_PERF_EVENTS_DISABLE); | ||
84 | |||
85 | for (i = 0; i < 4; i++) { | ||
86 | FAIL_IF(event_read(&events[i])); | ||
87 | event_report(&events[i]); | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * We should see that all events have enabled == running. That | ||
92 | * shows that they were all on the PMU at once. | ||
93 | */ | ||
94 | for (i = 0; i < 4; i++) | ||
95 | FAIL_IF(events[i].result.running != events[i].result.enabled); | ||
96 | |||
97 | /* | ||
98 | * We can also check that the result for instructions is >= all the | ||
99 | * other counts. That's because it is counting all instructions while | ||
100 | * the others are counting a subset. | ||
101 | */ | ||
102 | for (i = 1; i < 4; i++) | ||
103 | FAIL_IF(events[0].result.value < events[i].result.value); | ||
104 | |||
105 | for (i = 0; i < 4; i++) | ||
106 | event_close(&events[i]); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | int main(void) | ||
112 | { | ||
113 | return test_harness(per_event_excludes, "per_event_excludes"); | ||
114 | } | ||