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