1 // SPDX-License-Identifier: GPL-2.0-only 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 "event.h" 11 #include "evsel.h" 12 #include "debug.h" 13 #include "util/sample.h" 14 #include "util/synthetic-events.h" 15 16 #include "tests/tests.h" 17 #include "arch-tests.h" 18 19 #define COMP(m) do { \ 20 if (s1->m != s2->m) { \ 21 pr_debug("Samples differ at '"#m"'\n"); \ 22 return false; \ 23 } \ 24 } while (0) 25 26 static bool samples_same(const struct perf_sample *s1, 27 const struct perf_sample *s2, 28 u64 type) 29 { 30 if (type & PERF_SAMPLE_WEIGHT_STRUCT) 31 COMP(ins_lat); 32 33 return true; 34 } 35 36 static int do_test(u64 sample_type) 37 { 38 struct evsel evsel = { 39 .needs_swap = false, 40 .core = { 41 . attr = { 42 .sample_type = sample_type, 43 .read_format = 0, 44 }, 45 }, 46 }; 47 union perf_event *event; 48 struct perf_sample sample = { 49 .weight = 101, 50 .ins_lat = 102, 51 }; 52 struct perf_sample sample_out; 53 size_t i, sz, bufsz; 54 int err, ret = -1; 55 56 sz = perf_event__sample_event_size(&sample, sample_type, 0); 57 bufsz = sz + 4096; /* Add a bit for overrun checking */ 58 event = malloc(bufsz); 59 if (!event) { 60 pr_debug("malloc failed\n"); 61 return -1; 62 } 63 64 memset(event, 0xff, bufsz); 65 event->header.type = PERF_RECORD_SAMPLE; 66 event->header.misc = 0; 67 event->header.size = sz; 68 69 err = perf_event__synthesize_sample(event, sample_type, 0, &sample); 70 if (err) { 71 pr_debug("%s failed for sample_type %#"PRIx64", error %d\n", 72 "perf_event__synthesize_sample", sample_type, err); 73 goto out_free; 74 } 75 76 /* The data does not contain 0xff so we use that to check the size */ 77 for (i = bufsz; i > 0; i--) { 78 if (*(i - 1 + (u8 *)event) != 0xff) 79 break; 80 } 81 if (i != sz) { 82 pr_debug("Event size mismatch: actual %zu vs expected %zu\n", 83 i, sz); 84 goto out_free; 85 } 86 87 evsel.sample_size = __evsel__sample_size(sample_type); 88 89 err = evsel__parse_sample(&evsel, event, &sample_out); 90 if (err) { 91 pr_debug("%s failed for sample_type %#"PRIx64", error %d\n", 92 "evsel__parse_sample", sample_type, err); 93 goto out_free; 94 } 95 96 if (!samples_same(&sample, &sample_out, sample_type)) { 97 pr_debug("parsing failed for sample_type %#"PRIx64"\n", 98 sample_type); 99 goto out_free; 100 } 101 102 ret = 0; 103 out_free: 104 free(event); 105 106 return ret; 107 } 108 109 /** 110 * test__x86_sample_parsing - test X86 specific sample parsing 111 * 112 * This function implements a test that synthesizes a sample event, parses it 113 * and then checks that the parsed sample matches the original sample. If the 114 * test passes %0 is returned, otherwise %-1 is returned. 115 * 116 * For now, the PERF_SAMPLE_WEIGHT_STRUCT is the only X86 specific sample type. 117 * The test only checks the PERF_SAMPLE_WEIGHT_STRUCT type. 118 */ 119 int test__x86_sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 120 { 121 return do_test(PERF_SAMPLE_WEIGHT_STRUCT); 122 } 123