# HG changeset patch # User gingold@virtu10 # Node ID 2c06898a1e8448dfe3b2efdfaa6a79493d362422 # Parent f353f99397732f9f229abc430ad5da096b1c3b6f Change DOM0_PERFCCONTROL: remove array limit. Descriptors and values are passed by two distinct buffers. Signed-off-by: Tristan Gingold diff -r f353f9939773 -r 2c06898a1e84 tools/libxc/xc_misc.c --- a/tools/libxc/xc_misc.c Mon Aug 07 06:37:21 2006 +0200 +++ b/tools/libxc/xc_misc.c Mon Aug 07 09:08:45 2006 +0200 @@ -68,7 +68,10 @@ int xc_sched_id(int xc_handle, int xc_perfc_control(int xc_handle, uint32_t opcode, - xc_perfc_desc_t *desc) + xc_perfc_desc_t *desc, + xc_perfc_val_t *val, + int *nbr_desc, + int *nbr_val) { int rc; DECLARE_DOM0_OP; @@ -76,10 +79,16 @@ int xc_perfc_control(int xc_handle, op.cmd = DOM0_PERFCCONTROL; op.u.perfccontrol.op = opcode; set_xen_guest_handle(op.u.perfccontrol.desc, desc); + set_xen_guest_handle(op.u.perfccontrol.val, val); rc = do_dom0_op(xc_handle, &op); - return (rc == 0) ? op.u.perfccontrol.nr_counters : rc; + if (nbr_desc) + *nbr_desc = op.u.perfccontrol.nr_counters; + if (nbr_val) + *nbr_val = op.u.perfccontrol.nr_vals; + + return rc; } long long xc_msr_read(int xc_handle, int cpu_mask, int msr) diff -r f353f9939773 -r 2c06898a1e84 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Mon Aug 07 06:37:21 2006 +0200 +++ b/tools/libxc/xenctrl.h Mon Aug 07 09:08:45 2006 +0200 @@ -466,10 +466,15 @@ unsigned long xc_make_page_below_4G(int unsigned long mfn); typedef dom0_perfc_desc_t xc_perfc_desc_t; -/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */ +typedef dom0_perfc_val_t xc_perfc_val_t; +/* IMPORTANT: The caller is responsible for mlock()'ing the @desc and @val + arrays. */ int xc_perfc_control(int xc_handle, uint32_t op, - xc_perfc_desc_t *desc); + xc_perfc_desc_t *desc, + xc_perfc_val_t *val, + int *nbr_desc, + int *nbr_val); /* read/write msr */ long long xc_msr_read(int xc_handle, int cpu_mask, int msr); diff -r f353f9939773 -r 2c06898a1e84 tools/misc/xenperf.c --- a/tools/misc/xenperf.c Mon Aug 07 06:37:21 2006 +0200 +++ b/tools/misc/xenperf.c Mon Aug 07 09:08:45 2006 +0200 @@ -22,7 +22,10 @@ int main(int argc, char *argv[]) { int i, j, xc_handle; xc_perfc_desc_t *pcd; - unsigned int num, sum, reset = 0, full = 0; + xc_perfc_val_t *pcv; + xc_perfc_val_t *val; + int num_desc, num_val; + unsigned int sum, reset = 0, full = 0; if ( argc > 1 ) { @@ -62,7 +65,7 @@ int main(int argc, char *argv[]) if ( reset ) { if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_RESET, - NULL) < 0 ) + NULL, NULL, NULL, NULL) != 0 ) { fprintf(stderr, "Error reseting performance counters: %d (%s)\n", errno, strerror(errno)); @@ -72,47 +75,54 @@ int main(int argc, char *argv[]) return 0; } + if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, + NULL, NULL, &num_desc, &num_val) != 0 ) + { + fprintf(stderr, "Error getting number of perf counters: %d (%s)\n", + errno, strerror(errno)); + return 1; + } - if ( (num = xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, - NULL)) < 0 ) + pcd = malloc(sizeof(*pcd) * num_desc); + pcv = malloc(sizeof(*pcv) * num_val); + + if ( pcd == NULL + || mlock(pcd, sizeof(*pcd) * num_desc) != 0 + || pcv == NULL + || mlock(pcd, sizeof(*pcv) * num_val) != 0) { - fprintf(stderr, "Error getting number of perf counters: %d (%s)\n", + fprintf(stderr, "Could not alloc or mlock buffers: %d (%s)\n", + errno, strerror(errno)); + exit(-1); + } + + if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, + pcd, pcv, NULL, NULL) != 0 ) + { + fprintf(stderr, "Error getting perf counter: %d (%s)\n", errno, strerror(errno)); return 1; } - pcd = malloc(sizeof(*pcd) * num); + munlock(pcd, sizeof(*pcd) * num_desc); + munlock(pcv, sizeof(*pcv) * num_val); - if ( mlock(pcd, sizeof(*pcd) * num) != 0 ) - { - fprintf(stderr, "Could not mlock descriptor buffer: %d (%s)\n", - errno, strerror(errno)); - exit(-1); - } - - if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, pcd) <= 0 ) - { - fprintf(stderr, "Error getting perf counter description: %d (%s)\n", - errno, strerror(errno)); - return 1; - } - - munlock(pcd, sizeof(*pcd) * num); - - for ( i = 0; i < num; i++ ) + val = pcv; + for ( i = 0; i < num_desc; i++ ) { printf ("%-35s ", pcd[i].name); sum = 0; for ( j = 0; j < pcd[i].nr_vals; j++ ) - sum += pcd[i].vals[j]; + sum += val[j]; printf ("T=%10u ", (unsigned int)sum); if ( full || (pcd[i].nr_vals <= 4) ) for ( j = 0; j < pcd[i].nr_vals; j++ ) - printf(" %10u", (unsigned int)pcd[i].vals[j]); + printf(" %10u", (unsigned int)val[j]); printf("\n"); + val += pcd[i].nr_vals; } return 0; diff -r f353f9939773 -r 2c06898a1e84 xen/common/perfc.c --- a/xen/common/perfc.c Mon Aug 07 06:37:21 2006 +0200 +++ b/xen/common/perfc.c Mon Aug 07 09:08:45 2006 +0200 @@ -16,39 +16,51 @@ #undef PERFSTATUS #undef PERFSTATUS_CPU #undef PERFSTATUS_ARRAY -#define PERFCOUNTER( var, name ) { name, TYPE_SINGLE, 0 }, -#define PERFCOUNTER_CPU( var, name ) { name, TYPE_CPU, 0 }, -#define PERFCOUNTER_ARRAY( var, name, size ) { name, TYPE_ARRAY, size }, -#define PERFSTATUS( var, name ) { name, TYPE_S_SINGLE, 0 }, -#define PERFSTATUS_CPU( var, name ) { name, TYPE_S_CPU, 0 }, -#define PERFSTATUS_ARRAY( var, name, size ) { name, TYPE_S_ARRAY, size }, -static struct { - char *name; - enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY, - TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY - } type; - int nr_elements; -} perfc_info[] = { +#define PERFCOUNTER( var, name ) TYPE_SINGLE, +#define PERFCOUNTER_CPU( var, name ) TYPE_CPU, +#define PERFCOUNTER_ARRAY( var, name, size ) TYPE_ARRAY, +#define PERFSTATUS( var, name ) TYPE_S_SINGLE, +#define PERFSTATUS_CPU( var, name ) TYPE_S_CPU, +#define PERFSTATUS_ARRAY( var, name, size ) TYPE_S_ARRAY, +static const enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY, + TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY +} perfc_type[] = { #include }; -#define NR_PERFCTRS (sizeof(perfc_info) / sizeof(perfc_info[0])) - -struct perfcounter perfcounters; +#undef PERFCOUNTER +#undef PERFCOUNTER_CPU +#undef PERFCOUNTER_ARRAY +#undef PERFSTATUS +#undef PERFSTATUS_CPU +#undef PERFSTATUS_ARRAY +#define PERFCOUNTER( var, name ) { name, 1 }, +#define PERFCOUNTER_CPU( var, name ) { name, NR_CPUS }, +#define PERFCOUNTER_ARRAY( var, name, size ) { name, size }, +#define PERFSTATUS( var, name ) { name, 1 }, +#define PERFSTATUS_CPU( var, name ) { name, NR_CPUS }, +#define PERFSTATUS_ARRAY( var, name, size ) { name, size }, +static const dom0_perfc_desc_t perfc_d[] = { +#include +}; + +#define NR_PERFCTRS (sizeof(perfc_d) / sizeof(perfc_d[0])) + +union perfcounters_union perfcounters; void perfc_printall(unsigned char key) { unsigned int i, j, sum; s_time_t now = NOW(); - atomic_t *counters = (atomic_t *)&perfcounters; + atomic_t *counters = perfcounters.a; printk("Xen performance counters SHOW (now = 0x%08X:%08X)\n", (u32)(now>>32), (u32)now); for ( i = 0; i < NR_PERFCTRS; i++ ) { - printk("%-32s ", perfc_info[i].name); - switch ( perfc_info[i].type ) + printk("%-32s ", perfc_d[i].name); + switch ( perfc_type[i] ) { case TYPE_SINGLE: case TYPE_S_SINGLE: @@ -70,13 +82,13 @@ void perfc_printall(unsigned char key) break; case TYPE_ARRAY: case TYPE_S_ARRAY: - for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ ) + for ( j = sum = 0; j < perfc_d[i].nr_vals; j++ ) sum += atomic_read(&counters[j]); printk("TOTAL[%10u]", sum); #ifdef PERF_ARRAYS if (sum) { - for ( j = 0; j < perfc_info[i].nr_elements; j++ ) + for ( j = 0; j < perfc_d[i].nr_vals; j++ ) { if ( (j % 4) == 0 ) printk("\n "); @@ -97,7 +109,7 @@ void perfc_reset(unsigned char key) { unsigned int i, j; s_time_t now = NOW(); - atomic_t *counters = (atomic_t *)&perfcounters; + atomic_t *counters = perfcounters.a; if ( key != '\0' ) printk("Xen performance counters RESET (now = 0x%08X:%08X)\n", @@ -107,7 +119,7 @@ void perfc_reset(unsigned char key) for ( i = 0; i < NR_PERFCTRS; i++ ) { - switch ( perfc_info[i].type ) + switch ( perfc_type[i] ) { case TYPE_SINGLE: atomic_set(&counters[0],0); @@ -121,10 +133,10 @@ void perfc_reset(unsigned char key) counters += NR_CPUS; break; case TYPE_ARRAY: - for ( j = 0; j < perfc_info[i].nr_elements; j++ ) + for ( j = 0; j < perfc_d[i].nr_vals; j++ ) atomic_set(&counters[j],0); case TYPE_S_ARRAY: - counters += perfc_info[i].nr_elements; + counters += perfc_d[i].nr_vals; break; } } @@ -132,75 +144,16 @@ void perfc_reset(unsigned char key) arch_perfc_reset (); } -static dom0_perfc_desc_t perfc_d[NR_PERFCTRS]; -static int perfc_init = 0; -static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc) -{ - unsigned int i, j; - atomic_t *counters = (atomic_t *)&perfcounters; - - if ( guest_handle_is_null(desc) ) - return 0; - - /* We only copy the name and array-size information once. */ - if ( !perfc_init ) - { - for ( i = 0; i < NR_PERFCTRS; i++ ) - { - strncpy(perfc_d[i].name, perfc_info[i].name, - sizeof(perfc_d[i].name)); - perfc_d[i].name[sizeof(perfc_d[i].name)-1] = '\0'; - - switch ( perfc_info[i].type ) - { - case TYPE_SINGLE: - case TYPE_S_SINGLE: - perfc_d[i].nr_vals = 1; - break; - case TYPE_CPU: - case TYPE_S_CPU: - perfc_d[i].nr_vals = num_online_cpus(); - break; - case TYPE_ARRAY: - case TYPE_S_ARRAY: - perfc_d[i].nr_vals = perfc_info[i].nr_elements; - break; - } - - if ( perfc_d[i].nr_vals > ARRAY_SIZE(perfc_d[i].vals) ) - perfc_d[i].nr_vals = ARRAY_SIZE(perfc_d[i].vals); - } - - perfc_init = 1; - } - - /* We gather the counts together every time. */ - for ( i = 0; i < NR_PERFCTRS; i++ ) - { - switch ( perfc_info[i].type ) - { - case TYPE_SINGLE: - case TYPE_S_SINGLE: - perfc_d[i].vals[0] = atomic_read(&counters[0]); - counters += 1; - break; - case TYPE_CPU: - case TYPE_S_CPU: - for ( j = 0; j < perfc_d[i].nr_vals; j++ ) - perfc_d[i].vals[j] = atomic_read(&counters[j]); - counters += NR_CPUS; - break; - case TYPE_ARRAY: - case TYPE_S_ARRAY: - for ( j = 0; j < perfc_d[i].nr_vals; j++ ) - perfc_d[i].vals[j] = atomic_read(&counters[j]); - counters += perfc_info[i].nr_elements; - break; - } - } - - return (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS) ? - -EFAULT : 0); +static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc, + XEN_GUEST_HANDLE(dom0_perfc_val_t) val) +{ + if ( !guest_handle_is_null(desc) ) + if (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS)) + return -EFAULT; + if ( !guest_handle_is_null(val) ) + if (copy_to_guest(val, (uint32_t *)perfcounters.u, NR_PERFC_VALS)) + return -EFAULT; + return 0; } /* Dom0 control of perf counters */ @@ -210,20 +163,18 @@ int perfc_control(dom0_perfccontrol_t *p u32 op = pc->op; int rc; - pc->nr_counters = NR_PERFCTRS; - spin_lock(&lock); switch ( op ) { case DOM0_PERFCCONTROL_OP_RESET: - perfc_copy_info(pc->desc); + perfc_copy_info(pc->desc, pc->val); perfc_reset(0); rc = 0; break; case DOM0_PERFCCONTROL_OP_QUERY: - perfc_copy_info(pc->desc); + perfc_copy_info(pc->desc, pc->val); rc = 0; break; @@ -233,6 +184,9 @@ int perfc_control(dom0_perfccontrol_t *p } spin_unlock(&lock); + + pc->nr_counters = NR_PERFCTRS; + pc->nr_vals = NR_PERFC_VALS; return rc; } diff -r f353f9939773 -r 2c06898a1e84 xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Mon Aug 07 06:37:21 2006 +0200 +++ b/xen/include/public/dom0_ops.h Mon Aug 07 09:08:45 2006 +0200 @@ -361,17 +361,20 @@ struct dom0_perfc_desc { struct dom0_perfc_desc { char name[80]; /* name of perf counter */ uint32_t nr_vals; /* number of values for this counter */ - uint32_t vals[64]; /* array of values */ }; typedef struct dom0_perfc_desc dom0_perfc_desc_t; DEFINE_XEN_GUEST_HANDLE(dom0_perfc_desc_t); +typedef uint32_t dom0_perfc_val_t; +DEFINE_XEN_GUEST_HANDLE(dom0_perfc_val_t); struct dom0_perfccontrol { /* IN variables. */ uint32_t op; /* DOM0_PERFCCONTROL_OP_??? */ /* OUT variables. */ - uint32_t nr_counters; /* number of counters */ + uint32_t nr_counters; /* number of counters description */ + uint32_t nr_vals; /* number of values */ XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc; /* counter information (or NULL) */ + XEN_GUEST_HANDLE(dom0_perfc_val_t) val; /* counter values (or NULL) */ }; typedef struct dom0_perfccontrol dom0_perfccontrol_t; DEFINE_XEN_GUEST_HANDLE(dom0_perfccontrol_t); diff -r f353f9939773 -r 2c06898a1e84 xen/include/xen/perfc.h --- a/xen/include/xen/perfc.h Mon Aug 07 06:37:21 2006 +0200 +++ b/xen/include/xen/perfc.h Mon Aug 07 09:08:45 2006 +0200 @@ -51,35 +51,40 @@ struct perfcounter { #include }; -extern struct perfcounter perfcounters; +#define NR_PERFC_VALS (sizeof(struct perfcounter)/sizeof(atomic_t)) +extern union perfcounters_union { + struct perfcounter s; + atomic_t a[NR_PERFC_VALS]; + uint32_t u[NR_PERFC_VALS]; +} perfcounters; -#define perfc_value(x) atomic_read(&perfcounters.x[0]) -#define perfc_valuec(x) atomic_read(&perfcounters.x[smp_processor_id()]) +#define perfc_value(x) atomic_read(&perfcounters.s.x[0]) +#define perfc_valuec(x) atomic_read(&perfcounters.s.x[smp_processor_id()]) #define perfc_valuea(x,y) \ - ( (y) < (sizeof(perfcounters.x) / sizeof(*perfcounters.x)) ? \ - atomic_read(&perfcounters.x[y]) : 0 ) -#define perfc_set(x,v) atomic_set(&perfcounters.x[0], v) -#define perfc_setc(x,v) atomic_set(&perfcounters.x[smp_processor_id()], v) -#define perfc_seta(x,y,v) \ - do { \ - if ( (y) < (sizeof(perfcounters.x) / sizeof(*perfcounters.x)) ) \ - atomic_set(&perfcounters.x[y], v); \ + ( (y) < (sizeof(perfcounters.s.x) / sizeof(*perfcounters.s.x)) ? \ + atomic_read(&perfcounters.s.x[y]) : 0 ) +#define perfc_set(x,v) atomic_set(&perfcounters.s.x[0], v) +#define perfc_setc(x,v) atomic_set(&perfcounters.s.x[smp_processor_id()], v) +#define perfc_seta(x,y,v) \ + do { \ + if ( (y) < (sizeof(perfcounters.s.x) / sizeof(*perfcounters.s.x)) ) \ + atomic_set(&perfcounters.s.x[y], v); \ } while ( 0 ) -#define perfc_incr(x) atomic_inc(&perfcounters.x[0]) -#define perfc_decr(x) atomic_dec(&perfcounters.x[0]) -#define perfc_incrc(x) atomic_inc(&perfcounters.x[smp_processor_id()]) -#define perfc_decrc(x) atomic_dec(&perfcounters.x[smp_processor_id()]) -#define perfc_incra(x,y) \ - do { \ - if ( (y) < (sizeof(perfcounters.x) / sizeof(*perfcounters.x)) ) \ - atomic_inc(&perfcounters.x[y]); \ +#define perfc_incr(x) atomic_inc(&perfcounters.s.x[0]) +#define perfc_decr(x) atomic_dec(&perfcounters.s.x[0]) +#define perfc_incrc(x) atomic_inc(&perfcounters.s.x[smp_processor_id()]) +#define perfc_decrc(x) atomic_dec(&perfcounters.s.x[smp_processor_id()]) +#define perfc_incra(x,y) \ + do { \ + if ( (y) < (sizeof(perfcounters.s.x) / sizeof(*perfcounters.s.x)) ) \ + atomic_inc(&perfcounters.s.x[y]); \ } while ( 0 ) -#define perfc_add(x,y) atomic_add((y), &perfcounters.x[0]) -#define perfc_addc(x,y) atomic_add((y), &perfcounters.x[smp_processor_id()]) -#define perfc_adda(x,y,z) \ - do { \ - if ( (y) < (sizeof(perfcounters.x) / sizeof(*perfcounters.x)) ) \ - atomic_add((z), &perfcounters.x[y]); \ +#define perfc_add(x,y) atomic_add((y), &perfcounters.s.x[0]) +#define perfc_addc(x,y) atomic_add((y), &perfcounters.s.x[smp_processor_id()]) +#define perfc_adda(x,y,z) \ + do { \ + if ( (y) < (sizeof(perfcounters.s.x) / sizeof(*perfcounters.s.x)) ) \ + atomic_add((z), &perfcounters.s.x[y]); \ } while ( 0 ) /*