1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2cff7f956SJiri Olsa #include "parse-events.h" 3cff7f956SJiri Olsa #include "pmu.h" 4cff7f956SJiri Olsa #include "tests.h" 5a43783aeSArnaldo Carvalho de Melo #include <errno.h> 6e293a5e8SNamhyung Kim #include <fcntl.h> 7e9dacd63SArnaldo Carvalho de Melo #include <stdio.h> 8877a7a11SArnaldo Carvalho de Melo #include <linux/kernel.h> 9e9dacd63SArnaldo Carvalho de Melo #include <linux/limits.h> 10804fee5dSIan Rogers #include <linux/zalloc.h> 11cff7f956SJiri Olsa 12cff7f956SJiri Olsa /* Simulated format definitions. */ 13cff7f956SJiri Olsa static struct test_format { 14cff7f956SJiri Olsa const char *name; 15cff7f956SJiri Olsa const char *value; 16cff7f956SJiri Olsa } test_formats[] = { 17cff7f956SJiri Olsa { "krava01", "config:0-1,62-63\n", }, 18cff7f956SJiri Olsa { "krava02", "config:10-17\n", }, 19cff7f956SJiri Olsa { "krava03", "config:5\n", }, 20cff7f956SJiri Olsa { "krava11", "config1:0,2,4,6,8,20-28\n", }, 21cff7f956SJiri Olsa { "krava12", "config1:63\n", }, 22cff7f956SJiri Olsa { "krava13", "config1:45-47\n", }, 23cff7f956SJiri Olsa { "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", }, 24cff7f956SJiri Olsa { "krava22", "config2:8,18,48,58\n", }, 25cff7f956SJiri Olsa { "krava23", "config2:28-29,38\n", }, 26cff7f956SJiri Olsa }; 27cff7f956SJiri Olsa 28cff7f956SJiri Olsa /* Simulated users input. */ 296cee6cd3SArnaldo Carvalho de Melo static struct parse_events_term test_terms[] = { 30cff7f956SJiri Olsa { 31*970ef02eSIan Rogers .config = "krava01", 32cff7f956SJiri Olsa .val.num = 15, 33cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 34cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 35cff7f956SJiri Olsa }, 36cff7f956SJiri Olsa { 37*970ef02eSIan Rogers .config = "krava02", 38cff7f956SJiri Olsa .val.num = 170, 39cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 40cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 41cff7f956SJiri Olsa }, 42cff7f956SJiri Olsa { 43*970ef02eSIan Rogers .config = "krava03", 44cff7f956SJiri Olsa .val.num = 1, 45cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 46cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 47cff7f956SJiri Olsa }, 48cff7f956SJiri Olsa { 49*970ef02eSIan Rogers .config = "krava11", 50cff7f956SJiri Olsa .val.num = 27, 51cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 52cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 53cff7f956SJiri Olsa }, 54cff7f956SJiri Olsa { 55*970ef02eSIan Rogers .config = "krava12", 56cff7f956SJiri Olsa .val.num = 1, 57cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 58cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 59cff7f956SJiri Olsa }, 60cff7f956SJiri Olsa { 61*970ef02eSIan Rogers .config = "krava13", 62cff7f956SJiri Olsa .val.num = 2, 63cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 64cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 65cff7f956SJiri Olsa }, 66cff7f956SJiri Olsa { 67*970ef02eSIan Rogers .config = "krava21", 68cff7f956SJiri Olsa .val.num = 119, 69cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 70cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 71cff7f956SJiri Olsa }, 72cff7f956SJiri Olsa { 73*970ef02eSIan Rogers .config = "krava22", 74cff7f956SJiri Olsa .val.num = 11, 75cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 76cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 77cff7f956SJiri Olsa }, 78cff7f956SJiri Olsa { 79*970ef02eSIan Rogers .config = "krava23", 80cff7f956SJiri Olsa .val.num = 2, 81cff7f956SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 82cff7f956SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 83cff7f956SJiri Olsa }, 84cff7f956SJiri Olsa }; 85cff7f956SJiri Olsa 86cff7f956SJiri Olsa /* 87cff7f956SJiri Olsa * Prepare format directory data, exported by kernel 88cff7f956SJiri Olsa * at /sys/bus/event_source/devices/<dev>/format. 89cff7f956SJiri Olsa */ 90f50b8357SIan Rogers static char *test_format_dir_get(char *dir, size_t sz) 91cff7f956SJiri Olsa { 92cff7f956SJiri Olsa unsigned int i; 93cff7f956SJiri Olsa 94f50b8357SIan Rogers snprintf(dir, sz, "/tmp/perf-pmu-test-format-XXXXXX"); 95cff7f956SJiri Olsa if (!mkdtemp(dir)) 96cff7f956SJiri Olsa return NULL; 97cff7f956SJiri Olsa 98be651ed9SArnaldo Carvalho de Melo for (i = 0; i < ARRAY_SIZE(test_formats); i++) { 99f50b8357SIan Rogers char name[PATH_MAX]; 100cff7f956SJiri Olsa struct test_format *format = &test_formats[i]; 101cff7f956SJiri Olsa FILE *file; 102cff7f956SJiri Olsa 10377f18153SJiri Olsa scnprintf(name, PATH_MAX, "%s/%s", dir, format->name); 104cff7f956SJiri Olsa 105cff7f956SJiri Olsa file = fopen(name, "w"); 106cff7f956SJiri Olsa if (!file) 107cff7f956SJiri Olsa return NULL; 108cff7f956SJiri Olsa 109cff7f956SJiri Olsa if (1 != fwrite(format->value, strlen(format->value), 1, file)) 110cff7f956SJiri Olsa break; 111cff7f956SJiri Olsa 112cff7f956SJiri Olsa fclose(file); 113cff7f956SJiri Olsa } 114cff7f956SJiri Olsa 115cff7f956SJiri Olsa return dir; 116cff7f956SJiri Olsa } 117cff7f956SJiri Olsa 118cff7f956SJiri Olsa /* Cleanup format directory. */ 119cff7f956SJiri Olsa static int test_format_dir_put(char *dir) 120cff7f956SJiri Olsa { 121f50b8357SIan Rogers char buf[PATH_MAX + 20]; 122f50b8357SIan Rogers 123f50b8357SIan Rogers snprintf(buf, sizeof(buf), "rm -f %s/*\n", dir); 124cff7f956SJiri Olsa if (system(buf)) 125cff7f956SJiri Olsa return -1; 126cff7f956SJiri Olsa 127f50b8357SIan Rogers snprintf(buf, sizeof(buf), "rmdir %s\n", dir); 128cff7f956SJiri Olsa return system(buf); 129cff7f956SJiri Olsa } 130cff7f956SJiri Olsa 131cff7f956SJiri Olsa static struct list_head *test_terms_list(void) 132cff7f956SJiri Olsa { 133cff7f956SJiri Olsa static LIST_HEAD(terms); 134cff7f956SJiri Olsa unsigned int i; 135cff7f956SJiri Olsa 136be651ed9SArnaldo Carvalho de Melo for (i = 0; i < ARRAY_SIZE(test_terms); i++) 137cff7f956SJiri Olsa list_add_tail(&test_terms[i].list, &terms); 138cff7f956SJiri Olsa 139cff7f956SJiri Olsa return &terms; 140cff7f956SJiri Olsa } 141cff7f956SJiri Olsa 14233f44bfdSIan Rogers static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 143cff7f956SJiri Olsa { 144f50b8357SIan Rogers char dir[PATH_MAX]; 145804fee5dSIan Rogers char *format; 146cff7f956SJiri Olsa struct list_head *terms = test_terms_list(); 147804fee5dSIan Rogers struct perf_event_attr attr; 148804fee5dSIan Rogers struct perf_pmu *pmu; 149804fee5dSIan Rogers int fd; 150cff7f956SJiri Olsa int ret; 151cff7f956SJiri Olsa 152804fee5dSIan Rogers pmu = zalloc(sizeof(*pmu)); 153804fee5dSIan Rogers if (!pmu) 154804fee5dSIan Rogers return -ENOMEM; 155cff7f956SJiri Olsa 156804fee5dSIan Rogers INIT_LIST_HEAD(&pmu->format); 157804fee5dSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 158804fee5dSIan Rogers INIT_LIST_HEAD(&pmu->caps); 159804fee5dSIan Rogers format = test_format_dir_get(dir, sizeof(dir)); 160804fee5dSIan Rogers if (!format) { 161804fee5dSIan Rogers free(pmu); 162804fee5dSIan Rogers return -EINVAL; 163804fee5dSIan Rogers } 164cff7f956SJiri Olsa 165cff7f956SJiri Olsa memset(&attr, 0, sizeof(attr)); 166cff7f956SJiri Olsa 167e293a5e8SNamhyung Kim fd = open(format, O_DIRECTORY); 168e293a5e8SNamhyung Kim if (fd < 0) { 169e293a5e8SNamhyung Kim ret = fd; 170804fee5dSIan Rogers goto out; 171e293a5e8SNamhyung Kim } 172cff7f956SJiri Olsa 173804fee5dSIan Rogers pmu->name = strdup("perf-pmu-test"); 17450402641SIan Rogers ret = perf_pmu__format_parse(pmu, fd, /*eager_load=*/true); 175cff7f956SJiri Olsa if (ret) 176804fee5dSIan Rogers goto out; 177804fee5dSIan Rogers 178804fee5dSIan Rogers ret = perf_pmu__config_terms(pmu, &attr, terms, /*zero=*/false, /*err=*/NULL); 179804fee5dSIan Rogers if (ret) 180804fee5dSIan Rogers goto out; 181cff7f956SJiri Olsa 182cff7f956SJiri Olsa ret = -EINVAL; 183cff7f956SJiri Olsa if (attr.config != 0xc00000000002a823) 184804fee5dSIan Rogers goto out; 185cff7f956SJiri Olsa if (attr.config1 != 0x8000400000000145) 186804fee5dSIan Rogers goto out; 187cff7f956SJiri Olsa if (attr.config2 != 0x0400000020041d07) 188804fee5dSIan Rogers goto out; 189cff7f956SJiri Olsa 190cff7f956SJiri Olsa ret = 0; 191804fee5dSIan Rogers out: 192cff7f956SJiri Olsa test_format_dir_put(format); 193804fee5dSIan Rogers perf_pmu__delete(pmu); 194cff7f956SJiri Olsa return ret; 195cff7f956SJiri Olsa } 196d68f0365SIan Rogers 197d68f0365SIan Rogers DEFINE_SUITE("Parse perf pmu format", pmu); 198