// SPDX-License-Identifier: GPL-2.0-only #include <stdbool.h> #include <inttypes.h> #include <stdlib.h> #include <string.h> #include <linux/bitops.h> #include <linux/kernel.h> #include <linux/types.h> #include "event.h" #include "evsel.h" #include "debug.h" #include "util/sample.h" #include "util/synthetic-events.h" #include "tests/tests.h" #include "arch-tests.h" #define COMP(m) do { \ if (s1->m != s2->m) { \ pr_debug("Samples differ at '"#m"'\n"); \ return false; \ } \ } while (0) static bool samples_same(const struct perf_sample *s1, const struct perf_sample *s2, u64 type) { if (type & PERF_SAMPLE_WEIGHT_STRUCT) { COMP(ins_lat); COMP(retire_lat); } return true; } static int do_test(u64 sample_type) { struct evsel evsel = { .needs_swap = false, .core = { . attr = { .sample_type = sample_type, .read_format = 0, }, }, }; union perf_event *event; struct perf_sample sample = { .weight = 101, .ins_lat = 102, .retire_lat = 103, }; struct perf_sample sample_out; size_t i, sz, bufsz; int err, ret = -1; sz = perf_event__sample_event_size(&sample, sample_type, 0); bufsz = sz + 4096; /* Add a bit for overrun checking */ event = malloc(bufsz); if (!event) { pr_debug("malloc failed\n"); return -1; } memset(event, 0xff, bufsz); event->header.type = PERF_RECORD_SAMPLE; event->header.misc = 0; event->header.size = sz; err = perf_event__synthesize_sample(event, sample_type, 0, &sample); if (err) { pr_debug("%s failed for sample_type %#"PRIx64", error %d\n", "perf_event__synthesize_sample", sample_type, err); goto out_free; } /* The data does not contain 0xff so we use that to check the size */ for (i = bufsz; i > 0; i--) { if (*(i - 1 + (u8 *)event) != 0xff) break; } if (i != sz) { pr_debug("Event size mismatch: actual %zu vs expected %zu\n", i, sz); goto out_free; } evsel.sample_size = __evsel__sample_size(sample_type); err = evsel__parse_sample(&evsel, event, &sample_out); if (err) { pr_debug("%s failed for sample_type %#"PRIx64", error %d\n", "evsel__parse_sample", sample_type, err); goto out_free; } if (!samples_same(&sample, &sample_out, sample_type)) { pr_debug("parsing failed for sample_type %#"PRIx64"\n", sample_type); goto out_free; } ret = 0; out_free: free(event); return ret; } /** * test__x86_sample_parsing - test X86 specific sample parsing * * This function implements a test that synthesizes a sample event, parses it * and then checks that the parsed sample matches the original sample. If the * test passes %0 is returned, otherwise %-1 is returned. * * For now, the PERF_SAMPLE_WEIGHT_STRUCT is the only X86 specific sample type. * The test only checks the PERF_SAMPLE_WEIGHT_STRUCT type. */ int test__x86_sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { return do_test(PERF_SAMPLE_WEIGHT_STRUCT); }