Blame src/perfctr-2.6.x/linux/drivers/perfctr/marshal.c

Packit 577717
/* $Id: marshal.c,v 1.6.2.7 2008/06/22 12:48:56 mikpe Exp $
Packit 577717
 * Performance-monitoring counters driver.
Packit 577717
 * Structure marshalling support.
Packit 577717
 *
Packit 577717
 * Copyright (C) 2003-2008  Mikael Pettersson
Packit 577717
 */
Packit 577717
#ifdef __KERNEL__
Packit 577717
#include <linux/version.h>
Packit 577717
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
Packit 577717
#include <linux/config.h>
Packit 577717
#endif
Packit 577717
struct inode;
Packit 577717
#include <linux/sched.h>
Packit 577717
#include <linux/perfctr.h>
Packit 577717
#include <linux/errno.h>
Packit 577717
#include <linux/stddef.h>
Packit 577717
#include <linux/string.h>
Packit 577717
#include <asm/uaccess.h>
Packit 577717
#else	/* !__KERNEL__ */
Packit 577717
#define CONFIG_KPERFCTR
Packit 577717
#include <linux/perfctr.h>
Packit 577717
#include <sys/ioctl.h>
Packit 577717
#include <errno.h>
Packit 577717
#include <stddef.h>
Packit 577717
#include <string.h>
Packit 577717
#define put_user(w, p)	(*(p) = (w), 0)
Packit 577717
#define get_user(w, p)	((w) = *(p), 0)
Packit 577717
#endif	/* !__KERNEL__ */
Packit 577717
Packit 577717
#include "marshal.h"
Packit 577717
Packit 577717
/****************************************************************
Packit 577717
 *								*
Packit 577717
 * Struct encoding support.					*
Packit 577717
 *								*
Packit 577717
 ****************************************************************/
Packit 577717
Packit 577717
static void stream_write(struct perfctr_marshal_stream *stream, unsigned int word)
Packit 577717
{
Packit 577717
	if( !stream->error ) {
Packit 577717
		if( stream->pos >= stream->size )
Packit 577717
			stream->error = -EOVERFLOW;
Packit 577717
		else if( put_user(word, &stream->buffer[stream->pos]) )
Packit 577717
			stream->error = -EFAULT;
Packit 577717
	}
Packit 577717
	++stream->pos;
Packit 577717
}
Packit 577717
Packit 577717
static void encode_field(const void *address,
Packit 577717
			 const struct perfctr_field_desc *field,
Packit 577717
			 struct perfctr_marshal_stream *stream)
Packit 577717
{
Packit 577717
	unsigned int base_type = PERFCTR_TYPE_BASE(field->type);
Packit 577717
	unsigned int nr_items = PERFCTR_TYPE_NRITEMS(field->type);
Packit 577717
	unsigned int tag = field->tag;
Packit 577717
	const char *pointer = (const char*)address + field->offset;
Packit 577717
	unsigned int uint32_val;
Packit 577717
	union {
Packit 577717
		unsigned long long ull;
Packit 577717
		unsigned int ui[2];
Packit 577717
	} uint64_val;
Packit 577717
	unsigned int i = 0;
Packit 577717
Packit 577717
	do {
Packit 577717
		if( base_type == PERFCTR_TYPE_UINT64 ) {
Packit 577717
			uint64_val.ull = *(unsigned long long*)pointer;
Packit 577717
			pointer += sizeof(long long);
Packit 577717
			if( !uint64_val.ull )
Packit 577717
				continue;
Packit 577717
			stream_write(stream, PERFCTR_HEADER(PERFCTR_HEADER_UINT64, tag, i));
Packit 577717
			stream_write(stream, uint64_val.ui[0]);
Packit 577717
			stream_write(stream, uint64_val.ui[1]);
Packit 577717
		} else {		/* PERFCTR_TYPE_BYTES4 */
Packit 577717
			memcpy(&uint32_val, pointer, sizeof(int));
Packit 577717
			pointer += sizeof(int);	
Packit 577717
			if( !uint32_val )
Packit 577717
				continue;
Packit 577717
			stream_write(stream, PERFCTR_HEADER(PERFCTR_HEADER_UINT32, tag, i));
Packit 577717
			stream_write(stream, uint32_val);
Packit 577717
		}
Packit 577717
	} while( ++i < nr_items );
Packit 577717
}
Packit 577717
Packit 577717
void perfctr_encode_struct(const void *address,
Packit 577717
			   const struct perfctr_struct_desc *sdesc,
Packit 577717
			   struct perfctr_marshal_stream *stream)
Packit 577717
{
Packit 577717
	unsigned int i;
Packit 577717
Packit 577717
	for(i = 0; i < sdesc->nrfields; ++i)
Packit 577717
		encode_field(address, &sdesc->fields[i], stream);
Packit 577717
	for(i = 0; i < sdesc->nrsubs; ++i) {
Packit 577717
		const struct perfctr_sub_struct_desc *sub = &sdesc->subs[i];
Packit 577717
		perfctr_encode_struct((char*)address + sub->offset, sub->sdesc, stream);
Packit 577717
	}
Packit 577717
}
Packit 577717
Packit 577717
/****************************************************************
Packit 577717
 *								*
Packit 577717
 * Struct decoding support.					*
Packit 577717
 *								*
Packit 577717
 ****************************************************************/
Packit 577717
Packit 577717
static int stream_read(struct perfctr_marshal_stream *stream, unsigned int *word)
Packit 577717
{
Packit 577717
	if( stream->pos >= stream->size )
Packit 577717
		return 0;
Packit 577717
	if( get_user(*word, &stream->buffer[stream->pos]) )
Packit 577717
		return -EFAULT;
Packit 577717
	++stream->pos;
Packit 577717
	return 1;
Packit 577717
}
Packit 577717
Packit 577717
static const struct perfctr_field_desc*
Packit 577717
find_field(unsigned int *struct_offset,
Packit 577717
	   const struct perfctr_struct_desc *sdesc,
Packit 577717
	   unsigned int tag)
Packit 577717
{
Packit 577717
	unsigned int low, high, mid, i;
Packit 577717
	const struct perfctr_field_desc *field;
Packit 577717
	const struct perfctr_sub_struct_desc *sub;
Packit 577717
Packit 577717
	low = 0;
Packit 577717
	high = sdesc->nrfields;	/* [low,high[ */
Packit 577717
	while( low < high ) {
Packit 577717
		mid = (low + high) / 2;
Packit 577717
		field = &sdesc->fields[mid];
Packit 577717
		if( field->tag == tag )
Packit 577717
			return field;
Packit 577717
		if( field->tag < tag )
Packit 577717
			low = mid + 1;
Packit 577717
		else
Packit 577717
			high = mid;
Packit 577717
	}
Packit 577717
	for(i = 0; i < sdesc->nrsubs; ++i) {
Packit 577717
		sub = &sdesc->subs[i];
Packit 577717
		field = find_field(struct_offset, sub->sdesc, tag);
Packit 577717
		if( field ) {
Packit 577717
			*struct_offset += sub->offset;
Packit 577717
			return field;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
int perfctr_decode_struct(void *address,
Packit 577717
			  const struct perfctr_struct_desc *sdesc,
Packit 577717
			  struct perfctr_marshal_stream *stream)
Packit 577717
{
Packit 577717
	unsigned int header;
Packit 577717
	int err;
Packit 577717
	const struct perfctr_field_desc *field;
Packit 577717
	unsigned int struct_offset;
Packit 577717
	union {
Packit 577717
		unsigned long long ull;
Packit 577717
		unsigned int ui[2];
Packit 577717
	} val;
Packit 577717
	char *target;
Packit 577717
	unsigned int itemnr;
Packit 577717
Packit 577717
	for(;;) {
Packit 577717
		err = stream_read(stream, &header);
Packit 577717
		if( err <= 0 )
Packit 577717
			return err;
Packit 577717
		struct_offset = 0;
Packit 577717
		field = find_field(&struct_offset, sdesc, PERFCTR_HEADER_TAG(header));
Packit 577717
		if( !field )
Packit 577717
			goto err_eproto;
Packit 577717
		/* a 64-bit datum must have a 64-bit target field */
Packit 577717
		if( PERFCTR_HEADER_TYPE(header) != PERFCTR_HEADER_UINT32 &&
Packit 577717
		    PERFCTR_TYPE_BASE(field->type) != PERFCTR_TYPE_UINT64 )
Packit 577717
			goto err_eproto;
Packit 577717
		err = stream_read(stream, &val.ui[0]);
Packit 577717
		if( err <= 0 )
Packit 577717
			goto err_err;
Packit 577717
		target = (char*)address + struct_offset + field->offset;
Packit 577717
		itemnr = PERFCTR_HEADER_ITEMNR(header);
Packit 577717
		if( itemnr >= PERFCTR_TYPE_NRITEMS(field->type) )
Packit 577717
			goto err_eproto;
Packit 577717
		if( PERFCTR_TYPE_BASE(field->type) == PERFCTR_TYPE_UINT64 ) {
Packit 577717
			/* a 64-bit field must have a 64-bit datum */
Packit 577717
			if( PERFCTR_HEADER_TYPE(header) == PERFCTR_HEADER_UINT32 )
Packit 577717
				goto err_eproto;
Packit 577717
			err = stream_read(stream, &val.ui[1]);
Packit 577717
			if( err <= 0 )
Packit 577717
				goto err_err;
Packit 577717
			((unsigned long long*)target)[itemnr] = val.ull;
Packit 577717
		} else
Packit 577717
			memcpy(&((unsigned int*)target)[itemnr], &val.ui[0], sizeof(int));
Packit 577717
	}
Packit 577717
 err_err:	/* err ? err : -EPROTO */
Packit 577717
	if( err )
Packit 577717
		return err;
Packit 577717
 err_eproto:	/* saves object code over inlining it */
Packit 577717
	return -EPROTO;
Packit 577717
}
Packit 577717
Packit 577717
/****************************************************************
Packit 577717
 *								*
Packit 577717
 * Structure descriptors.					*
Packit 577717
 *								*
Packit 577717
 ****************************************************************/
Packit 577717
Packit 577717
#undef ARRAY_SIZE
Packit 577717
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
Packit 577717
#define STRUCT_ARRAY_SIZE(TYPE, MEMBER) ARRAY_SIZE(((TYPE*)0)->MEMBER)
Packit 577717
Packit 577717
#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__arm__)
Packit 577717
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_TSC_ON	32
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_NRACTRS	33
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_NRICTRS	34
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_PMC_MAP	35
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_EVNTSEL	36
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_IRESET	37
Packit 577717
/* 38-40 are arch-specific, see below */
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_RSVD1	41
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_RSVD2	42
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_RSVD3	43
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_RSVD4	44
Packit 577717
#define PERFCTR_CPU_CONTROL_NRFIELDS_0	(7 + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, pmc_map) + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, evntsel) + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, ireset))
Packit 577717
Packit 577717
#if defined(__i386__) || defined(__x86_64__)
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_P4_ESCR	38
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_P4_PE	39
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_P4_PMV	40
Packit 577717
#define PERFCTR_CPU_CONTROL_NRFIELDS_1	(2 + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, p4.escr))
Packit 577717
#endif	/* __i386__ || __x86_64__ */
Packit 577717
Packit 577717
#if defined(__powerpc__)
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_PPC_MMCR0	38
Packit 577717
#define PERFCTR_TAG_CPU_CONTROL_PPC_MMCR2	39
Packit 577717
/* 40: unused */
Packit 577717
#define PERFCTR_CPU_CONTROL_NRFIELDS_1	2
Packit 577717
#endif	/* __powerpc__ */
Packit 577717
Packit 577717
#if defined(__arm__)
Packit 577717
#define PERFCTR_CPU_CONTROL_NRFIELDS_1	0
Packit 577717
#endif
Packit 577717
Packit 577717
#define PERFCTR_CPU_CONTROL_NRFIELDS	(PERFCTR_CPU_CONTROL_NRFIELDS_0 + PERFCTR_CPU_CONTROL_NRFIELDS_1)
Packit 577717
Packit 577717
#define PERFCTR_TAG_SUM_CTRS_TSC	48
Packit 577717
#define PERFCTR_TAG_SUM_CTRS_PMC	49
Packit 577717
#define PERFCTR_SUM_CTRS_NRFIELDS	(1 + STRUCT_ARRAY_SIZE(struct perfctr_sum_ctrs, pmc))
Packit 577717
Packit 577717
static const struct perfctr_field_desc perfctr_sum_ctrs_fields[] = {
Packit 577717
	{ .offset = offsetof(struct perfctr_sum_ctrs, tsc),
Packit 577717
	  .tag = PERFCTR_TAG_SUM_CTRS_TSC,
Packit 577717
	  .type = PERFCTR_TYPE_UINT64 },
Packit 577717
	{ .offset = offsetof(struct perfctr_sum_ctrs, pmc),
Packit 577717
	  .tag = PERFCTR_TAG_SUM_CTRS_PMC,
Packit 577717
	  .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_sum_ctrs,pmc),
Packit 577717
				     PERFCTR_TYPE_UINT64) },
Packit 577717
};
Packit 577717
Packit 577717
const struct perfctr_struct_desc perfctr_sum_ctrs_sdesc = {
Packit 577717
	.total_sizeof = sizeof(struct perfctr_sum_ctrs),
Packit 577717
	.total_nrfields = PERFCTR_SUM_CTRS_NRFIELDS,
Packit 577717
	.nrfields = ARRAY_SIZE(perfctr_sum_ctrs_fields),
Packit 577717
	.fields = perfctr_sum_ctrs_fields,
Packit 577717
};
Packit 577717
Packit 577717
static const struct perfctr_field_desc perfctr_cpu_control_fields[] = {
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, tsc_on),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_TSC_ON,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, nractrs),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_NRACTRS,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, nrictrs),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_NRICTRS,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, pmc_map),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_PMC_MAP,
Packit 577717
	  .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,pmc_map),
Packit 577717
				     PERFCTR_TYPE_BYTES4) },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, evntsel),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_EVNTSEL,
Packit 577717
	  .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,evntsel),
Packit 577717
				     PERFCTR_TYPE_BYTES4) },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, ireset),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_IRESET,
Packit 577717
	  .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,ireset),
Packit 577717
				     PERFCTR_TYPE_BYTES4) },
Packit 577717
#if defined(__i386__) || defined(__x86_64__)
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, p4.escr),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_P4_ESCR,
Packit 577717
	  .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,p4.escr),
Packit 577717
				     PERFCTR_TYPE_BYTES4) },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, p4.pebs_enable),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_P4_PE,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, p4.pebs_matrix_vert),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_P4_PMV,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
#endif	/* __i386__ || __x86_64__ */
Packit 577717
#if defined(__powerpc__)
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, ppc.mmcr0),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_PPC_MMCR0,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, ppc.mmcr2),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_PPC_MMCR2,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
#endif	/* __powerpc__ */
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, _reserved1),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_RSVD1,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, _reserved2),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_RSVD2,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, _reserved3),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_RSVD3,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_cpu_control, _reserved4),
Packit 577717
	  .tag = PERFCTR_TAG_CPU_CONTROL_RSVD4,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
};
Packit 577717
Packit 577717
const struct perfctr_struct_desc perfctr_cpu_control_sdesc = {
Packit 577717
	.total_sizeof = sizeof(struct perfctr_cpu_control),
Packit 577717
	.total_nrfields = PERFCTR_CPU_CONTROL_NRFIELDS,
Packit 577717
	.nrfields = ARRAY_SIZE(perfctr_cpu_control_fields),
Packit 577717
	.fields = perfctr_cpu_control_fields,
Packit 577717
};
Packit 577717
Packit 577717
#endif	/* __i386__ || __x86_64__ || __powerpc__ */
Packit 577717
Packit 577717
#define PERFCTR_TAG_INFO_ABI_VERSION		0
Packit 577717
#define PERFCTR_TAG_INFO_DRIVER_VERSION		1
Packit 577717
#define PERFCTR_TAG_INFO_CPU_TYPE		2
Packit 577717
#define PERFCTR_TAG_INFO_CPU_FEATURES		3
Packit 577717
#define PERFCTR_TAG_INFO_CPU_KHZ		4
Packit 577717
#define PERFCTR_TAG_INFO_TSC_TO_CPU_MULT	5
Packit 577717
#define PERFCTR_TAG_INFO_RSVD2			6
Packit 577717
#define PERFCTR_TAG_INFO_RSVD3			7
Packit 577717
#define PERFCTR_TAG_INFO_RSVD4			8
Packit 577717
#define PERFCTR_INFO_NRFIELDS	(8 + sizeof(((struct perfctr_info*)0)->driver_version)/sizeof(int))
Packit 577717
Packit 577717
#define VPERFCTR_TAG_CONTROL_SIGNO		9
Packit 577717
#define VPERFCTR_TAG_CONTROL_PRESERVE		10
Packit 577717
#define VPERFCTR_TAG_CONTROL_FLAGS		11
Packit 577717
#define VPERFCTR_TAG_CONTROL_RSVD2		12
Packit 577717
#define VPERFCTR_TAG_CONTROL_RSVD3		13
Packit 577717
#define VPERFCTR_TAG_CONTROL_RSVD4		14
Packit 577717
#define VPERFCTR_CONTROL_NRFIELDS		(6 + PERFCTR_CPU_CONTROL_NRFIELDS)
Packit 577717
Packit 577717
#define GPERFCTR_TAG_CPU_CONTROL_CPU		15
Packit 577717
#define GPERFCTR_TAG_CPU_CONTROL_RSVD1		16
Packit 577717
#define GPERFCTR_TAG_CPU_CONTROL_RSVD2		17
Packit 577717
#define GPERFCTR_TAG_CPU_CONTROL_RSVD3		18
Packit 577717
#define GPERFCTR_TAG_CPU_CONTROL_RSVD4		19
Packit 577717
#define GPERFCTR_CPU_CONTROL_NRFIELDS		(5 + PERFCTR_CPU_CONTROL_NRFIELDS)
Packit 577717
Packit 577717
#define GPERFCTR_TAG_CPU_STATE_CPU		20
Packit 577717
#define GPERFCTR_TAG_CPU_STATE_RSVD1		21
Packit 577717
#define GPERFCTR_TAG_CPU_STATE_RSVD2		22
Packit 577717
#define GPERFCTR_TAG_CPU_STATE_RSVD3		23
Packit 577717
#define GPERFCTR_TAG_CPU_STATE_RSVD4		24
Packit 577717
#define GPERFCTR_CPU_STATE_ONLY_CPU_NRFIELDS	5
Packit 577717
#define GPERFCTR_CPU_STATE_NRFIELDS	(GPERFCTR_CPU_STATE_ONLY_CPU_NRFIELDS + PERFCTR_CPU_CONTROL_NRFIELDS + PERFCTR_SUM_CTRS_NRFIELDS)
Packit 577717
Packit 577717
static const struct perfctr_field_desc perfctr_info_fields[] = {
Packit 577717
	{ .offset = offsetof(struct perfctr_info, abi_version),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_ABI_VERSION,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_info, driver_version),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_DRIVER_VERSION,
Packit 577717
	  .type = PERFCTR_TYPE_ARRAY(sizeof(((struct perfctr_info*)0)->driver_version)/sizeof(int), PERFCTR_TYPE_BYTES4) },
Packit 577717
	{ .offset = offsetof(struct perfctr_info, cpu_type),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_CPU_TYPE,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_info, cpu_features),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_CPU_FEATURES,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_info, cpu_khz),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_CPU_KHZ,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_info, tsc_to_cpu_mult),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_TSC_TO_CPU_MULT,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_info, _reserved2),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_RSVD2,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_info, _reserved3),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_RSVD3,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct perfctr_info, _reserved4),
Packit 577717
	  .tag = PERFCTR_TAG_INFO_RSVD4,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
};
Packit 577717
Packit 577717
const struct perfctr_struct_desc perfctr_info_sdesc = {
Packit 577717
	.total_sizeof = sizeof(struct perfctr_info),
Packit 577717
	.total_nrfields = PERFCTR_INFO_NRFIELDS,
Packit 577717
	.nrfields = ARRAY_SIZE(perfctr_info_fields),
Packit 577717
	.fields = perfctr_info_fields,
Packit 577717
};
Packit 577717
Packit 577717
#if defined(CONFIG_PERFCTR_VIRTUAL) || !defined(__KERNEL__)
Packit 577717
static const struct perfctr_field_desc vperfctr_control_fields[] = {
Packit 577717
	{ .offset = offsetof(struct vperfctr_control, si_signo),
Packit 577717
	  .tag = VPERFCTR_TAG_CONTROL_SIGNO,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct vperfctr_control, preserve),
Packit 577717
	  .tag = VPERFCTR_TAG_CONTROL_PRESERVE,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct vperfctr_control, flags),
Packit 577717
	  .tag = VPERFCTR_TAG_CONTROL_FLAGS,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct vperfctr_control, _reserved2),
Packit 577717
	  .tag = VPERFCTR_TAG_CONTROL_RSVD2,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct vperfctr_control, _reserved3),
Packit 577717
	  .tag = VPERFCTR_TAG_CONTROL_RSVD3,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct vperfctr_control, _reserved4),
Packit 577717
	  .tag = VPERFCTR_TAG_CONTROL_RSVD4,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
};
Packit 577717
Packit 577717
static const struct perfctr_sub_struct_desc vperfctr_control_subs[] = {
Packit 577717
	{ .offset = offsetof(struct vperfctr_control, cpu_control),
Packit 577717
	  .sdesc = &perfctr_cpu_control_sdesc },
Packit 577717
};
Packit 577717
Packit 577717
const struct perfctr_struct_desc vperfctr_control_sdesc = {
Packit 577717
	.total_sizeof = sizeof(struct vperfctr_control),
Packit 577717
	.total_nrfields = VPERFCTR_CONTROL_NRFIELDS,
Packit 577717
	.nrfields = ARRAY_SIZE(vperfctr_control_fields),
Packit 577717
	.fields = vperfctr_control_fields,
Packit 577717
	.nrsubs = ARRAY_SIZE(vperfctr_control_subs),
Packit 577717
	.subs = vperfctr_control_subs,
Packit 577717
};
Packit 577717
#endif	/* CONFIG_PERFCTR_VIRTUAL || !__KERNEL__ */
Packit 577717
Packit 577717
#if defined(CONFIG_PERFCTR_GLOBAL) || !defined(__KERNEL__)
Packit 577717
static const struct perfctr_field_desc gperfctr_cpu_control_fields[] = {
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_control, cpu),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_CONTROL_CPU,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_control, _reserved1),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_CONTROL_RSVD1,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_control, _reserved2),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_CONTROL_RSVD2,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_control, _reserved3),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_CONTROL_RSVD3,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_control, _reserved4),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_CONTROL_RSVD4,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
};
Packit 577717
Packit 577717
static const struct perfctr_sub_struct_desc gperfctr_cpu_control_subs[] = {
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_control, cpu_control),
Packit 577717
	  .sdesc = &perfctr_cpu_control_sdesc },
Packit 577717
};
Packit 577717
Packit 577717
const struct perfctr_struct_desc gperfctr_cpu_control_sdesc = {
Packit 577717
	.total_sizeof = sizeof(struct gperfctr_cpu_control),
Packit 577717
	.total_nrfields = GPERFCTR_CPU_CONTROL_NRFIELDS,
Packit 577717
	.nrfields = ARRAY_SIZE(gperfctr_cpu_control_fields),
Packit 577717
	.fields = gperfctr_cpu_control_fields,
Packit 577717
	.nrsubs = ARRAY_SIZE(gperfctr_cpu_control_subs),
Packit 577717
	.subs = gperfctr_cpu_control_subs,
Packit 577717
};
Packit 577717
Packit 577717
static const struct perfctr_field_desc gperfctr_cpu_state_fields[] = {
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_state, cpu),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_STATE_CPU,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_state, _reserved1),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_STATE_RSVD1,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_state, _reserved2),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_STATE_RSVD2,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_state, _reserved3),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_STATE_RSVD3,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_state, _reserved4),
Packit 577717
	  .tag = GPERFCTR_TAG_CPU_STATE_RSVD4,
Packit 577717
	  .type = PERFCTR_TYPE_BYTES4 },
Packit 577717
};
Packit 577717
Packit 577717
static const struct perfctr_sub_struct_desc gperfctr_cpu_state_subs[] = {
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_state, cpu_control),
Packit 577717
	  .sdesc = &perfctr_cpu_control_sdesc },
Packit 577717
	{ .offset = offsetof(struct gperfctr_cpu_state, sum),
Packit 577717
	  .sdesc = &perfctr_sum_ctrs_sdesc },
Packit 577717
};
Packit 577717
Packit 577717
const struct perfctr_struct_desc gperfctr_cpu_state_only_cpu_sdesc = {
Packit 577717
	.total_sizeof = sizeof(struct gperfctr_cpu_state),
Packit 577717
	.total_nrfields = GPERFCTR_CPU_STATE_ONLY_CPU_NRFIELDS,
Packit 577717
	.nrfields = ARRAY_SIZE(gperfctr_cpu_state_fields),
Packit 577717
	.fields = gperfctr_cpu_state_fields,
Packit 577717
};
Packit 577717
Packit 577717
const struct perfctr_struct_desc gperfctr_cpu_state_sdesc = {
Packit 577717
	.total_sizeof = sizeof(struct gperfctr_cpu_state),
Packit 577717
	.total_nrfields = GPERFCTR_CPU_STATE_NRFIELDS,
Packit 577717
	.nrfields = ARRAY_SIZE(gperfctr_cpu_state_fields),
Packit 577717
	.fields = gperfctr_cpu_state_fields,
Packit 577717
	.nrsubs = ARRAY_SIZE(gperfctr_cpu_state_subs),
Packit 577717
	.subs = gperfctr_cpu_state_subs,
Packit 577717
};
Packit 577717
#endif	/* CONFIG_PERFCTR_GLOBAL || !__KERNEL__ */
Packit 577717
Packit 577717
#ifdef __KERNEL__
Packit 577717
Packit 577717
int perfctr_copy_from_user(void *struct_address,
Packit 577717
			   struct perfctr_struct_buf *argp,
Packit 577717
			   const struct perfctr_struct_desc *sdesc)
Packit 577717
{
Packit 577717
	struct perfctr_marshal_stream stream;
Packit 577717
Packit 577717
	if( get_user(stream.size, &argp->rdsize) )
Packit 577717
		return -EFAULT;
Packit 577717
	stream.buffer = argp->buffer;
Packit 577717
	stream.pos = 0;
Packit 577717
	stream.error = 0;
Packit 577717
	memset(struct_address, 0, sdesc->total_sizeof);
Packit 577717
	return perfctr_decode_struct(struct_address, sdesc, &stream);
Packit 577717
}
Packit 577717
Packit 577717
int perfctr_copy_to_user(struct perfctr_struct_buf *argp,
Packit 577717
			 void *struct_address,
Packit 577717
			 const struct perfctr_struct_desc *sdesc)
Packit 577717
{
Packit 577717
	struct perfctr_marshal_stream stream;
Packit 577717
Packit 577717
	if( get_user(stream.size, &argp->wrsize) )
Packit 577717
		return -EFAULT;
Packit 577717
	stream.buffer = argp->buffer;
Packit 577717
	stream.pos = 0;
Packit 577717
	stream.error = 0;
Packit 577717
	perfctr_encode_struct(struct_address, sdesc, &stream);
Packit 577717
	if( stream.error )
Packit 577717
		return stream.error;
Packit 577717
	if( put_user(stream.pos, &argp->rdsize) )
Packit 577717
		return -EFAULT;
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
#else	/* !__KERNEL__ */
Packit 577717
Packit 577717
#define sdesc_bufsize(sdesc)	((sdesc)->total_nrfields + (sdesc)->total_sizeof/sizeof(int))
Packit 577717
Packit 577717
static int common_ioctl_w(const void *arg,
Packit 577717
			  const struct perfctr_struct_desc *sdesc,
Packit 577717
			  struct perfctr_struct_buf *buf,
Packit 577717
			  unsigned int bufsize)
Packit 577717
{
Packit 577717
	struct perfctr_marshal_stream stream;
Packit 577717
Packit 577717
	stream.size = bufsize;
Packit 577717
	stream.buffer = buf->buffer;
Packit 577717
	stream.pos = 0;
Packit 577717
	stream.error = 0;
Packit 577717
	perfctr_encode_struct(arg, sdesc, &stream);
Packit 577717
	if( stream.error ) {
Packit 577717
		errno = -stream.error;
Packit 577717
		return -1;
Packit 577717
	}
Packit 577717
	buf->rdsize = stream.pos;
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
int perfctr_ioctl_w(int fd, unsigned int cmd, const void *arg,
Packit 577717
		    const struct perfctr_struct_desc *sdesc)
Packit 577717
{
Packit 577717
	unsigned int bufsize = sdesc_bufsize(sdesc);
Packit 577717
	union {
Packit 577717
		struct perfctr_struct_buf buf;
Packit 577717
		struct {
Packit 577717
			unsigned int rdsize;
Packit 577717
			unsigned int wrsize;
Packit 577717
			unsigned int buffer[bufsize];
Packit 577717
		} buf_bufsize;
Packit 577717
	} u;
Packit 577717
	int err;
Packit 577717
Packit 577717
	err = common_ioctl_w(arg, sdesc, &u.buf, bufsize);
Packit 577717
	if( err < 0 )
Packit 577717
		return err;
Packit 577717
	u.buf.wrsize = 0;
Packit 577717
	return ioctl(fd, cmd, &u.buf);
Packit 577717
}
Packit 577717
Packit 577717
static int common_ioctl_r(int fd, unsigned int cmd, void *res,
Packit 577717
			   const struct perfctr_struct_desc *sdesc,
Packit 577717
			   struct perfctr_struct_buf *buf)
Packit 577717
{
Packit 577717
	struct perfctr_marshal_stream stream;
Packit 577717
	int err;
Packit 577717
Packit 577717
	if( ioctl(fd, cmd, buf) < 0 )
Packit 577717
		return -1;
Packit 577717
	stream.size = buf->rdsize;
Packit 577717
	stream.buffer = buf->buffer;
Packit 577717
	stream.pos = 0;
Packit 577717
	stream.error = 0;
Packit 577717
	memset(res, 0, sdesc->total_sizeof);
Packit 577717
	err = perfctr_decode_struct(res, sdesc, &stream);
Packit 577717
	if( err < 0 ) {
Packit 577717
		errno = -err;
Packit 577717
		return -1;
Packit 577717
	}
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
int perfctr_ioctl_r(int fd, unsigned int cmd, void *res,
Packit 577717
		    const struct perfctr_struct_desc *sdesc)
Packit 577717
{
Packit 577717
	unsigned int bufsize = sdesc_bufsize(sdesc);
Packit 577717
	union {
Packit 577717
		struct perfctr_struct_buf buf;
Packit 577717
		struct {
Packit 577717
			unsigned int rdsize;
Packit 577717
			unsigned int wrsize;
Packit 577717
			unsigned int buffer[bufsize];
Packit 577717
		} buf_bufsize;
Packit 577717
	} u;
Packit 577717
Packit 577717
	u.buf.rdsize = 0;
Packit 577717
	u.buf.wrsize = bufsize;
Packit 577717
	return common_ioctl_r(fd, cmd, res, sdesc, &u.buf);
Packit 577717
}
Packit 577717
Packit 577717
int perfctr_ioctl_wr(int fd, unsigned int cmd, void *argres,
Packit 577717
		     const struct perfctr_struct_desc *arg_sdesc,
Packit 577717
		     const struct perfctr_struct_desc *res_sdesc)
Packit 577717
{
Packit 577717
	unsigned int arg_bufsize = sdesc_bufsize(arg_sdesc);
Packit 577717
	unsigned int res_bufsize = sdesc_bufsize(res_sdesc);
Packit 577717
	unsigned int bufsize = arg_bufsize > res_bufsize ? arg_bufsize : res_bufsize;
Packit 577717
	union {
Packit 577717
		struct perfctr_struct_buf buf;
Packit 577717
		struct {
Packit 577717
			unsigned int rdsize;
Packit 577717
			unsigned int wrsize;
Packit 577717
			unsigned int buffer[bufsize];
Packit 577717
		} buf_bufsize;
Packit 577717
	} u;
Packit 577717
	int err;
Packit 577717
Packit 577717
	err = common_ioctl_w(argres, arg_sdesc, &u.buf, arg_bufsize);
Packit 577717
	if( err < 0 )
Packit 577717
		return err;
Packit 577717
	u.buf.wrsize = res_bufsize;
Packit 577717
	return common_ioctl_r(fd, cmd, argres, res_sdesc, &u.buf);
Packit 577717
}
Packit 577717
Packit 577717
#endif /* !__KERNEL__ */