aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/perfc.c
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-12-01 13:25:22 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-12-01 13:25:22 +0000
commitae51438ac62eb5db9d1815b52bbe3e2aef551199 (patch)
tree6199dd18917ee72e9a87c315a5b5eb0cbd571e1f /xen/common/perfc.c
parent3752c7fe16d51e7065d8078acbd91bd3f6fe6196 (diff)
downloadxen-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.c111
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;
+}