diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-12-01 13:25:22 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-12-01 13:25:22 +0000 |
commit | ae51438ac62eb5db9d1815b52bbe3e2aef551199 (patch) | |
tree | 6199dd18917ee72e9a87c315a5b5eb0cbd571e1f /xen/common/perfc.c | |
parent | 3752c7fe16d51e7065d8078acbd91bd3f6fe6196 (diff) | |
download | xen-ae51438ac62eb5db9d1815b52bbe3e2aef551199.tar.gz xen-ae51438ac62eb5db9d1815b52bbe3e2aef551199.tar.bz2 xen-ae51438ac62eb5db9d1815b52bbe3e2aef551199.zip |
bitkeeper revision 1.1159.187.48 (41adc6420WlNaaoUkvfgNxl44rpYYg)
Export Xen s/w perfctrs to DOM0 via new 'xenperf' utility.
Diffstat (limited to 'xen/common/perfc.c')
-rw-r--r-- | xen/common/perfc.c | 111 |
1 files changed, 109 insertions, 2 deletions
diff --git a/xen/common/perfc.c b/xen/common/perfc.c index 3a05c2e071..d5384c4af5 100644 --- a/xen/common/perfc.c +++ b/xen/common/perfc.c @@ -4,6 +4,8 @@ #include <xen/time.h> #include <xen/perfc.h> #include <xen/keyhandler.h> +#include <public/dom0_ops.h> +#include <asm/uaccess.h> #undef PERFCOUNTER #undef PERFCOUNTER_CPU @@ -79,8 +81,9 @@ void perfc_reset(unsigned char key) s_time_t now = NOW(); atomic_t *counters = (atomic_t *)&perfcounters; - printk("Xen performance counters RESET (now = 0x%08X:%08X)\n", - (u32)(now>>32), (u32)now); + if ( key != '\0' ) + printk("Xen performance counters RESET (now = 0x%08X:%08X)\n", + (u32)(now>>32), (u32)now); /* leave STATUS counters alone -- don't reset */ @@ -109,3 +112,107 @@ void perfc_reset(unsigned char key) } } +static dom0_perfc_desc_t perfc_d[NR_PERFCTRS]; +static int perfc_init = 0; +static int perfc_copy_info(dom0_perfc_desc_t *desc) +{ + unsigned int i, j; + atomic_t *counters = (atomic_t *)&perfcounters; + + if ( desc == NULL ) + 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 = smp_num_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_user(desc, perfc_d, NR_PERFCTRS * sizeof(*desc)) ? + -EFAULT : 0); +} + +/* Dom0 control of perf counters */ +int perfc_control(dom0_perfccontrol_t *pc) +{ + static spinlock_t lock = SPIN_LOCK_UNLOCKED; + 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_reset(0); + rc = 0; + break; + + case DOM0_PERFCCONTROL_OP_QUERY: + perfc_copy_info(pc->desc); + rc = 0; + break; + + default: + rc = -EINVAL; + break; + } + + spin_unlock(&lock); + + return rc; +} |