aboutsummaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--.rootkeys1
-rw-r--r--BitKeeper/etc/ignore2
-rw-r--r--tools/libxc/xc.h9
-rw-r--r--tools/libxc/xc_misc.c18
-rw-r--r--tools/misc/Makefile16
-rw-r--r--tools/misc/xenperf.c104
-rw-r--r--xen/arch/x86/memory.c6
-rw-r--r--xen/common/dom0_ops.c10
-rw-r--r--xen/common/perfc.c111
-rw-r--r--xen/include/public/dom0_ops.h20
10 files changed, 278 insertions, 19 deletions
diff --git a/.rootkeys b/.rootkeys
index 1691f867c4..31497b58ac 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -380,6 +380,7 @@
3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README
405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons
40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend
+41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/misc/xenperf.c
4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops
40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
diff --git a/BitKeeper/etc/ignore b/BitKeeper/etc/ignore
index ec7c4e8ee6..6767868bd3 100644
--- a/BitKeeper/etc/ignore
+++ b/BitKeeper/etc/ignore
@@ -58,7 +58,7 @@ tools/balloon/balloon
tools/check/.*
tools/libxc/xen/*
tools/misc/miniterm/miniterm
-tools/misc/xen_cpuperf
+tools/misc/xenperf
tools/vnet/gc
tools/vnet/gc*/*
tools/vnet/vnet-module/.tmp_versions/*
diff --git a/tools/libxc/xc.h b/tools/libxc/xc.h
index 7778b71673..18665e9178 100644
--- a/tools/libxc/xc.h
+++ b/tools/libxc/xc.h
@@ -178,14 +178,19 @@ int xc_domain_setinitialmem(int xc_handle,
unsigned int initial_memkb);
int xc_domain_setmaxmem(int xc_handle,
- u32 domid,
- unsigned int max_memkb);
+ u32 domid,
+ unsigned int max_memkb);
int xc_domain_setvmassist(int xc_handle,
u32 domid,
unsigned int cmd,
unsigned int type);
+typedef dom0_perfc_desc_t xc_perfc_desc_t;
+/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
+int xc_perfc_control(int xc_handle,
+ u32 op,
+ xc_perfc_desc_t *desc);
void *xc_map_foreign_range(int xc_handle, u32 dom,
int size, int prot,
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index e8ea18c5ff..0efd1f1972 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -74,10 +74,26 @@ int xc_sched_id(int xc_handle,
op.cmd = DOM0_SCHED_ID;
op.interface_version = DOM0_INTERFACE_VERSION;
- if((ret = do_dom0_op(xc_handle, &op))) return ret;
+ if ( (ret = do_dom0_op(xc_handle, &op)) != 0 )
+ return ret;
*sched_id = op.u.sched_id.sched_id;
return 0;
}
+int xc_perfc_control(int xc_handle,
+ u32 op,
+ xc_perfc_desc_t *desc)
+{
+ int rc;
+ dom0_op_t dop;
+
+ dop.cmd = DOM0_PERFCCONTROL;
+ dop.u.perfccontrol.op = op;
+ dop.u.perfccontrol.desc = desc;
+
+ rc = do_dom0_op(xc_handle, &dop);
+
+ return (rc == 0) ? dop.u.perfccontrol.nr_counters : rc;
+}
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index 760348b0b4..7c20e8d1b0 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -3,22 +3,18 @@ XEN_ROOT=../..
include $(XEN_ROOT)/tools/Make.defs
CC = gcc
-CFLAGS = -Wall -O3
+CFLAGS = -Wall -Werror -O3
INCLUDES += -I $(XEN_XC)
INCLUDES += -I $(XEN_LIBXC)
-INCLUDES += -I $(XEN_LIBXUTIL)
-
-CFLAGS += $(INCLUDES)
+CFLAGS += $(INCLUDES)
HDRS = $(wildcard *.h)
-SRCS = $(wildcard *.c)
-OBJS = $(patsubst %.c,%.o,$(SRCS))
-TARGETS =
+TARGETS = xenperf
INSTALL_BIN = $(TARGETS) xencons
-INSTALL_SBIN = netfix xm xend xensv
+INSTALL_SBIN = netfix xm xend xensv xenperf
all: $(TARGETS)
$(MAKE) -C miniterm
@@ -32,7 +28,7 @@ install: all
clean:
$(RM) *.o $(TARGETS) *~
- $(MAKE) -C miniterm clean
+ $(MAKE) -C miniterm clean
%: %.c $(HDRS) Makefile
- $(CC) $(CFLAGS) -o $@ $<
+ $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxc -L$(XEN_LIBXUTIL) -lxutil
diff --git a/tools/misc/xenperf.c b/tools/misc/xenperf.c
new file mode 100644
index 0000000000..d2846224b1
--- /dev/null
+++ b/tools/misc/xenperf.c
@@ -0,0 +1,104 @@
+/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
+ ****************************************************************************
+ * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: xenperf.c
+ * Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
+ * Date: Nov 2004
+ *
+ * Description:
+ */
+
+
+#include <xc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ int i, j, xc_handle;
+ xc_perfc_desc_t *pcd;
+ unsigned int num, sum, reset = 0;
+
+ if ( argc > 1 )
+ {
+ char *p = argv[1];
+ if ( (*p++ == '-') && (*p == 'r') )
+ reset = 1;
+ else
+ {
+ printf("%s: [-r]\n", argv[0]);
+ printf("no args: print xen performance counters\n");
+ printf(" -r : reset xen performance counters\n");
+ return 0;
+ }
+ }
+
+ if ( (xc_handle = xc_interface_open()) == -1 )
+ {
+ fprintf(stderr, "Error opening xc interface: %d (%s)\n",
+ errno, strerror(errno));
+ return 1;
+ }
+
+ if ( reset )
+ {
+ if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_RESET,
+ NULL) < 0 )
+ {
+ fprintf(stderr, "Error reseting performance counters: %d (%s)\n",
+ errno, strerror(errno));
+ return 1;
+ }
+
+ return 0;
+ }
+
+
+ if ( (num = xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
+ NULL)) < 0 )
+ {
+ fprintf(stderr, "Error getting number of perf counters: %d (%s)\n",
+ errno, strerror(errno));
+ return 1;
+ }
+
+ pcd = malloc(sizeof(*pcd) * num);
+
+ 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++ )
+ {
+ printf ("%-35s ", pcd[i].name);
+
+ sum = 0;
+ for ( j = 0; j < pcd[i].nr_vals; j++ )
+ sum += pcd[i].vals[j];
+ printf ("T=%10u ", (unsigned int)sum);
+
+ for ( j = 0; j < pcd[i].nr_vals; j++ )
+ printf(" %10u", (unsigned int)pcd[i].vals[j]);
+
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c
index 5734f45ba9..7cab825a4d 100644
--- a/xen/arch/x86/memory.c
+++ b/xen/arch/x86/memory.c
@@ -1299,9 +1299,6 @@ int do_mmu_update(
u32 type_info;
domid_t domid;
- perfc_incrc(calls_to_mmu_update);
- perfc_addc(num_page_updates, count);
-
cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
/*
@@ -1331,6 +1328,9 @@ int do_mmu_update(
}
}
+ perfc_incrc(calls_to_mmu_update);
+ perfc_addc(num_page_updates, count);
+
if ( unlikely(!array_access_ok(VERIFY_READ, ureqs, count, sizeof(req))) )
{
rc = -EFAULT;
diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c
index 812814068b..5622ae174e 100644
--- a/xen/common/dom0_ops.c
+++ b/xen/common/dom0_ops.c
@@ -651,6 +651,16 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
}
break;
+#ifdef PERF_COUNTERS
+ case DOM0_PERFCCONTROL:
+ {
+ extern int perfc_control(dom0_perfccontrol_t *);
+ ret = perfc_control(&op->u.perfccontrol);
+ copy_to_user(u_dom0_op, op, sizeof(*op));
+ }
+ break;
+#endif
+
default:
ret = arch_do_dom0_op(op,u_dom0_op);
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;
+}
diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h
index f8c7bab6d3..9673c88678 100644
--- a/xen/include/public/dom0_ops.h
+++ b/xen/include/public/dom0_ops.h
@@ -386,6 +386,25 @@ typedef struct {
u32 __pad1;
} PACKED dom0_read_memtype_t; /* 32 bytes */
+/* Interface for controlling Xen software performance counters. */
+#define DOM0_PERFCCONTROL 34
+/* Sub-operations: */
+#define DOM0_PERFCCONTROL_OP_RESET 1 /* Reset all counters to zero. */
+#define DOM0_PERFCCONTROL_OP_QUERY 2 /* Get perfctr information. */
+typedef struct {
+ u8 name[80]; /* 0: name of perf counter */
+ u32 nr_vals; /* 80: number of values for this counter */
+ u32 vals[64]; /* 84: array of values */
+} PACKED dom0_perfc_desc_t; /* 340 bytes */
+typedef struct {
+ /* IN variables. */
+ u32 op; /* 0: DOM0_PERFCCONTROL_OP_??? */
+ /* OUT variables. */
+ u32 nr_counters; /* 4: number of counters */
+ dom0_perfc_desc_t *desc; /* 8: counter information (or NULL) */
+ MEMORY_PADDING;
+} PACKED dom0_perfccontrol_t; /* 16 bytes */
+
typedef struct {
u32 cmd; /* 0 */
u32 interface_version; /* 4 */ /* DOM0_INTERFACE_VERSION */
@@ -419,6 +438,7 @@ typedef struct {
dom0_add_memtype_t add_memtype;
dom0_del_memtype_t del_memtype;
dom0_read_memtype_t read_memtype;
+ dom0_perfccontrol_t perfccontrol;
} PACKED u;
} PACKED dom0_op_t; /* 80 bytes */