linux/tools/perf/tests/pmu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include "parse-events.h"
   3#include "pmu.h"
   4#include "util.h"
   5#include "tests.h"
   6#include <errno.h>
   7#include <linux/kernel.h>
   8
   9/* Simulated format definitions. */
  10static struct test_format {
  11        const char *name;
  12        const char *value;
  13} test_formats[] = {
  14        { "krava01", "config:0-1,62-63\n", },
  15        { "krava02", "config:10-17\n", },
  16        { "krava03", "config:5\n", },
  17        { "krava11", "config1:0,2,4,6,8,20-28\n", },
  18        { "krava12", "config1:63\n", },
  19        { "krava13", "config1:45-47\n", },
  20        { "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", },
  21        { "krava22", "config2:8,18,48,58\n", },
  22        { "krava23", "config2:28-29,38\n", },
  23};
  24
  25/* Simulated users input. */
  26static struct parse_events_term test_terms[] = {
  27        {
  28                .config    = (char *) "krava01",
  29                .val.num   = 15,
  30                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  31                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  32        },
  33        {
  34                .config    = (char *) "krava02",
  35                .val.num   = 170,
  36                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  37                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  38        },
  39        {
  40                .config    = (char *) "krava03",
  41                .val.num   = 1,
  42                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  43                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  44        },
  45        {
  46                .config    = (char *) "krava11",
  47                .val.num   = 27,
  48                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  49                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  50        },
  51        {
  52                .config    = (char *) "krava12",
  53                .val.num   = 1,
  54                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  55                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  56        },
  57        {
  58                .config    = (char *) "krava13",
  59                .val.num   = 2,
  60                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  61                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  62        },
  63        {
  64                .config    = (char *) "krava21",
  65                .val.num   = 119,
  66                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  67                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  68        },
  69        {
  70                .config    = (char *) "krava22",
  71                .val.num   = 11,
  72                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  73                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  74        },
  75        {
  76                .config    = (char *) "krava23",
  77                .val.num   = 2,
  78                .type_val  = PARSE_EVENTS__TERM_TYPE_NUM,
  79                .type_term = PARSE_EVENTS__TERM_TYPE_USER,
  80        },
  81};
  82
  83/*
  84 * Prepare format directory data, exported by kernel
  85 * at /sys/bus/event_source/devices/<dev>/format.
  86 */
  87static char *test_format_dir_get(void)
  88{
  89        static char dir[PATH_MAX];
  90        unsigned int i;
  91
  92        snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX");
  93        if (!mkdtemp(dir))
  94                return NULL;
  95
  96        for (i = 0; i < ARRAY_SIZE(test_formats); i++) {
  97                static char name[PATH_MAX];
  98                struct test_format *format = &test_formats[i];
  99                FILE *file;
 100
 101                scnprintf(name, PATH_MAX, "%s/%s", dir, format->name);
 102
 103                file = fopen(name, "w");
 104                if (!file)
 105                        return NULL;
 106
 107                if (1 != fwrite(format->value, strlen(format->value), 1, file))
 108                        break;
 109
 110                fclose(file);
 111        }
 112
 113        return dir;
 114}
 115
 116/* Cleanup format directory. */
 117static int test_format_dir_put(char *dir)
 118{
 119        char buf[PATH_MAX];
 120        snprintf(buf, PATH_MAX, "rm -f %s/*\n", dir);
 121        if (system(buf))
 122                return -1;
 123
 124        snprintf(buf, PATH_MAX, "rmdir %s\n", dir);
 125        return system(buf);
 126}
 127
 128static struct list_head *test_terms_list(void)
 129{
 130        static LIST_HEAD(terms);
 131        unsigned int i;
 132
 133        for (i = 0; i < ARRAY_SIZE(test_terms); i++)
 134                list_add_tail(&test_terms[i].list, &terms);
 135
 136        return &terms;
 137}
 138
 139int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
 140{
 141        char *format = test_format_dir_get();
 142        LIST_HEAD(formats);
 143        struct list_head *terms = test_terms_list();
 144        int ret;
 145
 146        if (!format)
 147                return -EINVAL;
 148
 149        do {
 150                struct perf_event_attr attr;
 151
 152                memset(&attr, 0, sizeof(attr));
 153
 154                ret = perf_pmu__format_parse(format, &formats);
 155                if (ret)
 156                        break;
 157
 158                ret = perf_pmu__config_terms(&formats, &attr, terms,
 159                                             false, NULL);
 160                if (ret)
 161                        break;
 162
 163                ret = -EINVAL;
 164
 165                if (attr.config  != 0xc00000000002a823)
 166                        break;
 167                if (attr.config1 != 0x8000400000000145)
 168                        break;
 169                if (attr.config2 != 0x0400000020041d07)
 170                        break;
 171
 172                ret = 0;
 173        } while (0);
 174
 175        test_format_dir_put(format);
 176        return ret;
 177}
 178