Linux Perf
pmu.c
Go to the documentation of this file.
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. */
10 static 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. */
26 static 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  */
87 static 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. */
117 static 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 
128 static 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 
139 int 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 }
int perf_pmu__format_parse(char *dir, struct list_head *head)
Definition: pmu.c:43
int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
Definition: pmu.c:139
static char * dir
Definition: attr.c:39
static char * test_format_dir_get(void)
Definition: pmu.c:87
static struct test_format test_formats[]
static int test_format_dir_put(char *dir)
Definition: pmu.c:117
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
union parse_events_term::@132 val
#define PATH_MAX
Definition: jevents.c:1042
static struct list_head * test_terms_list(void)
Definition: pmu.c:128
const char * name
Definition: pmu.c:11
static LIST_HEAD(pmus)
int perf_pmu__config_terms(struct list_head *formats, struct perf_event_attr *attr, struct list_head *head_terms, bool zero, struct parse_events_error *err)
Definition: pmu.c:1014
static struct parse_events_term test_terms[]
Definition: pmu.c:26
Definition: tests.h:30
const char * value
Definition: pmu.c:12