diff options
-rw-r--r-- | tools/libxc/Makefile | 1 | ||||
-rw-r--r-- | tools/libxc/xc_tbuf.c | 51 | ||||
-rw-r--r-- | tools/libxc/xenctrl.h | 43 | ||||
-rw-r--r-- | tools/xentrace/Makefile | 2 | ||||
-rw-r--r-- | tools/xentrace/formats | 26 | ||||
-rw-r--r-- | tools/xentrace/setsize.c | 36 | ||||
-rw-r--r-- | tools/xentrace/tbctl.c | 26 | ||||
-rw-r--r-- | xen/Rules.mk | 2 | ||||
-rw-r--r-- | xen/common/trace.c | 124 | ||||
-rw-r--r-- | xen/include/public/dom0_ops.h | 3 |
10 files changed, 281 insertions, 33 deletions
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 9c4b705641..b1d91d157d 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -23,6 +23,7 @@ SRCS += xc_misc.c SRCS += xc_physdev.c SRCS += xc_private.c SRCS += xc_sedf.c +SRCS += xc_tbuf.c BUILD_SRCS += xc_linux_build.c BUILD_SRCS += xc_load_bin.c BUILD_SRCS += xc_load_elf.c diff --git a/tools/libxc/xc_tbuf.c b/tools/libxc/xc_tbuf.c new file mode 100644 index 0000000000..b47cde2867 --- /dev/null +++ b/tools/libxc/xc_tbuf.c @@ -0,0 +1,51 @@ +/****************************************************************************** + * xc_tbuf.c + * + * API for manipulating and accessing trace buffer parameters + * + * Copyright (c) 2005, Rob Gardner + */ + +#include "xc_private.h" + +int xc_tbuf_enable(int xc_handle, int enable) +{ + dom0_op_t op; + + op.cmd = DOM0_TBUFCONTROL; + op.interface_version = DOM0_INTERFACE_VERSION; + if (enable) + op.u.tbufcontrol.op = DOM0_TBUF_ENABLE; + else + op.u.tbufcontrol.op = DOM0_TBUF_DISABLE; + + return xc_dom0_op(xc_handle, &op); +} + +int xc_tbuf_set_size(int xc_handle, uint32_t size) +{ + dom0_op_t op; + + op.cmd = DOM0_TBUFCONTROL; + op.interface_version = DOM0_INTERFACE_VERSION; + op.u.tbufcontrol.op = DOM0_TBUF_SET_SIZE; + op.u.tbufcontrol.size = size; + + return xc_dom0_op(xc_handle, &op); +} + +int xc_tbuf_get_size(int xc_handle, uint32_t *size) +{ + int rc; + dom0_op_t op; + + op.cmd = DOM0_TBUFCONTROL; + op.interface_version = DOM0_INTERFACE_VERSION; + op.u.tbufcontrol.op = DOM0_TBUF_GET_INFO; + + rc = xc_dom0_op(xc_handle, &op); + if (rc == 0) + *size = op.u.tbufcontrol.size; + return rc; +} + diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index ffbe4fdfff..42ce3097be 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -149,7 +149,7 @@ int xc_domain_dumpcore(int xc_handle, const char *corename); /* - * This function sets the maximum number vcpus that a domian may create. + * This function sets the maximum number of vcpus that a domain may create. * * @parm xc_handle a handle to an open hypervisor interface. * @parm domid the domain id in which vcpus are to be created. @@ -490,6 +490,47 @@ int xc_gnttab_dump_table(int xc_handle, /* Get current total pages allocated to a domain. */ long xc_get_tot_pages(int xc_handle, uint32_t domid); + +/* + * Trace Buffer Operations + */ + +/** + * This function enables or disables tracing. Trace buffer memory must + * be already allocated by setting the size to a non-zero value, otherwise + * tracing cannot be enabled. + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm enable the desired action, 1 for enable, 0 for disable + * @return 0 on success, -1 on failure. + */ +int xc_tbuf_enable(int xc_handle, int enable); + +/** + * This function sets the size of the trace buffers. Setting it to zero + * deallocates the memory used for trace buffers, and setting it to a + * non-zero value specifies the number of pages per cpu to allocate. + * To change the size of an existing allocation, you must first deallocate + * it then reallocate it. No change in size is allowed when tracing is + * enabled; A disable call must be made first. + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm size the size in pages per cpu for the trace buffers + * @return 0 on success, -1 on failure. + */ +int xc_tbuf_set_size(int xc_handle, uint32_t size); + +/** + * This function retrieves the current size of the trace buffers. + * Note that the size returned is in terms of bytes, not pages. + + * @parm xc_handle a handle to an open hypervisor interface + * @parm size will contain the size in bytes for the trace buffers + * @return 0 on success, -1 on failure. + */ +int xc_tbuf_get_size(int xc_handle, uint32_t *size); + + /* Execute a privileged dom0 operation. */ int xc_dom0_op(int xc_handle, dom0_op_t *op); diff --git a/tools/xentrace/Makefile b/tools/xentrace/Makefile index b6ae508d85..5c3a77be83 100644 --- a/tools/xentrace/Makefile +++ b/tools/xentrace/Makefile @@ -14,7 +14,7 @@ CFLAGS += -I $(XEN_LIBXC) HDRS = $(wildcard *.h) OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) -BIN = xentrace +BIN = xentrace tbctl setsize SCRIPTS = xentrace_format MAN1 = $(wildcard *.1) MAN8 = $(wildcard *.8) diff --git a/tools/xentrace/formats b/tools/xentrace/formats index 78954b9543..818eef1c60 100644 --- a/tools/xentrace/formats +++ b/tools/xentrace/formats @@ -1,16 +1,16 @@ -0x00020001 CPU%(cpu)d %(tsc)d sched_add_domain [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] -0x00020002 CPU%(cpu)d %(tsc)d sched_rem_domain [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] -0x00020003 CPU%(cpu)d %(tsc)d domain_sleep [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] -0x00020004 CPU%(cpu)d %(tsc)d domain_wake [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] -0x00020005 CPU%(cpu)d %(tsc)d do_yield [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] -0x00020006 CPU%(cpu)d %(tsc)d do_block [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] -0x00020007 CPU%(cpu)d %(tsc)d domain_shutdown [ domid = 0x%(1)08x, edomid = 0x%(2)08x, reason = 0x%(3)08x ] -0x00020008 CPU%(cpu)d %(tsc)d sched_ctl -0x00020009 CPU%(cpu)d %(tsc)d sched_adjdom [ domid = 0x%(1)08x ] -0x0002000a CPU%(cpu)d %(tsc)d __enter_scheduler [ prev<domid:edomid> = 0x%(1)08x : 0x%(2)08x, next<domid:edomid> = 0x%(3)08x : 0x%(4)08x ] -0x0002000B CPU%(cpu)d %(tsc)d s_timer_fn -0x0002000c CPU%(cpu)d %(tsc)d t_timer_fn -0x0002000d CPU%(cpu)d %(tsc)d dom_timer_fn +0x0002f001 CPU%(cpu)d %(tsc)d sched_add_domain [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] +0x0002f002 CPU%(cpu)d %(tsc)d sched_rem_domain [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] +0x0002f003 CPU%(cpu)d %(tsc)d domain_sleep [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] +0x0002f004 CPU%(cpu)d %(tsc)d domain_wake [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] +0x0002f005 CPU%(cpu)d %(tsc)d do_yield [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] +0x0002f006 CPU%(cpu)d %(tsc)d do_block [ domid = 0x%(1)08x, edomid = 0x%(2)08x ] +0x0002f007 CPU%(cpu)d %(tsc)d domain_shutdown [ domid = 0x%(1)08x, edomid = 0x%(2)08x, reason = 0x%(3)08x ] +0x0002f008 CPU%(cpu)d %(tsc)d sched_ctl +0x0002f009 CPU%(cpu)d %(tsc)d sched_adjdom [ domid = 0x%(1)08x ] +0x0002f00a CPU%(cpu)d %(tsc)d __enter_scheduler [ prev<domid:edomid> = 0x%(1)08x : 0x%(2)08x, next<domid:edomid> = 0x%(3)08x : 0x%(4)08x ] +0x0002f00B CPU%(cpu)d %(tsc)d s_timer_fn +0x0002f00c CPU%(cpu)d %(tsc)d t_timer_fn +0x0002f00d CPU%(cpu)d %(tsc)d dom_timer_fn 0x00080001 CPU%(cpu)d %(tsc)d VMX_VMEXIT [ domid = 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ] 0x00080002 CPU%(cpu)d %(tsc)d VMX_VECTOR [ domid = 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ] diff --git a/tools/xentrace/setsize.c b/tools/xentrace/setsize.c new file mode 100644 index 0000000000..0b5311ea57 --- /dev/null +++ b/tools/xentrace/setsize.c @@ -0,0 +1,36 @@ +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <xenctrl.h> + +int main(int argc, char * argv[]) +{ + unsigned int size; + int xc_handle = xc_interface_open(); + + if (xc_tbuf_get_size(xc_handle, &size) != 0) { + perror("Failure to get tbuf info from Xen. Guess size is 0."); + printf("This may mean that tracing is not compiled into xen.\n"); + exit(1); + } + else + printf("Current tbuf size: 0x%x\n", size); + + if (argc < 2) + exit(0); + + size = atoi(argv[1]); + + if (xc_tbuf_set_size(xc_handle, size) != 0) { + perror("set_size Hypercall failure"); + exit(1); + } + + if (xc_tbuf_get_size(xc_handle, &size) != 0) + perror("Failure to get tbuf info from Xen. Guess size is 0."); + else + printf("New tbuf size: 0x%x\n", size); + + xc_interface_close(xc_handle); + return 0; +} diff --git a/tools/xentrace/tbctl.c b/tools/xentrace/tbctl.c new file mode 100644 index 0000000000..fd9dc3a9c8 --- /dev/null +++ b/tools/xentrace/tbctl.c @@ -0,0 +1,26 @@ +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <xenctrl.h> + +int main(int argc, char * argv[]) +{ + int enable; + int xc_handle = xc_interface_open(); + + if (argc < 2) { + printf("usage: %s [0|1]\n", argv[0]); + exit(1); + } + enable = atoi(argv[1]); + + if (xc_tbuf_enable(xc_handle, enable) != 0) { + perror("Enable/Disable Hypercall failure"); + exit(1); + } + else + printf("Tracing now %s\n", (enable ? "enabled" : "disabled")); + + xc_interface_close(xc_handle); + return 0; +} diff --git a/xen/Rules.mk b/xen/Rules.mk index f65564240a..cb198b77f4 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -6,7 +6,7 @@ verbose ?= n debug ?= n perfc ?= n perfc_arrays?= n -trace ?= n +trace ?= y domu_debug ?= n crash_debug ?= n diff --git a/xen/common/trace.c b/xen/common/trace.c index 7ba71a8009..f3582c61e4 100644 --- a/xen/common/trace.c +++ b/xen/common/trace.c @@ -5,8 +5,9 @@ * * Copyright (C) 2004 by Intel Research Cambridge * - * Author: Mark Williamson, mark.a.williamson@intel.com - * Date: January 2004 + * Authors: Mark Williamson, mark.a.williamson@intel.com + * Rob Gardner, rob.gardner@hp.com + * Date: October 2005 * * Copyright (C) 2005 Bin Ren * @@ -31,13 +32,14 @@ #include <public/dom0_ops.h> /* opt_tbuf_size: trace buffer size (in pages) */ -static unsigned int opt_tbuf_size = 10; +static unsigned int opt_tbuf_size = 0; integer_param("tbuf_size", opt_tbuf_size); /* Pointers to the meta-data objects for all system trace buffers */ struct t_buf *t_bufs[NR_CPUS]; -/* a flag recording whether initialisation has been done */ +/* a flag recording whether initialization has been done */ +/* or more properly, if the tbuf subsystem is enabled right now */ int tb_init_done = 0; /* which CPUs tracing is enabled on */ @@ -45,19 +47,17 @@ unsigned long tb_cpu_mask = (~0UL); /* which tracing events are enabled */ u32 tb_event_mask = TRC_ALL; + /** - * init_trace_bufs - performs initialisation of the per-cpu trace buffers. + * init_trace_bufs - performs initialization of the per-cpu trace buffers. * - * This function is called at start of day in order to initialise the per-cpu + * This function is called at start of day in order to initialize the per-cpu * trace buffers. The trace buffers are then available for debugging use, via * the %TRACE_xD macros exported in <xen/trace.h>. */ void init_trace_bufs(void) { - int i, order; - unsigned long nr_pages; - char *rawbuf; - struct t_buf *buf; + extern int alloc_trace_bufs(void); if ( opt_tbuf_size == 0 ) { @@ -65,13 +65,40 @@ void init_trace_bufs(void) return; } + if (alloc_trace_bufs() == 0) { + printk("Xen trace buffers: initialised\n"); + wmb(); /* above must be visible before tb_init_done flag set */ + tb_init_done = 1; + } +} + +/** + * alloc_trace_bufs - performs initialization of the per-cpu trace buffers. + * + * This function is called at start of day in order to initialize the per-cpu + * trace buffers. The trace buffers are then available for debugging use, via + * the %TRACE_xD macros exported in <xen/trace.h>. + * + * This function may also be called later when enabling trace buffers + * via the SET_SIZE hypercall. + */ +int alloc_trace_bufs(void) +{ + int i, order; + unsigned long nr_pages; + char *rawbuf; + struct t_buf *buf; + + if ( opt_tbuf_size == 0 ) + return -EINVAL; + nr_pages = num_online_cpus() * opt_tbuf_size; order = get_order_from_pages(nr_pages); if ( (rawbuf = alloc_xenheap_pages(order)) == NULL ) { printk("Xen trace buffers: memory allocation failed\n"); - return; + return -EINVAL; } /* Share pages so that xentrace can map them. */ @@ -88,14 +115,51 @@ void init_trace_bufs(void) buf->rec = (struct t_rec *)(buf + 1); buf->rec_addr = __pa(buf->rec); } + return 0; +} - printk("Xen trace buffers: initialised\n"); - - wmb(); /* above must be visible before tb_init_done flag set */ - tb_init_done = 1; +/** + * tb_set_size - handle the logic involved with dynamically + * allocating and deallocating tbufs + * + * This function is called when the SET_SIZE hypercall is done. + */ +int tb_set_size(int size) +{ + // There are three cases to handle: + // 1. Changing from 0 to non-zero ==> simple allocate + // 2. Changing from non-zero to 0 ==> simple deallocate + // 3. Changing size ==> deallocate and reallocate? Or disallow? + // User can just do a change to 0, then a change to the new size. + // + // Tracing must be disabled (tb_init_done==0) before calling this + + if (opt_tbuf_size == 0 && size > 0) { + // What if size is too big? alloc_xenheap will complain. + opt_tbuf_size = size; + if (alloc_trace_bufs() != 0) + return -EINVAL; + wmb(); + printk("Xen trace buffers: initialized\n"); + return 0; + } + else if (opt_tbuf_size > 0 && size == 0) { + int order = get_order_from_pages(num_online_cpus() * opt_tbuf_size); + // is there a way to undo SHARE_PFN_WITH_DOMAIN? + free_xenheap_pages(t_bufs[0], order); + opt_tbuf_size = 0; + printk("Xen trace buffers: uninitialized\n"); + return 0; + } + else { + printk("tb_set_size from %d to %d not implemented\n", opt_tbuf_size, size); + printk("change size from %d to 0, and then to %d\n", opt_tbuf_size, size); + return -EINVAL; + } } + /** * tb_control - DOM0 operations on trace buffers. * @tbc: a pointer to a dom0_tbufcontrol_t to be filled out @@ -105,8 +169,10 @@ int tb_control(dom0_tbufcontrol_t *tbc) static spinlock_t lock = SPIN_LOCK_UNLOCKED; int rc = 0; - if ( !tb_init_done ) - return -EINVAL; + // Commenting this out since we have to allow some of these operations + // in order to enable dynamic control of the trace buffers. + // if ( !tb_init_done ) + // return -EINVAL; spin_lock(&lock); @@ -124,6 +190,30 @@ int tb_control(dom0_tbufcontrol_t *tbc) case DOM0_TBUF_SET_EVT_MASK: tb_event_mask = tbc->evt_mask; break; + case DOM0_TBUF_SET_SIZE: + // Change trace buffer allocation. + // Trace buffers must be disabled to do this. + if (tb_init_done) { + printk("attempt to change size with tbufs enabled\n"); + rc = -EINVAL; + } + else + rc = tb_set_size(tbc->size); + break; + case DOM0_TBUF_ENABLE: + // Enable trace buffers. Size must be non-zero, ie, buffers + // must already be allocated. + if (opt_tbuf_size == 0) + rc = -EINVAL; + else + tb_init_done = 1; + break; + case DOM0_TBUF_DISABLE: + // Disable trace buffers. Just stops new records from being written, + // does not deallocate any memory. + tb_init_done = 0; + printk("Xen trace buffers: disabled\n"); + break; default: rc = -EINVAL; } diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index 1af736de7b..a6447c30f9 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -193,6 +193,9 @@ typedef struct { #define DOM0_TBUF_GET_INFO 0 #define DOM0_TBUF_SET_CPU_MASK 1 #define DOM0_TBUF_SET_EVT_MASK 2 +#define DOM0_TBUF_SET_SIZE 3 +#define DOM0_TBUF_ENABLE 4 +#define DOM0_TBUF_DISABLE 5 uint8_t op; /* IN/OUT variables */ unsigned long cpu_mask; |