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