|
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__ */
|