diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-12-08 05:50:24 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-12-08 05:50:24 -0500 |
commit | 2a2662bf88e693d477ef08351d03934f7bc0b51c (patch) | |
tree | cef243df159cc12ada7e97998a253df7c0abb2a2 /tools/perf/tests | |
parent | b2776bf7149bddd1f4161f14f79520f17fc1d71d (diff) | |
parent | 36748b9518a2437beffe861b47dff6d12b736b3f (diff) |
Merge branch 'perf/core-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into perf/hw_breakpoints
Pull AMD range breakpoints support from Frederic Weisbecker:
" - Extend breakpoint tools and core to support address range through perf
event with initial backend support for AMD extended breakpoints.
Syntax is:
perf record -e mem:addr/len:type
For example set write breakpoint from 0x1000 to 0x1200 (0x1000 + 512)
perf record -e mem:0x1000/512:w
- Clean up a bit breakpoint code validation
It has been acked by Jiri and Oleg. "
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/tests')
-rw-r--r-- | tools/perf/tests/builtin-test.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/code-reading.c | 13 | ||||
-rw-r--r-- | tools/perf/tests/dwarf-unwind.c | 18 | ||||
-rw-r--r-- | tools/perf/tests/hists_filter.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/mmap-thread-lookup.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/parse-events.c | 58 | ||||
-rw-r--r-- | tools/perf/tests/sample-parsing.c | 55 |
7 files changed, 115 insertions, 35 deletions
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 162c978f1491..4b7d9ab0f049 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -85,7 +85,7 @@ static struct test { | |||
85 | .func = test__hists_link, | 85 | .func = test__hists_link, |
86 | }, | 86 | }, |
87 | { | 87 | { |
88 | .desc = "Try 'use perf' in python, checking link problems", | 88 | .desc = "Try 'import perf' in python, checking link problems", |
89 | .func = test__python_use, | 89 | .func = test__python_use, |
90 | }, | 90 | }, |
91 | { | 91 | { |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 67f2d6323558..f671ec37a7c4 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -133,8 +133,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf, | |||
133 | } | 133 | } |
134 | 134 | ||
135 | static int read_object_code(u64 addr, size_t len, u8 cpumode, | 135 | static int read_object_code(u64 addr, size_t len, u8 cpumode, |
136 | struct thread *thread, struct machine *machine, | 136 | struct thread *thread, struct state *state) |
137 | struct state *state) | ||
138 | { | 137 | { |
139 | struct addr_location al; | 138 | struct addr_location al; |
140 | unsigned char buf1[BUFSZ]; | 139 | unsigned char buf1[BUFSZ]; |
@@ -145,8 +144,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, | |||
145 | 144 | ||
146 | pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); | 145 | pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); |
147 | 146 | ||
148 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr, | 147 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al); |
149 | &al); | ||
150 | if (!al.map || !al.map->dso) { | 148 | if (!al.map || !al.map->dso) { |
151 | pr_debug("thread__find_addr_map failed\n"); | 149 | pr_debug("thread__find_addr_map failed\n"); |
152 | return -1; | 150 | return -1; |
@@ -170,8 +168,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, | |||
170 | len = al.map->end - addr; | 168 | len = al.map->end - addr; |
171 | 169 | ||
172 | /* Read the object code using perf */ | 170 | /* Read the object code using perf */ |
173 | ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1, | 171 | ret_len = dso__data_read_offset(al.map->dso, thread->mg->machine, |
174 | len); | 172 | al.addr, buf1, len); |
175 | if (ret_len != len) { | 173 | if (ret_len != len) { |
176 | pr_debug("dso__data_read_offset failed\n"); | 174 | pr_debug("dso__data_read_offset failed\n"); |
177 | return -1; | 175 | return -1; |
@@ -264,8 +262,7 @@ static int process_sample_event(struct machine *machine, | |||
264 | 262 | ||
265 | cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 263 | cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
266 | 264 | ||
267 | return read_object_code(sample.ip, READLEN, cpumode, thread, machine, | 265 | return read_object_code(sample.ip, READLEN, cpumode, thread, state); |
268 | state); | ||
269 | } | 266 | } |
270 | 267 | ||
271 | static int process_event(struct machine *machine, struct perf_evlist *evlist, | 268 | static int process_event(struct machine *machine, struct perf_evlist *evlist, |
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index fc25e57f4a5d..ab28cca2cb97 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c | |||
@@ -59,7 +59,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) | |||
59 | } | 59 | } |
60 | 60 | ||
61 | __attribute__ ((noinline)) | 61 | __attribute__ ((noinline)) |
62 | static int unwind_thread(struct thread *thread, struct machine *machine) | 62 | static int unwind_thread(struct thread *thread) |
63 | { | 63 | { |
64 | struct perf_sample sample; | 64 | struct perf_sample sample; |
65 | unsigned long cnt = 0; | 65 | unsigned long cnt = 0; |
@@ -72,7 +72,7 @@ static int unwind_thread(struct thread *thread, struct machine *machine) | |||
72 | goto out; | 72 | goto out; |
73 | } | 73 | } |
74 | 74 | ||
75 | err = unwind__get_entries(unwind_entry, &cnt, machine, thread, | 75 | err = unwind__get_entries(unwind_entry, &cnt, thread, |
76 | &sample, MAX_STACK); | 76 | &sample, MAX_STACK); |
77 | if (err) | 77 | if (err) |
78 | pr_debug("unwind failed\n"); | 78 | pr_debug("unwind failed\n"); |
@@ -89,21 +89,21 @@ static int unwind_thread(struct thread *thread, struct machine *machine) | |||
89 | } | 89 | } |
90 | 90 | ||
91 | __attribute__ ((noinline)) | 91 | __attribute__ ((noinline)) |
92 | static int krava_3(struct thread *thread, struct machine *machine) | 92 | static int krava_3(struct thread *thread) |
93 | { | 93 | { |
94 | return unwind_thread(thread, machine); | 94 | return unwind_thread(thread); |
95 | } | 95 | } |
96 | 96 | ||
97 | __attribute__ ((noinline)) | 97 | __attribute__ ((noinline)) |
98 | static int krava_2(struct thread *thread, struct machine *machine) | 98 | static int krava_2(struct thread *thread) |
99 | { | 99 | { |
100 | return krava_3(thread, machine); | 100 | return krava_3(thread); |
101 | } | 101 | } |
102 | 102 | ||
103 | __attribute__ ((noinline)) | 103 | __attribute__ ((noinline)) |
104 | static int krava_1(struct thread *thread, struct machine *machine) | 104 | static int krava_1(struct thread *thread) |
105 | { | 105 | { |
106 | return krava_2(thread, machine); | 106 | return krava_2(thread); |
107 | } | 107 | } |
108 | 108 | ||
109 | int test__dwarf_unwind(void) | 109 | int test__dwarf_unwind(void) |
@@ -137,7 +137,7 @@ int test__dwarf_unwind(void) | |||
137 | goto out; | 137 | goto out; |
138 | } | 138 | } |
139 | 139 | ||
140 | err = krava_1(thread, machine); | 140 | err = krava_1(thread); |
141 | 141 | ||
142 | out: | 142 | out: |
143 | machine__delete_threads(machine); | 143 | machine__delete_threads(machine); |
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 5a31787cc6b9..74f257a81265 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c | |||
@@ -43,7 +43,7 @@ static struct sample fake_samples[] = { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | static int add_hist_entries(struct perf_evlist *evlist, | 45 | static int add_hist_entries(struct perf_evlist *evlist, |
46 | struct machine *machine __maybe_unused) | 46 | struct machine *machine) |
47 | { | 47 | { |
48 | struct perf_evsel *evsel; | 48 | struct perf_evsel *evsel; |
49 | struct addr_location al; | 49 | struct addr_location al; |
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c index 4a456fef66ca..2113f1c8611f 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c | |||
@@ -187,7 +187,7 @@ static int mmap_events(synth_cb synth) | |||
187 | 187 | ||
188 | pr_debug("looking for map %p\n", td->map); | 188 | pr_debug("looking for map %p\n", td->map); |
189 | 189 | ||
190 | thread__find_addr_map(thread, machine, | 190 | thread__find_addr_map(thread, |
191 | PERF_RECORD_MISC_USER, MAP__FUNCTION, | 191 | PERF_RECORD_MISC_USER, MAP__FUNCTION, |
192 | (unsigned long) (td->map + 1), &al); | 192 | (unsigned long) (td->map + 1), &al); |
193 | 193 | ||
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 7f2f51f93619..4169f460efa1 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c | |||
@@ -1145,6 +1145,49 @@ static int test__pinned_group(struct perf_evlist *evlist) | |||
1145 | return 0; | 1145 | return 0; |
1146 | } | 1146 | } |
1147 | 1147 | ||
1148 | static int test__checkevent_breakpoint_len(struct perf_evlist *evlist) | ||
1149 | { | ||
1150 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
1151 | |||
1152 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
1153 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
1154 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
1155 | TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == | ||
1156 | evsel->attr.bp_type); | ||
1157 | TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_1 == | ||
1158 | evsel->attr.bp_len); | ||
1159 | |||
1160 | return 0; | ||
1161 | } | ||
1162 | |||
1163 | static int test__checkevent_breakpoint_len_w(struct perf_evlist *evlist) | ||
1164 | { | ||
1165 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
1166 | |||
1167 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
1168 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
1169 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
1170 | TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W == | ||
1171 | evsel->attr.bp_type); | ||
1172 | TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_2 == | ||
1173 | evsel->attr.bp_len); | ||
1174 | |||
1175 | return 0; | ||
1176 | } | ||
1177 | |||
1178 | static int | ||
1179 | test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist) | ||
1180 | { | ||
1181 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
1182 | |||
1183 | TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); | ||
1184 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | ||
1185 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
1186 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | ||
1187 | |||
1188 | return test__checkevent_breakpoint_rw(evlist); | ||
1189 | } | ||
1190 | |||
1148 | static int count_tracepoints(void) | 1191 | static int count_tracepoints(void) |
1149 | { | 1192 | { |
1150 | char events_path[PATH_MAX]; | 1193 | char events_path[PATH_MAX]; |
@@ -1420,6 +1463,21 @@ static struct evlist_test test__events[] = { | |||
1420 | .check = test__pinned_group, | 1463 | .check = test__pinned_group, |
1421 | .id = 41, | 1464 | .id = 41, |
1422 | }, | 1465 | }, |
1466 | { | ||
1467 | .name = "mem:0/1", | ||
1468 | .check = test__checkevent_breakpoint_len, | ||
1469 | .id = 42, | ||
1470 | }, | ||
1471 | { | ||
1472 | .name = "mem:0/2:w", | ||
1473 | .check = test__checkevent_breakpoint_len_w, | ||
1474 | .id = 43, | ||
1475 | }, | ||
1476 | { | ||
1477 | .name = "mem:0/4:rw:u", | ||
1478 | .check = test__checkevent_breakpoint_len_rw_modifier, | ||
1479 | .id = 44 | ||
1480 | }, | ||
1423 | #if defined(__s390x__) | 1481 | #if defined(__s390x__) |
1424 | { | 1482 | { |
1425 | .name = "kvm-s390:kvm_s390_create_vm", | 1483 | .name = "kvm-s390:kvm_s390_create_vm", |
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index ca292f9a4ae2..4908c648a597 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c | |||
@@ -126,16 +126,28 @@ static bool samples_same(const struct perf_sample *s1, | |||
126 | if (type & PERF_SAMPLE_TRANSACTION) | 126 | if (type & PERF_SAMPLE_TRANSACTION) |
127 | COMP(transaction); | 127 | COMP(transaction); |
128 | 128 | ||
129 | if (type & PERF_SAMPLE_REGS_INTR) { | ||
130 | size_t sz = hweight_long(s1->intr_regs.mask) * sizeof(u64); | ||
131 | |||
132 | COMP(intr_regs.mask); | ||
133 | COMP(intr_regs.abi); | ||
134 | if (s1->intr_regs.abi && | ||
135 | (!s1->intr_regs.regs || !s2->intr_regs.regs || | ||
136 | memcmp(s1->intr_regs.regs, s2->intr_regs.regs, sz))) { | ||
137 | pr_debug("Samples differ at 'intr_regs'\n"); | ||
138 | return false; | ||
139 | } | ||
140 | } | ||
141 | |||
129 | return true; | 142 | return true; |
130 | } | 143 | } |
131 | 144 | ||
132 | static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) | 145 | static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) |
133 | { | 146 | { |
134 | struct perf_evsel evsel = { | 147 | struct perf_evsel evsel = { |
135 | .needs_swap = false, | 148 | .needs_swap = false, |
136 | .attr = { | 149 | .attr = { |
137 | .sample_type = sample_type, | 150 | .sample_type = sample_type, |
138 | .sample_regs_user = sample_regs_user, | ||
139 | .read_format = read_format, | 151 | .read_format = read_format, |
140 | }, | 152 | }, |
141 | }; | 153 | }; |
@@ -154,7 +166,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) | |||
154 | /* 1 branch_entry */ | 166 | /* 1 branch_entry */ |
155 | .data = {1, 211, 212, 213}, | 167 | .data = {1, 211, 212, 213}, |
156 | }; | 168 | }; |
157 | u64 user_regs[64]; | 169 | u64 regs[64]; |
158 | const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL}; | 170 | const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL}; |
159 | const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; | 171 | const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; |
160 | struct perf_sample sample = { | 172 | struct perf_sample sample = { |
@@ -176,8 +188,8 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) | |||
176 | .branch_stack = &branch_stack.branch_stack, | 188 | .branch_stack = &branch_stack.branch_stack, |
177 | .user_regs = { | 189 | .user_regs = { |
178 | .abi = PERF_SAMPLE_REGS_ABI_64, | 190 | .abi = PERF_SAMPLE_REGS_ABI_64, |
179 | .mask = sample_regs_user, | 191 | .mask = sample_regs, |
180 | .regs = user_regs, | 192 | .regs = regs, |
181 | }, | 193 | }, |
182 | .user_stack = { | 194 | .user_stack = { |
183 | .size = sizeof(data), | 195 | .size = sizeof(data), |
@@ -187,14 +199,25 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) | |||
187 | .time_enabled = 0x030a59d664fca7deULL, | 199 | .time_enabled = 0x030a59d664fca7deULL, |
188 | .time_running = 0x011b6ae553eb98edULL, | 200 | .time_running = 0x011b6ae553eb98edULL, |
189 | }, | 201 | }, |
202 | .intr_regs = { | ||
203 | .abi = PERF_SAMPLE_REGS_ABI_64, | ||
204 | .mask = sample_regs, | ||
205 | .regs = regs, | ||
206 | }, | ||
190 | }; | 207 | }; |
191 | struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; | 208 | struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; |
192 | struct perf_sample sample_out; | 209 | struct perf_sample sample_out; |
193 | size_t i, sz, bufsz; | 210 | size_t i, sz, bufsz; |
194 | int err, ret = -1; | 211 | int err, ret = -1; |
195 | 212 | ||
196 | for (i = 0; i < sizeof(user_regs); i++) | 213 | if (sample_type & PERF_SAMPLE_REGS_USER) |
197 | *(i + (u8 *)user_regs) = i & 0xfe; | 214 | evsel.attr.sample_regs_user = sample_regs; |
215 | |||
216 | if (sample_type & PERF_SAMPLE_REGS_INTR) | ||
217 | evsel.attr.sample_regs_intr = sample_regs; | ||
218 | |||
219 | for (i = 0; i < sizeof(regs); i++) | ||
220 | *(i + (u8 *)regs) = i & 0xfe; | ||
198 | 221 | ||
199 | if (read_format & PERF_FORMAT_GROUP) { | 222 | if (read_format & PERF_FORMAT_GROUP) { |
200 | sample.read.group.nr = 4; | 223 | sample.read.group.nr = 4; |
@@ -271,7 +294,7 @@ int test__sample_parsing(void) | |||
271 | { | 294 | { |
272 | const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; | 295 | const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; |
273 | u64 sample_type; | 296 | u64 sample_type; |
274 | u64 sample_regs_user; | 297 | u64 sample_regs; |
275 | size_t i; | 298 | size_t i; |
276 | int err; | 299 | int err; |
277 | 300 | ||
@@ -280,7 +303,7 @@ int test__sample_parsing(void) | |||
280 | * were added. Please actually update the test rather than just change | 303 | * were added. Please actually update the test rather than just change |
281 | * the condition below. | 304 | * the condition below. |
282 | */ | 305 | */ |
283 | if (PERF_SAMPLE_MAX > PERF_SAMPLE_TRANSACTION << 1) { | 306 | if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) { |
284 | pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); | 307 | pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); |
285 | return -1; | 308 | return -1; |
286 | } | 309 | } |
@@ -297,22 +320,24 @@ int test__sample_parsing(void) | |||
297 | } | 320 | } |
298 | continue; | 321 | continue; |
299 | } | 322 | } |
323 | sample_regs = 0; | ||
300 | 324 | ||
301 | if (sample_type == PERF_SAMPLE_REGS_USER) | 325 | if (sample_type == PERF_SAMPLE_REGS_USER) |
302 | sample_regs_user = 0x3fff; | 326 | sample_regs = 0x3fff; |
303 | else | 327 | |
304 | sample_regs_user = 0; | 328 | if (sample_type == PERF_SAMPLE_REGS_INTR) |
329 | sample_regs = 0xff0fff; | ||
305 | 330 | ||
306 | err = do_test(sample_type, sample_regs_user, 0); | 331 | err = do_test(sample_type, sample_regs, 0); |
307 | if (err) | 332 | if (err) |
308 | return err; | 333 | return err; |
309 | } | 334 | } |
310 | 335 | ||
311 | /* Test all sample format bits together */ | 336 | /* Test all sample format bits together */ |
312 | sample_type = PERF_SAMPLE_MAX - 1; | 337 | sample_type = PERF_SAMPLE_MAX - 1; |
313 | sample_regs_user = 0x3fff; | 338 | sample_regs = 0x3fff; /* shared yb intr and user regs */ |
314 | for (i = 0; i < ARRAY_SIZE(rf); i++) { | 339 | for (i = 0; i < ARRAY_SIZE(rf); i++) { |
315 | err = do_test(sample_type, sample_regs_user, rf[i]); | 340 | err = do_test(sample_type, sample_regs, rf[i]); |
316 | if (err) | 341 | if (err) |
317 | return err; | 342 | return err; |
318 | } | 343 | } |