# HG changeset patch # User gingold@virtu10 # Node ID 6286aede6482ff468795ca9d9c58c94fae2dd758 # Parent 90fe9eed7f98394743b5499d28d92bf8f71ffa38 Change DOM0_PERFCCONTROL: remove array limit. Descriptors and values are passed by two distinct buffers. Signed-off-by: Tristan Gingold diff -r 90fe9eed7f98 -r 6286aede6482 tools/libxc/xc_misc.c --- a/tools/libxc/xc_misc.c Fri Aug 04 11:23:42 2006 +0200 +++ b/tools/libxc/xc_misc.c Fri Aug 04 11:32:16 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 90fe9eed7f98 -r 6286aede6482 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Fri Aug 04 11:23:42 2006 +0200 +++ b/tools/libxc/xenctrl.h Fri Aug 04 11:32:16 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 90fe9eed7f98 -r 6286aede6482 tools/misc/xenperf.c --- a/tools/misc/xenperf.c Fri Aug 04 11:23:42 2006 +0200 +++ b/tools/misc/xenperf.c Fri Aug 04 11:32:16 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 90fe9eed7f98 -r 6286aede6482 xen/common/perfc.c --- a/xen/common/perfc.c Fri Aug 04 11:23:42 2006 +0200 +++ b/xen/common/perfc.c Fri Aug 04 11:32:16 2006 +0200 @@ -136,10 +136,14 @@ void perfc_reset(unsigned char key) } static dom0_perfc_desc_t perfc_d[NR_PERFCTRS]; +static dom0_perfc_val_t *perfc_vals; +static int perfc_nbr_vals; static int perfc_init = 0; -static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc) +static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc, + XEN_GUEST_HANDLE(dom0_perfc_val_t) val) { unsigned int i, j; + unsigned int v = 0; atomic_t *counters = (atomic_t *)&perfcounters; if ( guest_handle_is_null(desc) ) @@ -169,13 +173,13 @@ static int perfc_copy_info(XEN_GUEST_HAN 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_nbr_vals += perfc_d[i].nr_vals; + } + perfc_vals = xmalloc_array(dom0_perfc_val_t, perfc_nbr_vals); perfc_init = 1; } + if (perfc_vals == NULL) + return -ENOMEM; /* We gather the counts together every time. */ for ( i = 0; i < NR_PERFCTRS; i++ ) @@ -184,26 +188,30 @@ static int perfc_copy_info(XEN_GUEST_HAN { case TYPE_SINGLE: case TYPE_S_SINGLE: - perfc_d[i].vals[0] = atomic_read(&counters[0]); + perfc_vals[v++] = 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]); + perfc_vals[v++] = 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]); + perfc_vals[v++] = 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); + BUG_ON(v != perfc_nbr_vals); + + if (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS)) + return -EFAULT; + if (copy_to_guest(val, perfc_vals, perfc_nbr_vals)) + return -EFAULT; + return 0; } /* Dom0 control of perf counters */ @@ -213,20 +221,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; @@ -236,6 +242,9 @@ int perfc_control(dom0_perfccontrol_t *p } spin_unlock(&lock); + + pc->nr_counters = NR_PERFCTRS; + pc->nr_vals = perfc_nbr_vals; return rc; } diff -r 90fe9eed7f98 -r 6286aede6482 xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Fri Aug 04 11:23:42 2006 +0200 +++ b/xen/include/public/dom0_ops.h Fri Aug 04 11:32:16 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);