Blame src/libpfm4/tests/validate.c

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