Blame src/libpfm4/tests/validate.c

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
}