projects/linux·blob master · refs

493 lines · 12.4 KiB

1// SPDX-License-Identifier: GPL-2.0
2#include <stdbool.h>
3#include <inttypes.h>
4#include <stdlib.h>
5#include <string.h>
6#include <linux/bitops.h>
7#include <linux/kernel.h>
8#include <linux/types.h>
9
10#include "map_symbol.h"
11#include "branch.h"
12#include "event.h"
13#include "evsel.h"
14#include "debug.h"
15#include "util/synthetic-events.h"
16#include "util/util.h"
17
18#include "tests.h"
19
20#define COMP(m) do { \
21 if (s1->m != s2->m) { \
22 pr_debug("Samples differ at '"#m"'\n"); \
23 return false; \
24 } \
25} while (0)
26
27#define MCOMP(m) do { \
28 if (memcmp(&s1->m, &s2->m, sizeof(s1->m))) { \
29 pr_debug("Samples differ at '"#m"'\n"); \
30 return false; \
31 } \
32} while (0)
33
34/*
35 * Hardcode the expected values for branch_entry flags.
36 * These are based on the input value (213) specified
37 * in branch_stack variable.
38 */
39#define BS_EXPECTED_BE 0xa000d00000000000
40#define BS_EXPECTED_LE 0x1aa00000000
41#define FLAG(s) s->branch_stack->entries[i].flags
42
43static bool samples_same(struct perf_sample *s1,
44 struct perf_sample *s2,
45 u64 type, u64 read_format, bool needs_swap)
46{
47 size_t i;
48
49 if (type & PERF_SAMPLE_IDENTIFIER)
50 COMP(id);
51
52 if (type & PERF_SAMPLE_IP)
53 COMP(ip);
54
55 if (type & PERF_SAMPLE_TID) {
56 COMP(pid);
57 COMP(tid);
58 }
59
60 if (type & PERF_SAMPLE_TIME)
61 COMP(time);
62
63 if (type & PERF_SAMPLE_ADDR)
64 COMP(addr);
65
66 if (type & PERF_SAMPLE_ID)
67 COMP(id);
68
69 if (type & PERF_SAMPLE_STREAM_ID)
70 COMP(stream_id);
71
72 if (type & PERF_SAMPLE_CPU)
73 COMP(cpu);
74
75 if (type & PERF_SAMPLE_PERIOD)
76 COMP(period);
77
78 if (type & PERF_SAMPLE_READ) {
79 if (read_format & PERF_FORMAT_GROUP)
80 COMP(read.group.nr);
81 else
82 COMP(read.one.value);
83 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
84 COMP(read.time_enabled);
85 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
86 COMP(read.time_running);
87 /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
88 if (read_format & PERF_FORMAT_GROUP) {
89 struct sample_read_value *v1 = s1->read.group.values;
90 struct sample_read_value *v2 = s2->read.group.values;
91
92 for (i = 0; i < s1->read.group.nr; i++) {
93 if (v1->value != v2->value) {
94 pr_debug("Samples differ at 'read.group.values[].value'\n");
95 return false;
96 }
97
98 if (v1->id != v2->id) {
99 pr_debug("Samples differ at 'read.group.values[].id'\n");
100 return false;
101 }
102
103 if (read_format & PERF_FORMAT_LOST &&
104 v1->lost != v2->lost) {
105 pr_debug("Samples differ at 'read.group.values[].lost'\n");
106 return false;
107 }
108 v1 = next_sample_read_value(v1, read_format);
109 v2 = next_sample_read_value(v2, read_format);
110 }
111 } else {
112 COMP(read.one.id);
113 if (read_format & PERF_FORMAT_LOST)
114 COMP(read.one.lost);
115 }
116 }
117
118 if (type & PERF_SAMPLE_CALLCHAIN) {
119 COMP(callchain->nr);
120 for (i = 0; i < s1->callchain->nr; i++)
121 COMP(callchain->ips[i]);
122 }
123
124 if (type & PERF_SAMPLE_RAW) {
125 COMP(raw_size);
126 if (memcmp(s1->raw_data, s2->raw_data, s1->raw_size)) {
127 pr_debug("Samples differ at 'raw_data'\n");
128 return false;
129 }
130 }
131
132 if (type & PERF_SAMPLE_BRANCH_STACK) {
133 COMP(branch_stack->nr);
134 COMP(branch_stack->hw_idx);
135 for (i = 0; i < s1->branch_stack->nr; i++) {
136 if (needs_swap)
137 return ((host_is_bigendian()) ?
138 (FLAG(s2).value == BS_EXPECTED_BE) :
139 (FLAG(s2).value == BS_EXPECTED_LE));
140 else
141 MCOMP(branch_stack->entries[i]);
142 }
143 }
144
145 if (type & PERF_SAMPLE_REGS_USER) {
146 struct regs_dump *s1_regs = perf_sample__user_regs(s1);
147 struct regs_dump *s2_regs = perf_sample__user_regs(s2);
148 size_t sz = hweight_long(s1_regs->mask) * sizeof(u64);
149
150 COMP(user_regs->mask);
151 COMP(user_regs->abi);
152 if (s1_regs->abi &&
153 (!s1_regs->regs || !s2_regs->regs ||
154 memcmp(s1_regs->regs, s2_regs->regs, sz))) {
155 pr_debug("Samples differ at 'user_regs'\n");
156 return false;
157 }
158 }
159
160 if (type & PERF_SAMPLE_STACK_USER) {
161 COMP(user_stack.size);
162 if (memcmp(s1->user_stack.data, s2->user_stack.data,
163 s1->user_stack.size)) {
164 pr_debug("Samples differ at 'user_stack'\n");
165 return false;
166 }
167 }
168
169 if (type & PERF_SAMPLE_WEIGHT)
170 COMP(weight);
171
172 if (type & PERF_SAMPLE_WEIGHT_STRUCT) {
173 COMP(weight);
174 COMP(ins_lat);
175 COMP(weight3);
176 }
177
178 if (type & PERF_SAMPLE_DATA_SRC)
179 COMP(data_src);
180
181 if (type & PERF_SAMPLE_TRANSACTION)
182 COMP(transaction);
183
184 if (type & PERF_SAMPLE_REGS_INTR) {
185 struct regs_dump *s1_regs = perf_sample__intr_regs(s1);
186 struct regs_dump *s2_regs = perf_sample__intr_regs(s2);
187 size_t sz = hweight_long(s1_regs->mask) * sizeof(u64);
188
189 COMP(intr_regs->mask);
190 COMP(intr_regs->abi);
191 if (s1_regs->abi &&
192 (!s1_regs->regs || !s2_regs->regs ||
193 memcmp(s1_regs->regs, s2_regs->regs, sz))) {
194 pr_debug("Samples differ at 'intr_regs'\n");
195 return false;
196 }
197 }
198
199 if (type & PERF_SAMPLE_PHYS_ADDR)
200 COMP(phys_addr);
201
202 if (type & PERF_SAMPLE_CGROUP)
203 COMP(cgroup);
204
205 if (type & PERF_SAMPLE_DATA_PAGE_SIZE)
206 COMP(data_page_size);
207
208 if (type & PERF_SAMPLE_CODE_PAGE_SIZE)
209 COMP(code_page_size);
210
211 if (type & PERF_SAMPLE_AUX) {
212 COMP(aux_sample.size);
213 if (memcmp(s1->aux_sample.data, s2->aux_sample.data,
214 s1->aux_sample.size)) {
215 pr_debug("Samples differ at 'aux_sample'\n");
216 return false;
217 }
218 }
219
220 return true;
221}
222
223static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
224{
225 struct perf_event_attr attr = {
226 .sample_type = sample_type,
227 .read_format = read_format,
228 };
229 struct evsel *evsel;
230 union perf_event *event;
231 union {
232 struct ip_callchain callchain;
233 u64 data[64];
234 } callchain = {
235 /* 3 ips */
236 .data = {3, 201, 202, 203},
237 };
238 union {
239 struct branch_stack branch_stack;
240 u64 data[64];
241 } branch_stack = {
242 /* 1 branch_entry */
243 .data = {1, -1ULL, 211, 212, 213},
244 };
245 u64 regs[64];
246 const u32 raw_data[] = {0x12345678, 0x0a0b0c0d, 0x11020304, 0x05060708, 0 };
247 const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL};
248 const u64 aux_data[] = {0xa55a, 0, 0xeeddee, 0x0282028202820282};
249 struct regs_dump user_regs = {
250 .abi = PERF_SAMPLE_REGS_ABI_64,
251 .mask = sample_regs,
252 .regs = regs,
253 };
254 struct regs_dump intr_regs = {
255 .abi = PERF_SAMPLE_REGS_ABI_64,
256 .mask = sample_regs,
257 .regs = regs,
258 };
259 struct perf_sample sample = {
260 .ip = 101,
261 .pid = 102,
262 .tid = 103,
263 .time = 104,
264 .addr = 105,
265 .id = 106,
266 .stream_id = 107,
267 .period = 108,
268 .weight = 109,
269 .cpu = 110,
270 .raw_size = sizeof(raw_data),
271 .data_src = 111,
272 .transaction = 112,
273 .raw_data = (void *)raw_data,
274 .callchain = &callchain.callchain,
275 .no_hw_idx = false,
276 .branch_stack = &branch_stack.branch_stack,
277 .user_regs = &user_regs,
278 .user_stack = {
279 .size = sizeof(data),
280 .data = (void *)data,
281 },
282 .read = {
283 .time_enabled = 0x030a59d664fca7deULL,
284 .time_running = 0x011b6ae553eb98edULL,
285 },
286 .intr_regs = &intr_regs,
287 .phys_addr = 113,
288 .cgroup = 114,
289 .data_page_size = 115,
290 .code_page_size = 116,
291 .ins_lat = 117,
292 .weight3 = 118,
293 .aux_sample = {
294 .size = sizeof(aux_data),
295 .data = (void *)aux_data,
296 },
297 };
298 struct sample_read_value values[] = {{1, 5, 0}, {9, 3, 0}, {2, 7, 0}, {6, 4, 1},};
299 struct sample_read_value packed_values[ARRAY_SIZE(values)];
300 struct perf_sample sample_out, sample_out_endian;
301 size_t i, sz, bufsz;
302 int err, ret = -1;
303
304 evsel = evsel__new(&attr);
305 if (!evsel) {
306 pr_debug("evsel__new failed\n");
307 return -1;
308 }
309 perf_sample__init(&sample_out, /*all=*/false);
310 perf_sample__init(&sample_out_endian, /*all=*/false);
311 if (sample_type & PERF_SAMPLE_REGS_USER)
312 evsel->core.attr.sample_regs_user = sample_regs;
313
314 if (sample_type & PERF_SAMPLE_REGS_INTR)
315 evsel->core.attr.sample_regs_intr = sample_regs;
316
317 if (sample_type & PERF_SAMPLE_BRANCH_STACK)
318 evsel->core.attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX;
319
320 for (i = 0; i < sizeof(regs); i++)
321 *(i + (u8 *)regs) = i & 0xfe;
322
323 if (read_format & PERF_FORMAT_GROUP) {
324 size_t vsz = sample_read_value_size(read_format);
325
326 /*
327 * evsel__parse_sample() points read.group.values at the event
328 * data, where the entries are packed according to read_format,
329 * so build the input the same way. Otherwise the fields
330 * compared afterwards are just overlapping bytes.
331 */
332 for (i = 0; i < ARRAY_SIZE(values); i++)
333 memcpy((void *)packed_values + i * vsz, &values[i], vsz);
334
335 sample.read.group.nr = ARRAY_SIZE(values);
336 sample.read.group.values = packed_values;
337 } else {
338 sample.read.one.value = 0x08789faeb786aa87ULL;
339 sample.read.one.id = 99;
340 sample.read.one.lost = 1;
341 }
342
343 sz = perf_event__sample_event_size(&sample, sample_type, read_format,
344 evsel->core.attr.branch_sample_type);
345 bufsz = sz + 4096; /* Add a bit for overrun checking */
346 event = malloc(bufsz);
347 if (!event) {
348 pr_debug("malloc failed\n");
349 goto out_free;
350 }
351
352 memset(event, 0xff, bufsz);
353 event->header.type = PERF_RECORD_SAMPLE;
354 event->header.misc = 0;
355 event->header.size = sz;
356
357 err = perf_event__synthesize_sample(event, sample_type, read_format,
358 evsel->core.attr.branch_sample_type, &sample);
359 if (err) {
360 pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
361 "perf_event__synthesize_sample", sample_type, err);
362 goto out_free;
363 }
364
365 /* The data does not contain 0xff so we use that to check the size */
366 for (i = bufsz; i > 0; i--) {
367 if (*(i - 1 + (u8 *)event) != 0xff)
368 break;
369 }
370 if (i != sz) {
371 pr_debug("Event size mismatch: actual %zu vs expected %zu\n",
372 i, sz);
373 goto out_free;
374 }
375
376 evsel->sample_size = __evsel__sample_size(sample_type);
377
378 err = evsel__parse_sample(evsel, event, &sample_out);
379 if (err) {
380 pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
381 "evsel__parse_sample", sample_type, err);
382 goto out_free;
383 }
384
385 if (!samples_same(&sample, &sample_out, sample_type, read_format, evsel->needs_swap)) {
386 pr_debug("parsing failed for sample_type %#"PRIx64"\n",
387 sample_type);
388 goto out_free;
389 }
390
391 if (sample_type == PERF_SAMPLE_BRANCH_STACK) {
392 evsel->needs_swap = true;
393 evsel->sample_size = __evsel__sample_size(sample_type);
394 err = evsel__parse_sample(evsel, event, &sample_out_endian);
395 if (err) {
396 pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
397 "evsel__parse_sample", sample_type, err);
398 goto out_free;
399 }
400
401 if (!samples_same(&sample, &sample_out_endian, sample_type,
402 read_format, evsel->needs_swap)) {
403 pr_debug("parsing failed for sample_type %#"PRIx64"\n",
404 sample_type);
405 goto out_free;
406 }
407 }
408
409 ret = 0;
410out_free:
411 free(event);
412 perf_sample__exit(&sample_out_endian);
413 perf_sample__exit(&sample_out);
414 evsel__put(evsel);
415 if (ret && read_format)
416 pr_debug("read_format %#"PRIx64"\n", read_format);
417 return ret;
418}
419
420/**
421 * test__sample_parsing - test sample parsing.
422 *
423 * This function implements a test that synthesizes a sample event, parses it
424 * and then checks that the parsed sample matches the original sample. The test
425 * checks sample format bits separately and together. If the test passes %0 is
426 * returned, otherwise %-1 is returned.
427 */
428static int test__sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
429{
430 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 28, 29, 30, 31};
431 u64 sample_type;
432 u64 sample_regs;
433 size_t i;
434 int err;
435
436 /*
437 * Fail the test if it has not been updated when new sample format bits
438 * were added. Please actually update the test rather than just change
439 * the condition below.
440 */
441 if (PERF_SAMPLE_MAX > PERF_SAMPLE_WEIGHT_STRUCT << 1) {
442 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
443 return -1;
444 }
445
446 /* Test each sample format bit separately */
447 for (sample_type = 1; sample_type != PERF_SAMPLE_MAX;
448 sample_type <<= 1) {
449 /* Test read_format variations */
450 if (sample_type == PERF_SAMPLE_READ) {
451 for (i = 0; i < ARRAY_SIZE(rf); i++) {
452 err = do_test(sample_type, 0, rf[i]);
453 if (err)
454 return err;
455 }
456 continue;
457 }
458 sample_regs = 0;
459
460 if (sample_type == PERF_SAMPLE_REGS_USER)
461 sample_regs = 0x3fff;
462
463 if (sample_type == PERF_SAMPLE_REGS_INTR)
464 sample_regs = 0xff0fff;
465
466 err = do_test(sample_type, sample_regs, 0);
467 if (err)
468 return err;
469 }
470
471 /*
472 * Test all sample format bits together
473 * Note: PERF_SAMPLE_WEIGHT and PERF_SAMPLE_WEIGHT_STRUCT cannot
474 * be set simultaneously.
475 */
476 sample_type = (PERF_SAMPLE_MAX - 1) & ~PERF_SAMPLE_WEIGHT;
477 sample_regs = 0x3fff; /* shared yb intr and user regs */
478 for (i = 0; i < ARRAY_SIZE(rf); i++) {
479 err = do_test(sample_type, sample_regs, rf[i]);
480 if (err)
481 return err;
482 }
483 sample_type = (PERF_SAMPLE_MAX - 1) & ~PERF_SAMPLE_WEIGHT_STRUCT;
484 for (i = 0; i < ARRAY_SIZE(rf); i++) {
485 err = do_test(sample_type, sample_regs, rf[i]);
486 if (err)
487 return err;
488 }
489
490 return 0;
491}
492
493DEFINE_SUITE("Sample parsing", sample_parsing);