aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxc/Makefile1
-rw-r--r--tools/libxc/xc_tbuf.c51
-rw-r--r--tools/libxc/xenctrl.h43
-rw-r--r--tools/xentrace/Makefile2
-rw-r--r--tools/xentrace/formats26
-rw-r--r--tools/xentrace/setsize.c36
-rw-r--r--tools/xentrace/tbctl.c26
-rw-r--r--xen/Rules.mk2
-rw-r--r--xen/common/trace.c124
-rw-r--r--xen/include/public/dom0_ops.h3
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;