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