aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/examples/xc_dom_control.py8
-rw-r--r--tools/xc/lib/xc_domain.c1
-rw-r--r--tools/xc/lib/xc_linux_restore.c7
-rw-r--r--tools/xc/lib/xc_linux_save.c207
-rw-r--r--tools/xc/lib/xc_private.c64
-rw-r--r--tools/xc/lib/xc_private.h5
-rw-r--r--tools/xc/py/Xc.c30
-rw-r--r--tools/xentrace/Makefile2
-rw-r--r--tools/xentrace/formats49
-rw-r--r--tools/xentrace/xentrace.c56
-rw-r--r--tools/xentrace/xentrace_format52
11 files changed, 330 insertions, 151 deletions
diff --git a/tools/examples/xc_dom_control.py b/tools/examples/xc_dom_control.py
index 877afa53d1..9feab009e3 100755
--- a/tools/examples/xc_dom_control.py
+++ b/tools/examples/xc_dom_control.py
@@ -136,15 +136,7 @@ elif cmd == 'suspend':
pid = int(fd.readline())
os.kill(pid, signal.SIGTERM)
- xc.domain_stop( dom=dom )
-
- while not xc.domain_getinfo( first_dom=dom, max_doms=1 )[0]['stopped']:
- print "Sleep..."
- time.sleep(0.001);
-
rc = xc.linux_save( dom=dom, state_file=file, progress=1)
- if rc == 0 : xc.domain_destroy( dom=dom, force=1 )
- else: xc.domain_start( dom=dom ) # sensible for production use
elif cmd == 'cpu_bvtslice':
if len(sys.argv) < 3:
diff --git a/tools/xc/lib/xc_domain.c b/tools/xc/lib/xc_domain.c
index 6d0dd6d0f3..97b2b26f6d 100644
--- a/tools/xc/lib/xc_domain.c
+++ b/tools/xc/lib/xc_domain.c
@@ -46,6 +46,7 @@ int xc_domain_stop(int xc_handle,
dom0_op_t op;
op.cmd = DOM0_STOPDOMAIN;
op.u.stopdomain.domain = (domid_t)domid;
+ op.u.stopdomain.sync = 0; // async
return do_dom0_op(xc_handle, &op);
}
diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c
index d66e22fd0a..4e89b5715f 100644
--- a/tools/xc/lib/xc_linux_restore.c
+++ b/tools/xc/lib/xc_linux_restore.c
@@ -592,14 +592,11 @@ int xc_linux_restore(int xc_handle,
out:
- if ( rc != 0 ) // destroy is something went wrong
+ if ( rc != 0 ) // destroy if something went wrong
{
if ( dom != 0 )
{
- op.cmd = DOM0_DESTROYDOMAIN;
- op.u.destroydomain.domain = (domid_t)dom;
- op.u.destroydomain.force = 1;
- (void)do_dom0_op(xc_handle, &op);
+ xc_domain_destroy( xc_handle, dom, 1 );
}
}
diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c
index ceb5f02e15..857007fd3e 100644
--- a/tools/xc/lib/xc_linux_save.c
+++ b/tools/xc/lib/xc_linux_save.c
@@ -82,6 +82,67 @@ inline void set_bit ( int nr, volatile void * addr)
(1 << (nr % (sizeof(unsigned long)*8) ) );
}
+long long tv_to_us( struct timeval *new )
+{
+ return (new->tv_sec * 1000000) + new->tv_usec;
+}
+
+long long tvdelta( struct timeval *new, struct timeval *old )
+{
+ return ((new->tv_sec - old->tv_sec)*1000000 ) +
+ (new->tv_usec - old->tv_usec);
+}
+
+int track_cpu_usage_dom0( int xc_handle, int print )
+{
+ static struct timeval wall_last;
+ static long long cpu_last;
+
+ struct timeval wall_now;
+ long long cpu_now, wall_delta, cpu_delta;
+
+ gettimeofday(&wall_now, NULL);
+
+ cpu_now = xc_domain_get_cpu_usage( xc_handle, 0 )/1000;
+
+ wall_delta = tvdelta(&wall_now,&wall_last)/1000;
+ cpu_delta = (cpu_now - cpu_last)/1000;
+
+ if(print)
+ printf("Dom0 : wall delta %lldms, cpu delta %lldms : %d%%\n",
+ wall_delta, cpu_delta, (cpu_delta*100)/wall_delta);
+
+ cpu_last = cpu_now;
+ wall_last = wall_now;
+
+ return 0;
+}
+
+int track_cpu_usage_target( int xc_handle, u64 domid, int print )
+{
+ static struct timeval wall_last;
+ static long long cpu_last;
+
+ struct timeval wall_now;
+ long long cpu_now, wall_delta, cpu_delta;
+
+ gettimeofday(&wall_now, NULL);
+
+ cpu_now = xc_domain_get_cpu_usage( xc_handle, domid )/1000;
+
+ wall_delta = tvdelta(&wall_now,&wall_last)/1000;
+ cpu_delta = (cpu_now - cpu_last)/1000;
+
+ if(print)
+ printf("Target: wall delta %lldms, cpu delta %lldms : %d%%\n",
+ wall_delta, cpu_delta, (cpu_delta*100)/wall_delta);
+
+ cpu_last = cpu_now;
+ wall_last = wall_now;
+
+ return 0;
+}
+
int xc_linux_save(int xc_handle,
u64 domid,
@@ -95,10 +156,11 @@ int xc_linux_save(int xc_handle,
int verbose = flags & XCFLAGS_VERBOSE;
int live = flags & XCFLAGS_LIVE;
int debug = flags & XCFLAGS_DEBUG;
- int sent_last_iter, sent_this_iter, max_iters;
-
- /* Remember if we stopped the guest, so we can restart it on exit. */
- int we_stopped_it = 0;
+ int sent_last_iter, sent_this_iter, skip_this_iter;
+
+ /* Important tuning parameters */
+ int max_iters = 29; // limit us to 30 times round loop
+ int max_factor = 3; // never send more than 3x nr_pfns
/* The new domain's shared-info frame number. */
unsigned long shared_info_frame;
@@ -137,11 +199,15 @@ int xc_linux_save(int xc_handle,
/* number of pages we're dealing with */
unsigned long nr_pfns;
- /* bitmap of pages left to send */
- unsigned long *to_send, *to_fix;
-
-//live=0;
+ /* bitmap of pages:
+ - that should be sent this iteration (unless later marked as skip);
+ - to skip this iteration because already dirty;
+ - to fixup by sending at the end if not already resent; */
+ unsigned long *to_send, *to_skip, *to_fix;
+ int needed_to_fix = 0;
+ int total_sent = 0;
+
if ( mlock(&ctxt, sizeof(ctxt) ) )
{
PERROR("Unable to mlock ctxt");
@@ -149,39 +215,16 @@ int xc_linux_save(int xc_handle,
}
/* Ensure that the domain exists, and that it is stopped. */
- for ( ; ; )
- {
- op.cmd = DOM0_GETDOMAININFO;
- op.u.getdomaininfo.domain = (domid_t)domid;
- op.u.getdomaininfo.ctxt = &ctxt;
- if ( (do_dom0_op(xc_handle, &op) < 0) ||
- ((u64)op.u.getdomaininfo.domain != domid) )
- {
- PERROR("Could not get info on domain");
- goto out;
- }
-
- memcpy(name, op.u.getdomaininfo.name, sizeof(name));
- shared_info_frame = op.u.getdomaininfo.shared_info_frame;
-
- if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
- break;
- we_stopped_it = 1;
-
- op.cmd = DOM0_STOPDOMAIN;
- op.u.stopdomain.domain = (domid_t)domid;
- if ( do_dom0_op(xc_handle, &op) != 0 )
- {
- we_stopped_it = 0;
- PERROR("Stopping target domain failed");
- goto out;
- }
-
- usleep(1000); // 1ms
- printf("Sleep for 1ms\n");
+ if ( xc_domain_stop_sync( xc_handle, domid, &op, &ctxt ) )
+ {
+ PERROR("Could not sync stop domain");
+ goto out;
}
+ memcpy(name, op.u.getdomaininfo.name, sizeof(name));
+ shared_info_frame = op.u.getdomaininfo.shared_info_frame;
+
/* A cheesy test to see whether the domain contains valid state. */
if ( ctxt.pt_base == 0 )
{
@@ -288,7 +331,6 @@ int xc_linux_save(int xc_handle,
last_iter = 0;
sent_last_iter = 1<<20; // 4GB's worth of pages
- max_iters = 9; // limit us to 10 time round loop
}
else
last_iter = 1;
@@ -300,12 +342,14 @@ int xc_linux_save(int xc_handle,
to_send = malloc( sz );
to_fix = calloc( 1, sz );
+ to_skip = malloc( sz );
- if (!to_send || !to_fix)
+ if (!to_send || !to_fix || !to_skip)
{
ERROR("Couldn't allocate to_send array");
goto out;
}
+
memset( to_send, 0xff, sz );
if ( mlock( to_send, sz ) )
@@ -313,6 +357,15 @@ int xc_linux_save(int xc_handle,
PERROR("Unable to mlock to_send");
return 1;
}
+
+ /* (to fix is local only) */
+
+ if ( mlock( to_skip, sz ) )
+ {
+ PERROR("Unable to mlock to_skip");
+ return 1;
+ }
+
}
@@ -369,8 +422,11 @@ int xc_linux_save(int xc_handle,
goto out;
}
- /* Now write out each data page, canonicalising page tables as we go... */
+ track_cpu_usage_dom0(xc_handle, 0);
+ track_cpu_usage_target( xc_handle, domid, 0);
+ /* Now write out each data page, canonicalising page tables as we go... */
+
while(1)
{
unsigned int prev_pc, batch, sent_this_iter;
@@ -378,6 +434,7 @@ int xc_linux_save(int xc_handle,
iter++;
sent_this_iter = 0;
+ skip_this_iter = 0;
prev_pc = 0;
verbose_printf("Saving memory pages: iter %d 0%%", iter);
@@ -391,6 +448,18 @@ int xc_linux_save(int xc_handle,
prev_pc = this_pc;
}
+ /* slightly wasteful to peek the whole array evey time,
+ but this is fast enough for the moment. */
+
+ if ( !last_iter &&
+ xc_shadow_control( xc_handle, domid,
+ DOM0_SHADOW_CONTROL_OP_PEEK,
+ to_skip, nr_pfns ) != nr_pfns )
+ {
+ ERROR("Error peeking shadow bitmap");
+ goto out;
+ }
+
/* load pfn_type[] with the mfn of all the pages we're doing in
this batch. */
@@ -404,15 +473,29 @@ int xc_linux_save(int xc_handle,
test_bit(n,to_send),
live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]&0xFFFFF]);
+ if (!last_iter && test_bit(n, to_send) && test_bit(n, to_skip))
+ skip_this_iter++; // stats keeping
- if ( !test_bit(n, to_send ) &&
- !( last_iter && test_bit(n, to_fix ) ) ) continue;
+ if (! ( (test_bit(n, to_send) && !test_bit(n, to_skip)) ||
+ (test_bit(n, to_send) && last_iter) ||
+ (test_bit(n, to_fix) && last_iter) ) )
+ continue;
+
+ /* we get here if:
+ 1. page is marked to_send & hasn't already been re-dirtied
+ 2. (ignore to_skip in last iteration)
+ 3. add in pages that still need fixup (net bufs)
+ */
pfn_batch[batch] = n;
pfn_type[batch] = live_pfn_to_mfn_table[n];
if( pfn_type[batch] == 0x80000004 )
{
+ /* not currently in pusedo-physical map -- set bit
+ in to_fix that we must send this page in last_iter
+ unless its sent sooner anyhow */
+
set_bit( n, to_fix );
if( iter>1 )
DDPRINTF("Urk! netbuf race: iter %d, pfn %lx. mfn %lx\n",
@@ -422,6 +505,7 @@ int xc_linux_save(int xc_handle,
if ( last_iter && test_bit(n, to_fix ) && !test_bit(n, to_send ))
{
+ needed_to_fix++;
DPRINTF("Fix! iter %d, pfn %lx. mfn %lx\n",
iter,n,pfn_type[batch]);
}
@@ -567,9 +651,23 @@ int xc_linux_save(int xc_handle,
munmap(region_base, batch*PAGE_SIZE);
skip:
+
+ total_sent += sent_this_iter;
+
+ verbose_printf("\b\b\b\b100%% (pages sent= %d, skipped= %d )\n",
+ sent_this_iter, skip_this_iter );
+
+ track_cpu_usage_dom0(xc_handle, 1);
+ track_cpu_usage_target( xc_handle, domid, 1);
+
- verbose_printf("\b\b\b\b100%% (%d pages)\n", sent_this_iter );
-
+ if ( last_iter )
+ {
+ verbose_printf("Total pages sent= %d (%.2fx)\n",
+ total_sent, ((float)total_sent)/nr_pfns );
+ verbose_printf("(of which %d were fixups)\n", needed_to_fix );
+ }
+
if ( debug && last_iter )
{
int minusone = -1;
@@ -592,18 +690,21 @@ int xc_linux_save(int xc_handle,
if ( live )
{
- if ( ( sent_this_iter > (sent_last_iter * 0.95) ) ||
- (iter >= max_iters) || (sent_this_iter < 10) )
+ if (
+ // ( sent_this_iter > (sent_last_iter * 0.95) ) ||
+ (iter >= max_iters) ||
+ (sent_this_iter+skip_this_iter < 10) ||
+ (total_sent > nr_pfns*max_factor) )
{
DPRINTF("Start last iteration\n");
last_iter = 1;
- xc_domain_stop_sync( xc_handle, domid );
+ xc_domain_stop_sync( xc_handle, domid, &op, NULL );
}
if ( xc_shadow_control( xc_handle, domid,
- DOM0_SHADOW_CONTROL_OP_CLEAN,
+ DOM0_SHADOW_CONTROL_OP_CLEAN2,
to_send, nr_pfns ) != nr_pfns )
{
ERROR("Error flushing shadow PT");
@@ -674,14 +775,6 @@ int xc_linux_save(int xc_handle,
munmap(live_shinfo, PAGE_SIZE);
out:
- /* Restart the domain if we had to stop it to save its state. */
- if ( we_stopped_it )
- {
- printf("Restart domain\n");
- op.cmd = DOM0_STARTDOMAIN;
- op.u.startdomain.domain = (domid_t)domid;
- (void)do_dom0_op(xc_handle, &op);
- }
if ( pfn_type != NULL )
free(pfn_type);
diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c
index 015354fde5..9fd36455fd 100644
--- a/tools/xc/lib/xc_private.c
+++ b/tools/xc/lib/xc_private.c
@@ -377,51 +377,67 @@ int finish_mmu_updates(int xc_handle, mmu_t *mmu)
/* this function is a hack until we get proper synchronous domain stop */
-int xc_domain_stop_sync( int xc_handle, domid_t domid )
+int xc_domain_stop_sync( int xc_handle, domid_t domid,
+ dom0_op_t *op, full_execution_context_t *ctxt)
{
- dom0_op_t op;
int i;
-
-
- op.cmd = DOM0_STOPDOMAIN;
- op.u.stopdomain.domain = (domid_t)domid;
- if ( do_dom0_op(xc_handle, &op) != 0 )
- {
- PERROR("Stopping target domain failed");
- goto out;
- }
- usleep(100); // 100us
+ printf("Sleep:");
for(i=0;;i++)
- {
- if (i>0)
- if (i==1) printf("Sleep.");
- else printf(".");
-
- op.cmd = DOM0_GETDOMAININFO;
- op.u.getdomaininfo.domain = (domid_t)domid;
- op.u.getdomaininfo.ctxt = NULL;
- if ( (do_dom0_op(xc_handle, &op) < 0) ||
- ((u64)op.u.getdomaininfo.domain != domid) )
+ {
+
+ op->cmd = DOM0_STOPDOMAIN;
+ op->u.stopdomain.domain = (domid_t)domid;
+ op->u.stopdomain.sync = 1;
+ do_dom0_op(xc_handle, op);
+ /* can't trust return code due to sync stop hack :-(( */
+
+
+ op->cmd = DOM0_GETDOMAININFO;
+ op->u.getdomaininfo.domain = (domid_t)domid;
+ op->u.getdomaininfo.ctxt = ctxt;
+ if ( (do_dom0_op(xc_handle, op) < 0) ||
+ ((u64)op->u.getdomaininfo.domain != domid) )
{
PERROR("Could not get info on domain");
goto out;
}
- if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
+ if ( op->u.getdomaininfo.state == DOMSTATE_STOPPED )
{
printf("Domain %lld stopped\n",domid);
return 0;
}
- usleep(1000);
+ printf(".");
+
+ //usleep(1000);
}
+ printf("\n");
+
out:
return -1;
}
+long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid )
+{
+ dom0_op_t op;
+
+ op.cmd = DOM0_GETDOMAININFO;
+ op.u.getdomaininfo.domain = (domid_t)domid;
+ op.u.getdomaininfo.ctxt = NULL;
+ if ( (do_dom0_op(xc_handle, &op) < 0) ||
+ ((u64)op.u.getdomaininfo.domain != domid) )
+ {
+ PERROR("Could not get info on domain");
+ return -1;
+ }
+ return op.u.getdomaininfo.cpu_time;
+}
+
+
/**********************************************************************/
// this is shared between save and restore, and may be useful.
diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h
index e3eff85e59..330edca50f 100644
--- a/tools/xc/lib/xc_private.h
+++ b/tools/xc/lib/xc_private.h
@@ -248,6 +248,9 @@ void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset,
/*********************/
-int xc_domain_stop_sync( int xc_handle, domid_t dom );
+int xc_domain_stop_sync( int xc_handle, domid_t dom,
+ dom0_op_t *op, full_execution_context_t *ctxt );
+
+long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid );
#endif /* __XC_PRIVATE_H__ */
diff --git a/tools/xc/py/Xc.c b/tools/xc/py/Xc.c
index 7bb1d877bd..8a6e3b22ef 100644
--- a/tools/xc/py/Xc.c
+++ b/tools/xc/py/Xc.c
@@ -214,6 +214,7 @@ static PyObject *pyxc_linux_save(PyObject *self,
struct hostent *h;
struct sockaddr_in s;
int sockbufsize;
+ int rc = -1;
int writerfn(void *fd, const void *buf, size_t count)
{
@@ -257,12 +258,24 @@ static PyObject *pyxc_linux_save(PyObject *self,
if ( xc_linux_save(xc->xc_handle, dom, flags,
writerfn, (void*)sd) == 0 )
{
- close(sd);
- Py_INCREF(zero);
- return zero;
+ if ( read( sd, &rc, sizeof(int) ) != sizeof(int) )
+ goto serr;
+
+ if ( rc == 0 )
+ {
+ printf("Migration succesful -- destroy local copy\n");
+ xc_domain_destroy( xc->xc_handle, dom, 1 );
+ close(sd);
+ Py_INCREF(zero);
+ return zero;
+ }
+ else
+ errno = rc;
}
serr:
+ printf("Migration failed -- restart local copy\n");
+ xc_domain_start( xc->xc_handle, dom );
PyErr_SetFromErrno(xc_error);
if ( sd >= 0 ) close(sd);
return NULL;
@@ -355,7 +368,7 @@ static PyObject *pyxc_linux_restore(PyObject *self,
struct sockaddr_in s, d, p;
socklen_t dlen, plen;
int sockbufsize;
- int on = 1;
+ int on = 1, rc = -1;
int readerfn(void *fd, void *buf, size_t count)
{
@@ -413,13 +426,18 @@ static PyObject *pyxc_linux_restore(PyObject *self,
sizeof sockbufsize) < 0 )
goto serr;
- if ( xc_linux_restore(xc->xc_handle, dom, flags,
- readerfn, (void*)sd, &dom) == 0 )
+ rc = xc_linux_restore(xc->xc_handle, dom, flags,
+ readerfn, (void*)sd, &dom);
+
+ write( sd, &rc, sizeof(int) );
+
+ if (rc == 0)
{
close(sd);
Py_INCREF(zero);
return zero;
}
+ errno = rc;
serr:
PyErr_SetFromErrno(xc_error);
diff --git a/tools/xentrace/Makefile b/tools/xentrace/Makefile
index 4a63ae2b3e..d64d2a5a36 100644
--- a/tools/xentrace/Makefile
+++ b/tools/xentrace/Makefile
@@ -1,6 +1,6 @@
CC = gcc
-CFLAGS = -Wall -O3
+CFLAGS = -Wall -O3 -Werror
CFLAGS += -I../../xen/include/hypervisor-ifs
CFLAGS += -I../../xenolinux-sparse/include
CFLAGS += -I../xend/lib
diff --git a/tools/xentrace/formats b/tools/xentrace/formats
index 726c199bd9..9a5b157f47 100644
--- a/tools/xentrace/formats
+++ b/tools/xentrace/formats
@@ -1,14 +1,35 @@
-0x00010000 CPU%(cpu)d 0x%(tsc)x sched_add_domain(0x%(3)08x) [ dom id = 0x%(1)x%(2)08x ]
-0x00010001 CPU%(cpu)d 0x%(tsc)x sched_rem_domain(0x%08(3)x) [ dom id = 0x%(1)x%(2)08x ]
-0x00010002 CPU%(cpu)d 0x%(tsc)x __wake_up(0x%(3)08x) [ dom id = 0x%(1)x%(2)08x ]
-0x00010003 CPU%(cpu)d 0x%(tsc)x do_block() [ current = 0x%(2)08x ]
-0x00010004 CPU%(cpu)d 0x%(tsc)x do_yield() [ current = %(2)08x ]
-0x00010005 CPU%(cpu)d 0x%(tsc)x do_set_timer_op(0x%(4)08x, 0x%(5)08x) [ current = 0x%(3)08x ]
-0x00010006 CPU%(cpu)d 0x%(tsc)x sched_ctl(0x%(1)08x)
-0x00010007 CPU%(cpu)d 0x%(tsc)x sched_adjdom(params) [ dom id = 0x%(1)x%(2)08x ]
-0x00010008 CPU%(cpu)d 0x%(tsc)x __reschedule(0x%(3)08x) [ dom id = 0x%(1)x%(2)08x ]
-0x00010009 CPU%(cpu)d 0x%(tsc)x switching to task_struct 0x%(1)08x [ dom id = 0x%(1)x ]
-0x0001000A CPU%(cpu)d 0x%(tsc)x s_timer_fn(unused)
-0x0001000B CPU%(cpu)d 0x%(tsc)x t_timer_fn(unused)
-0x0001000C CPU%(cpu)d 0x%(tsc)x dom_timer_fn(data)
-0x0001000D CPU%(cpu)d 0x%(tsc)x fallback_timer_fn(unused)
+#0x00010000 CPU%(cpu)d %(tsc).6f sched_add_domain(0x%(3)08x) [ dom id = 0x%(1)x%(2)08x ]
+#0x00010001 CPU%(cpu)d %(tsc).6f sched_rem_domain(0x%08(3)x) [ dom id = 0x%(1)x%(2)08x ]
+#0x00010002 CPU%(cpu)d %(tsc).6f __wake_up(0x%(3)08x) [ dom id = 0x%(1)x%(2)08x ]
+#0x00010003 CPU%(cpu)d %(tsc).6f do_block() [ current = 0x%(2)08x ]
+#0x00010004 CPU%(cpu)d %(tsc).6f do_yield() [ current = %(2)08x ]
+#0x00010005 CPU%(cpu)d %(tsc).6f do_set_timer_op(0x%(4)08x, 0x%(5)08x) [ current = 0x%(3)08x ]
+#0x00010006 CPU%(cpu)d %(tsc).6f sched_ctl(0x%(1)08x)
+#0x00010007 CPU%(cpu)d %(tsc).6f sched_adjdom(params) [ dom id = 0x%(1)x%(2)08x ]
+#0x00010008 CPU%(cpu)d %(tsc).6f __reschedule(0x%(3)08x) [ dom id = 0x%(1)x%(2)08x ]
+#0x00010009 CPU%(cpu)d %(tsc).6f switching to task_struct 0x%(1)08x [ dom id = 0x%(1)x ]
+#0x0001000A CPU%(cpu)d %(tsc).6f s_timer_fn(unused)
+#0x0001000B CPU%(cpu)d %(tsc).6f t_timer_fn(unused)
+#0x0001000C CPU%(cpu)d %(tsc).6f dom_timer_fn(data)
+#0x0001000D CPU%(cpu)d %(tsc).6f fallback_timer_fn(unused)
+
+
+0x00020008 CPU%(cpu)d %(tsc).6f enter: dom0_create_dom ( )
+0x00030008 CPU%(cpu)d %(tsc).6f leave: dom0_create_dom ( )
+
+0x00020009 CPU%(cpu)d %(tsc).6f enter: dom0_destroy_dom ( dom=0x%(2)x )
+0x00030009 CPU%(cpu)d %(tsc).6f leave: dom0_destroy_dom ( dom=0x%(2)x ) = %(1)d
+
+0x0002000A CPU%(cpu)d %(tsc).6f enter: dom0_start_dom ( dom=0x%(2)x )
+0x0003000A CPU%(cpu)d %(tsc).6f leave: dom0_start_dom ( dom=0x%(2)x ) = %(1)d
+0x0002000B CPU%(cpu)d %(tsc).6f enter: dom0_stop_dom ( dom=0x%(2)x )
+0x0003000B CPU%(cpu)d %(tsc).6f leave: dom0_stop_dom ( dom=0x%(2)x ) = %(1)d
+0x0002000C CPU%(cpu)d %(tsc).6f enter: dom0_getinfo ( dom=0x%(2)x )
+0x0003000C CPU%(cpu)d %(tsc).6f leave: dom0_getinfo ( dom=0x%(2)x ) = %(1)d
+0x0002000D CPU%(cpu)d %(tsc).6f enter: dom0_build ( dom=0x%(2)x )
+0x0003000D CPU%(cpu)d %(tsc).6f leave: dom0_build ( dom=0x%(2)x ) = %(1)d
+
+0x00020019 CPU%(cpu)d %(tsc).6f enter: dom0_shadow_op ( dom=0x%(2)x, %(3)d )
+0x00030019 CPU%(cpu)d %(tsc).6f leave: dom0_shadow_op ( dom=0x%(2)x, %(3)d ) = %(1)d
+
+#0x0 CPU%(cpu)d %(tsc).6f %(event)x
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index 157435baa0..dae9b67d80 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -227,10 +227,10 @@ struct t_rec **init_rec_ptrs(unsigned long tbufs_phys,
* trace buffer. Each entry in this table corresponds to the tail index for a
* particular trace buffer.
*/
-int *init_tail_idxs(struct t_buf **bufs, unsigned int num)
+unsigned long *init_tail_idxs(struct t_buf **bufs, unsigned int num)
{
int i;
- int *tails = calloc(num, sizeof(unsigned int));
+ unsigned long *tails = calloc(num, sizeof(unsigned int));
if ( tails == NULL )
{
@@ -276,16 +276,19 @@ unsigned int get_num_cpus()
*/
int monitor_tbufs(FILE *logfile)
{
- int i, j;
+ int i;
+
void *tbufs_mapped; /* pointer to where the tbufs are mapped */
struct t_buf **meta; /* pointers to the trace buffer metadata */
struct t_rec **data; /* pointers to the trace buffer data areas
* where they are mapped into user space. */
- int *tails; /* store tail indexes for the trace buffers */
+ unsigned long *cons; /* store tail indexes for the trace buffers */
unsigned long tbufs_phys; /* physical address of the tbufs */
unsigned int num; /* number of trace buffers / logical CPUS */
unsigned long size; /* size of a single trace buffer */
+ int size_in_recs;
+
/* get number of logical CPUs (and therefore number of trace buffers) */
num = get_num_cpus();
@@ -293,39 +296,32 @@ int monitor_tbufs(FILE *logfile)
get_tbufs(&tbufs_phys, &size);
tbufs_mapped = map_tbufs(tbufs_phys, num, size);
+ size_in_recs = (size / sizeof(struct t_rec) )-1;
+
/* build arrays of convenience ptrs */
meta = init_bufs_ptrs (tbufs_mapped, num, size);
data = init_rec_ptrs (tbufs_phys, tbufs_mapped, meta, num);
- tails = init_tail_idxs (meta, num);
+ cons = init_tail_idxs (meta, num);
/* now, scan buffers for events */
while ( !interrupted )
{
for ( i = 0; ( i < num ) && !interrupted; i++ )
- {
- signed long newdata = meta[i]->head - tails[i];
- signed long prewrap = newdata;
-
- /* correct newdata and prewrap in case of a pointer wrap */
- if ( newdata < 0 )
- {
- newdata += meta[i]->size;
- prewrap = meta[i]->size - tails[i];
- }
-
- if ( newdata >= opts.new_data_thresh )
- {
- /* output pre-wrap data */
- for(j = 0; j < prewrap; j++)
- write_rec(i, data[i] + tails[i] + j, logfile);
-
- /* output post-wrap data, if any */
- for(j = 0; j < (newdata - prewrap); j++)
- write_rec(i, data[i] + j, logfile);
-
- tails[i] += newdata;
- if(tails[i] >= meta[i]->size) tails[i] = 0;
- }
+ {
+/* printf("XX%d: cons=%ld head=%ld %p\n", i,
+ cons[i], meta[i]->head, data[i] + (cons[i] % size_in_recs) );
+ */
+ while( cons[i] < meta[i]->head )
+ {
+/*
+ if( (cons[i] % 6 ) == 0 )
+ printf("%d: cons=%ld head=%ld %p\n", i,
+ cons[i], meta[i]->head, data[i] + (cons[i] % size_in_recs) );
+ */
+ write_rec(i, data[i] + (cons[i] % size_in_recs), logfile);
+ cons[i]++;
+ }
+
}
nanosleep(&opts.poll_sleep, NULL);
}
@@ -333,7 +329,7 @@ int monitor_tbufs(FILE *logfile)
/* cleanup */
free(meta);
free(data);
- free(tails);
+ free(cons);
/* don't need to munmap - cleanup is automatic */
fclose(logfile);
diff --git a/tools/xentrace/xentrace_format b/tools/xentrace/xentrace_format
index 4014811249..d2e51265d4 100644
--- a/tools/xentrace/xentrace_format
+++ b/tools/xentrace/xentrace_format
@@ -4,7 +4,7 @@
# Program for reformatting trace buffer output according to user-supplied rules
-import re, sys, string, signal, struct
+import re, sys, string, signal, struct, os, getopt
def usage():
print >> sys.stderr, \
@@ -43,6 +43,9 @@ def read_defs(defs_file):
line = fd.readline()
if not line:
break
+
+ if line[0] == '#' or line[0] == '\n':
+ continue
m = reg.match(line)
@@ -58,29 +61,61 @@ def sighand(x,y):
##### Main code
+mhz = 0
+
if len(sys.argv) < 2:
usage()
+try:
+ opts, arg = getopt.getopt(sys.argv[1:], "c:" )
+
+ for opt in opts:
+ if opt[0] == '-c' : mhz = int(opt[1])
+
+except getopt.GetoptError:
+ usage()
+
+print mhz
+
signal.signal(signal.SIGTERM, sighand)
signal.signal(signal.SIGHUP, sighand)
signal.signal(signal.SIGINT, sighand)
interrupted = 0
-defs = read_defs(sys.argv[1])
+defs = read_defs(arg[0])
+
+print defs
# structure of trace record + prepended CPU id (as output by xentrace):
# CPU(I) TSC(Q) EVENT(L) D1(L) D2(L) D3(L) D4(L) D5(L)
TRCREC = "IQLLLLLL"
+last_tsc = [0,0,0,0,0,0,0,0]
+
+i=0
+
while not interrupted:
try:
+ i=i+1
line = sys.stdin.read(struct.calcsize(TRCREC))
if not line:
break
(cpu, tsc, event, d1, d2, d3, d4, d5) = struct.unpack(TRCREC, line)
+ #tsc = (tscH<<32) | tscL
+
+ #print i, tsc
+
+ if tsc < last_tsc[cpu]:
+ print "TSC stepped backward cpu %d ! %d %d" % (cpu,tsc,last_tsc[cpu])
+
+ last_tsc[cpu] = tsc
+
+ if mhz:
+ tsc = tsc / (mhz*1000000.0)
+
args = {'cpu' : cpu,
'tsc' : tsc,
'event' : event,
@@ -90,8 +125,15 @@ while not interrupted:
'4' : d4,
'5' : d5 }
- if defs.has_key(str(event)): print defs[str(event)] % args
- # silently skip lines we don't have a format for - a 'complain' option
- # should be added if needed
+ try:
+
+ if defs.has_key(str(event)):
+ print defs[str(event)] % args
+ else:
+ if defs.has_key(str(0)): print defs[str(0)] % args
+ except TypeError:
+ print defs[str(event)]
+ print args
+
except IOError, struct.error: sys.exit()