parlib: Expand our printf hacks
[akaros.git] / user / perfmon / tests / validate.c
1 /*
2  * validate.c - validate event tables + encodings
3  *
4  * Copyright (c) 2010 Google, Inc
5  * Contributed by Stephane Eranian <eranian@gmail.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11  * of the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * This file is part of libpfm, a performance monitoring support library for
25  * applications on Linux.
26  */
27 #include <sys/types.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <inttypes.h>
31 #include <stdarg.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <perfmon/err.h>
36
37 #include <perfmon/pfmlib.h>
38 #ifdef __linux__
39 #include <perfmon/pfmlib_perf_event.h>
40 #endif
41
42 #define __weak_func     __attribute__((weak))
43
44 #ifdef PFMLIB_WINDOWS
45 int set_env_var(const char *var, const char *value, int ov)
46 {
47         size_t len;
48         char *str;
49         int ret;
50
51         len = strlen(var) + 1 + strlen(value) + 1;
52
53         str = malloc(len);
54         if (!str)
55                 return PFM_ERR_NOMEM;
56
57         sprintf(str, "%s=%s", var, value);
58
59         ret = putenv(str);
60
61         free(str);
62
63         return ret ? PFM_ERR_INVAL : PFM_SUCCESS;
64 }
65 #else
66 static inline int
67 set_env_var(const char *var, const char *value, int ov)
68 {
69         return setenv(var, value, ov);
70 }
71 #endif
72
73 __weak_func int validate_arch(FILE *fp)
74 {
75         return 0;
76 }
77
78 static struct {
79         int valid_intern;
80         int valid_arch;
81 } options;
82
83 static void
84 usage(void)
85 {
86         printf("validate [-c] [-a] [-A]\n"
87                 "-c\trun the library validate events\n"
88                 "-a\trun architecture specific event tests\n"
89                 "-A\trun all tests\n"
90                 "-h\tget help\n");
91 }
92
93 static int
94 validate_event_tables(void)
95 {
96         pfm_pmu_info_t pinfo;
97         int i, ret, errors = 0;
98
99         memset(&pinfo, 0, sizeof(pinfo));
100
101         pinfo.size = sizeof(pinfo);
102
103         pfm_for_all_pmus(i) {
104                 ret = pfm_get_pmu_info(i, &pinfo);
105                 if (ret != PFM_SUCCESS)
106                         continue;
107
108                 printf("\tchecking %s (%d events): ", pinfo.name, pinfo.nevents);
109                 fflush(stdout);
110
111                 ret = pfm_pmu_validate(i, stdout);
112                 if (ret != PFM_SUCCESS && ret != PFM_ERR_NOTSUPP) {
113                         printf("Failed\n");
114                         errors++;
115                 } else if (ret == PFM_ERR_NOTSUPP) {
116                         printf("N/A\n");
117                 } else {
118                         printf("Passed\n");
119                 }
120         }
121         return errors;
122 }
123
124 #if __WORDSIZE == 64
125 #define STRUCT_MULT     8
126 #else
127 #define STRUCT_MULT     4
128 #endif
129
130 #define MAX_FIELDS 32
131 typedef struct {
132                 const char *name;
133                 size_t sz;
134 } field_desc_t;
135
136 typedef struct {
137         const char *name;
138         size_t sz;
139         size_t bitfield_sz;
140         size_t abi_sz;
141         field_desc_t fields[MAX_FIELDS];
142 } struct_desc_t;
143
144 #define LAST_STRUCT { .name = NULL, }
145
146 #define FIELD(n, st) \
147         { .name = #n, \
148           .sz   = sizeof(((st *)(0))->n), \
149         }
150 #define LAST_FIELD { .name = NULL, }
151
152 static const struct_desc_t pfmlib_structs[]={
153         {
154          .name = "pfm_pmu_info_t",
155          .sz   = sizeof(pfm_pmu_info_t),
156          .bitfield_sz = 4,
157          .abi_sz = PFM_PMU_INFO_ABI0,
158          .fields= {
159                 FIELD(name, pfm_pmu_info_t),
160                 FIELD(desc, pfm_pmu_info_t),
161                 FIELD(size, pfm_pmu_info_t),
162                 FIELD(pmu, pfm_pmu_info_t),
163                 FIELD(type, pfm_pmu_info_t),
164                 FIELD(nevents, pfm_pmu_info_t),
165                 FIELD(first_event, pfm_pmu_info_t),
166                 FIELD(max_encoding, pfm_pmu_info_t),
167                 FIELD(num_cntrs, pfm_pmu_info_t),
168                 FIELD(num_fixed_cntrs, pfm_pmu_info_t),
169                 LAST_FIELD
170          },
171         },
172         {
173          .name = "pfm_event_info_t",
174          .sz   = sizeof(pfm_event_info_t),
175          .bitfield_sz = 4,
176          .abi_sz = PFM_EVENT_INFO_ABI0,
177          .fields= {
178                 FIELD(name, pfm_event_info_t),
179                 FIELD(desc, pfm_event_info_t),
180                 FIELD(equiv, pfm_event_info_t),
181                 FIELD(size, pfm_event_info_t),
182                 FIELD(code, pfm_event_info_t),
183                 FIELD(pmu, pfm_event_info_t),
184                 FIELD(dtype, pfm_event_info_t),
185                 FIELD(idx, pfm_event_info_t),
186                 FIELD(nattrs, pfm_event_info_t),
187                 FIELD(reserved, pfm_event_info_t),
188                 LAST_FIELD
189          },
190         },
191         {
192          .name = "pfm_event_attr_info_t",
193          .sz   = sizeof(pfm_event_attr_info_t),
194          .bitfield_sz = 4+8,
195          .abi_sz = PFM_ATTR_INFO_ABI0,
196          .fields= {
197                 FIELD(name, pfm_event_attr_info_t),
198                 FIELD(desc, pfm_event_attr_info_t),
199                 FIELD(equiv, pfm_event_attr_info_t),
200                 FIELD(size, pfm_event_attr_info_t),
201                 FIELD(code, pfm_event_attr_info_t),
202                 FIELD(type, pfm_event_attr_info_t),
203                 FIELD(idx, pfm_event_attr_info_t),
204                 FIELD(ctrl, pfm_event_attr_info_t),
205                 LAST_FIELD
206          },
207         },
208         {
209          .name = "pfm_pmu_encode_arg_t",
210          .sz   = sizeof(pfm_pmu_encode_arg_t),
211          .abi_sz = PFM_RAW_ENCODE_ABI0,
212          .fields= {
213                 FIELD(codes, pfm_pmu_encode_arg_t),
214                 FIELD(fstr, pfm_pmu_encode_arg_t),
215                 FIELD(size, pfm_pmu_encode_arg_t),
216                 FIELD(count, pfm_pmu_encode_arg_t),
217                 FIELD(idx, pfm_pmu_encode_arg_t),
218                 LAST_FIELD
219          },
220         },
221 #ifdef __linux__
222         {
223          .name = "pfm_perf_encode_arg_t",
224          .sz   = sizeof(pfm_perf_encode_arg_t),
225          .bitfield_sz = 0,
226          .abi_sz = PFM_PERF_ENCODE_ABI0,
227          .fields= {
228                 FIELD(attr, pfm_perf_encode_arg_t),
229                 FIELD(fstr, pfm_perf_encode_arg_t),
230                 FIELD(size, pfm_perf_encode_arg_t),
231                 FIELD(idx, pfm_perf_encode_arg_t),
232                 FIELD(cpu, pfm_perf_encode_arg_t),
233                 FIELD(flags, pfm_perf_encode_arg_t),
234                 FIELD(pad0, pfm_perf_encode_arg_t),
235                 LAST_FIELD
236          },
237         },
238 #endif
239         LAST_STRUCT
240 };
241
242 static int
243 validate_structs(void)
244 {
245
246         const struct_desc_t *d;
247         const field_desc_t *f;
248         size_t sz;
249         int errors = 0;
250         int abi = LIBPFM_ABI_VERSION;
251
252         printf("\tlibpfm ABI version : %d\n", abi);
253         for (d = pfmlib_structs; d->name; d++) {
254
255                 printf("\t%s : ", d->name);
256
257                 if (d->abi_sz != d->sz) {
258                         printf("struct size does not correspond to ABI size %zu vs. %zu)\n", d->abi_sz, d->sz);
259                         errors++;
260                 }
261
262                 if (d->sz % STRUCT_MULT) {
263                         printf("Failed (wrong mult size=%zu)\n", d->sz);
264                         errors++;
265                 }
266
267                 sz = d->bitfield_sz;
268                 for (f = d->fields; f->name; f++) {
269                         sz += f->sz;
270                 }
271
272                 if (sz != d->sz) {
273                         printf("Failed (invisible padding of %zu bytes)\n", d->sz - sz);
274                         errors++;
275                         continue;
276                 }
277                 printf("Passed\n");
278                 
279         }
280         return errors;
281 }
282
283 int
284 main(int argc, char **argv)
285 {
286         int ret, c, errors = 0;
287
288
289         while ((c=getopt(argc, argv,"hcaA")) != -1) {
290                 switch(c) {
291                         case 'c':
292                                 options.valid_intern = 1;
293                                 break;
294                         case 'a':
295                                 options.valid_arch = 1;
296                                 break;
297                         case 'A':
298                                 options.valid_arch = 1;
299                                 options.valid_intern = 1;
300                                 break;
301                         case 'h':
302                                 usage();
303                                 exit(0);
304                         default:
305                                 errx(1, "unknown option error");
306                 }
307         }
308         /* to allow encoding of events from non detected PMU models */
309         ret = set_env_var("LIBPFM_ENCODE_INACTIVE", "1", 1);
310         if (ret != PFM_SUCCESS)
311                 errx(1, "cannot force inactive encoding");
312
313         ret = pfm_initialize();
314         if (ret != PFM_SUCCESS)
315                 errx(1, "cannot initialize libpfm: %s", pfm_strerror(ret));
316
317         /* run everything by default */
318         if (!(options.valid_intern || options.valid_arch)) {
319                 options.valid_intern = 1;
320                 options.valid_arch = 1;
321         }
322
323         printf("Libpfm structure tests:\n");
324         errors += validate_structs();
325
326         if (options.valid_intern) {
327                 printf("Libpfm internal table tests:\n");
328                 errors += validate_event_tables();
329         }
330
331         if (options.valid_arch) {
332                 printf("Architecture specific tests:\n");
333                 errors += validate_arch(stderr);
334         }
335
336         pfm_terminate();
337
338         if (errors)
339                 printf("Total %d errors\n", errors);
340         else
341                 printf("All tests passed\n");
342
343         return errors;
344 }