|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* validate.c - validate event tables + encodings
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2010 Google, Inc
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@gmail.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
577717 |
* of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
577717 |
* in the Software without restriction, including without limitation the rights
|
|
Packit |
577717 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
577717 |
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
Packit |
577717 |
* subject to the following conditions:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The above copyright notice and this permission notice shall be included in all
|
|
Packit |
577717 |
* copies or substantial portions of the Software.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
Packit |
577717 |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit |
577717 |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
577717 |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
Packit |
577717 |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
Packit |
577717 |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* This file is part of libpfm, a performance monitoring support library for
|
|
Packit |
577717 |
* applications on Linux.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <inttypes.h>
|
|
Packit |
577717 |
#include <stdarg.h>
|
|
Packit |
577717 |
#include <errno.h>
|
|
Packit |
577717 |
#include <unistd.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <perfmon/err.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <perfmon/pfmlib.h>
|
|
Packit |
577717 |
#ifdef __linux__
|
|
Packit |
577717 |
#include <perfmon/pfmlib_perf_event.h>
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define __weak_func __attribute__((weak))
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef PFMLIB_WINDOWS
|
|
Packit |
577717 |
int set_env_var(const char *var, const char *value, int ov)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
size_t len;
|
|
Packit |
577717 |
char *str;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
len = strlen(var) + 1 + strlen(value) + 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = malloc(len);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
return PFM_ERR_NOMEM;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sprintf(str, "%s=%s", var, value);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = putenv(str);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
free(str);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret ? PFM_ERR_INVAL : PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
set_env_var(const char *var, const char *value, int ov)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return setenv(var, value, ov);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__weak_func int validate_arch(FILE *fp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static struct {
|
|
Packit |
577717 |
int valid_intern;
|
|
Packit |
577717 |
int valid_arch;
|
|
Packit |
577717 |
} options;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
usage(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
printf("validate [-c] [-a] [-A]\n"
|
|
Packit |
577717 |
"-c\trun the library validate events\n"
|
|
Packit |
577717 |
"-a\trun architecture specific event tests\n"
|
|
Packit |
577717 |
"-A\trun all tests\n"
|
|
Packit |
577717 |
"-h\tget help\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
validate_event_tables(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_info_t pinfo;
|
|
Packit |
577717 |
int i, ret, errors = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&pinfo, 0, sizeof(pinfo));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pinfo.size = sizeof(pinfo);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_for_all_pmus(i) {
|
|
Packit |
577717 |
ret = pfm_get_pmu_info(i, &pinfo);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
printf("\tchecking %s (%d events): ", pinfo.name, pinfo.nevents);
|
|
Packit |
577717 |
fflush(stdout);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_pmu_validate(i, stdout);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS && ret != PFM_ERR_NOTSUPP) {
|
|
Packit |
577717 |
printf("Failed\n");
|
|
Packit |
577717 |
errors++;
|
|
Packit |
577717 |
} else if (ret == PFM_ERR_NOTSUPP) {
|
|
Packit |
577717 |
printf("N/A\n");
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
printf("Passed\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return errors;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if __WORDSIZE == 64
|
|
Packit |
577717 |
#define STRUCT_MULT 8
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
#define STRUCT_MULT 4
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define MAX_FIELDS 32
|
|
Packit |
577717 |
typedef struct {
|
|
Packit |
577717 |
const char *name;
|
|
Packit |
577717 |
size_t sz;
|
|
Packit |
577717 |
} field_desc_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
typedef struct {
|
|
Packit |
577717 |
const char *name;
|
|
Packit |
577717 |
size_t sz;
|
|
Packit |
577717 |
size_t bitfield_sz;
|
|
Packit |
577717 |
size_t abi_sz;
|
|
Packit |
577717 |
field_desc_t fields[MAX_FIELDS];
|
|
Packit |
577717 |
} struct_desc_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define LAST_STRUCT { .name = NULL, }
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define FIELD(n, st) \
|
|
Packit |
577717 |
{ .name = #n, \
|
|
Packit |
577717 |
.sz = sizeof(((st *)(0))->n), \
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#define LAST_FIELD { .name = NULL, }
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static const struct_desc_t pfmlib_structs[]={
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
.name = "pfm_pmu_info_t",
|
|
Packit |
577717 |
.sz = sizeof(pfm_pmu_info_t),
|
|
Packit |
577717 |
.bitfield_sz = 4,
|
|
Packit |
577717 |
.abi_sz = PFM_PMU_INFO_ABI0,
|
|
Packit |
577717 |
.fields= {
|
|
Packit |
577717 |
FIELD(name, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(desc, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(size, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(pmu, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(type, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(nevents, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(first_event, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(max_encoding, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(num_cntrs, pfm_pmu_info_t),
|
|
Packit |
577717 |
FIELD(num_fixed_cntrs, pfm_pmu_info_t),
|
|
Packit |
577717 |
LAST_FIELD
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
.name = "pfm_event_info_t",
|
|
Packit |
577717 |
.sz = sizeof(pfm_event_info_t),
|
|
Packit |
577717 |
.bitfield_sz = 4,
|
|
Packit |
577717 |
.abi_sz = PFM_EVENT_INFO_ABI0,
|
|
Packit |
577717 |
.fields= {
|
|
Packit |
577717 |
FIELD(name, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(desc, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(equiv, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(size, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(code, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(pmu, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(dtype, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(idx, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(nattrs, pfm_event_info_t),
|
|
Packit |
577717 |
FIELD(reserved, pfm_event_info_t),
|
|
Packit |
577717 |
LAST_FIELD
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
.name = "pfm_event_attr_info_t",
|
|
Packit |
577717 |
.sz = sizeof(pfm_event_attr_info_t),
|
|
Packit |
577717 |
.bitfield_sz = 4+8,
|
|
Packit |
577717 |
.abi_sz = PFM_ATTR_INFO_ABI0,
|
|
Packit |
577717 |
.fields= {
|
|
Packit |
577717 |
FIELD(name, pfm_event_attr_info_t),
|
|
Packit |
577717 |
FIELD(desc, pfm_event_attr_info_t),
|
|
Packit |
577717 |
FIELD(equiv, pfm_event_attr_info_t),
|
|
Packit |
577717 |
FIELD(size, pfm_event_attr_info_t),
|
|
Packit |
577717 |
FIELD(code, pfm_event_attr_info_t),
|
|
Packit |
577717 |
FIELD(type, pfm_event_attr_info_t),
|
|
Packit |
577717 |
FIELD(idx, pfm_event_attr_info_t),
|
|
Packit |
577717 |
FIELD(ctrl, pfm_event_attr_info_t),
|
|
Packit |
577717 |
LAST_FIELD
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
.name = "pfm_pmu_encode_arg_t",
|
|
Packit |
577717 |
.sz = sizeof(pfm_pmu_encode_arg_t),
|
|
Packit |
577717 |
.abi_sz = PFM_RAW_ENCODE_ABI0,
|
|
Packit |
577717 |
.fields= {
|
|
Packit |
577717 |
FIELD(codes, pfm_pmu_encode_arg_t),
|
|
Packit |
577717 |
FIELD(fstr, pfm_pmu_encode_arg_t),
|
|
Packit |
577717 |
FIELD(size, pfm_pmu_encode_arg_t),
|
|
Packit |
577717 |
FIELD(count, pfm_pmu_encode_arg_t),
|
|
Packit |
577717 |
FIELD(idx, pfm_pmu_encode_arg_t),
|
|
Packit |
577717 |
LAST_FIELD
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
#ifdef __linux__
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
.name = "pfm_perf_encode_arg_t",
|
|
Packit |
577717 |
.sz = sizeof(pfm_perf_encode_arg_t),
|
|
Packit |
577717 |
.bitfield_sz = 0,
|
|
Packit |
577717 |
.abi_sz = PFM_PERF_ENCODE_ABI0,
|
|
Packit |
577717 |
.fields= {
|
|
Packit |
577717 |
FIELD(attr, pfm_perf_encode_arg_t),
|
|
Packit |
577717 |
FIELD(fstr, pfm_perf_encode_arg_t),
|
|
Packit |
577717 |
FIELD(size, pfm_perf_encode_arg_t),
|
|
Packit |
577717 |
FIELD(idx, pfm_perf_encode_arg_t),
|
|
Packit |
577717 |
FIELD(cpu, pfm_perf_encode_arg_t),
|
|
Packit |
577717 |
FIELD(flags, pfm_perf_encode_arg_t),
|
|
Packit |
577717 |
FIELD(pad0, pfm_perf_encode_arg_t),
|
|
Packit |
577717 |
LAST_FIELD
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
LAST_STRUCT
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
validate_structs(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
|
|
Packit |
577717 |
const struct_desc_t *d;
|
|
Packit |
577717 |
const field_desc_t *f;
|
|
Packit |
577717 |
size_t sz;
|
|
Packit |
577717 |
int errors = 0;
|
|
Packit |
577717 |
int abi = LIBPFM_ABI_VERSION;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
printf("\tlibpfm ABI version : %d\n", abi);
|
|
Packit |
577717 |
for (d = pfmlib_structs; d->name; d++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
printf("\t%s : ", d->name);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (d->abi_sz != d->sz) {
|
|
Packit |
577717 |
printf("struct size does not correspond to ABI size %zu vs. %zu)\n", d->abi_sz, d->sz);
|
|
Packit |
577717 |
errors++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (d->sz % STRUCT_MULT) {
|
|
Packit |
577717 |
printf("Failed (wrong mult size=%zu)\n", d->sz);
|
|
Packit |
577717 |
errors++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sz = d->bitfield_sz;
|
|
Packit |
577717 |
for (f = d->fields; f->name; f++) {
|
|
Packit |
577717 |
sz += f->sz;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (sz != d->sz) {
|
|
Packit |
577717 |
printf("Failed (invisible padding of %zu bytes, total struct size %zu bytes)\n", d->sz - sz, d->sz);
|
|
Packit |
577717 |
errors++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
printf("Passed\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return errors;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
main(int argc, char **argv)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret, c, errors = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while ((c=getopt(argc, argv,"hcaA")) != -1) {
|
|
Packit |
577717 |
switch(c) {
|
|
Packit |
577717 |
case 'c':
|
|
Packit |
577717 |
options.valid_intern = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 'a':
|
|
Packit |
577717 |
options.valid_arch = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 'A':
|
|
Packit |
577717 |
options.valid_arch = 1;
|
|
Packit |
577717 |
options.valid_intern = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 'h':
|
|
Packit |
577717 |
usage();
|
|
Packit |
577717 |
exit(0);
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
errx(1, "unknown option error");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* to allow encoding of events from non detected PMU models */
|
|
Packit |
577717 |
ret = set_env_var("LIBPFM_ENCODE_INACTIVE", "1", 1);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
errx(1, "cannot force inactive encoding");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_initialize();
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
errx(1, "cannot initialize libpfm: %s", pfm_strerror(ret));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* run everything by default */
|
|
Packit |
577717 |
if (!(options.valid_intern || options.valid_arch)) {
|
|
Packit |
577717 |
options.valid_intern = 1;
|
|
Packit |
577717 |
options.valid_arch = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
printf("Libpfm structure tests:\n");
|
|
Packit |
577717 |
errors += validate_structs();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (options.valid_intern) {
|
|
Packit |
577717 |
printf("Libpfm internal table tests:\n");
|
|
Packit |
577717 |
errors += validate_event_tables();
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (options.valid_arch) {
|
|
Packit |
577717 |
printf("Architecture specific tests:\n");
|
|
Packit |
577717 |
errors += validate_arch(stderr);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_terminate();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (errors)
|
|
Packit |
577717 |
printf("Total %d errors\n", errors);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
printf("All tests passed\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return errors;
|
|
Packit |
577717 |
}
|