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 | |
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.
-rw-r--r-- | .rootkeys | 1 | ||||
-rw-r--r-- | BitKeeper/etc/ignore | 2 | ||||
-rw-r--r-- | tools/libxc/xc.h | 9 | ||||
-rw-r--r-- | tools/libxc/xc_misc.c | 18 | ||||
-rw-r--r-- | tools/misc/Makefile | 16 | ||||
-rw-r--r-- | tools/misc/xenperf.c | 104 | ||||
-rw-r--r-- | xen/arch/x86/memory.c | 6 | ||||
-rw-r--r-- | xen/common/dom0_ops.c | 10 | ||||
-rw-r--r-- | xen/common/perfc.c | 111 | ||||
-rw-r--r-- | xen/include/public/dom0_ops.h | 20 |
10 files changed, 278 insertions, 19 deletions
@@ -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 */ |