aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/xc/lib/xc_linux_restore.c41
-rw-r--r--tools/xc/lib/xc_linux_save.c114
-rw-r--r--tools/xc/lib/xc_private.c30
-rw-r--r--tools/xc/py/Xc.c8
4 files changed, 87 insertions, 106 deletions
diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c
index 9b1532159f..1bbc575889 100644
--- a/tools/xc/lib/xc_linux_restore.c
+++ b/tools/xc/lib/xc_linux_restore.c
@@ -12,6 +12,15 @@
#define MAX_BATCH_SIZE 1024
+#define DEBUG 0
+
+#if DEBUG
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+
/* This may allow us to create a 'quiet' command-line option, if necessary. */
#define verbose_printf(_f, _a...) \
do { \
@@ -230,7 +239,7 @@ int xc_linux_restore(int xc_handle,
goto out;
}
- printf("batch %d\n",j);
+ DPRINTF("batch %d\n",j);
if (j == 0)
break; // our work here is done
@@ -272,11 +281,6 @@ int xc_linux_restore(int xc_handle,
pfn = region_pfn_type[i] & ~PGT_type_mask;
-//if(n>=nr_pfns || ((region_pfn_type[i] & PGT_type_mask) == L2TAB) ) printf("pfn=%08lx mfn=%x\n",region_pfn_type[i],pfn_to_mfn_table[pfn]);
-
-
-//if(pfn_type[i])printf("^pfn=%d %08lx\n",pfn,pfn_type[i]);
-
if ((region_pfn_type[i]>>29) == 7)
continue;
@@ -292,8 +296,6 @@ int xc_linux_restore(int xc_handle,
mfn = pfn_to_mfn_table[pfn];
-//if(region_pfn_type[i])printf("i=%d pfn=%d mfn=%d type=%lx\n",i,pfn,mfn,region_pfn_type[i]);
-
ppage = (unsigned long*) (region_base + i*PAGE_SIZE);
if ( (*readerfn)(readerst, ppage, PAGE_SIZE) )
@@ -315,21 +317,12 @@ int xc_linux_restore(int xc_handle,
{
xpfn = ppage[k] >> PAGE_SHIFT;
-/*printf("L1 i=%d pfn=%d mfn=%d k=%d pte=%08lx xpfn=%d\n",
- i,pfn,mfn,k,ppage[k],xpfn);*/
-
if ( xpfn >= nr_pfns )
{
ERROR("Frame number in type %d page table is out of range. i=%d k=%d pfn=0x%x nr_pfns=%d",region_pfn_type[i]>>29,i,k,xpfn,nr_pfns);
goto out;
}
-#if 0
- if ( (region_pfn_type[xpfn] != NONE) && (ppage[k] & _PAGE_RW) )
- {
- ERROR("Write access requested for a restricted frame");
- goto out;
- }
-#endif
+
ppage[k] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
ppage[k] |= pfn_to_mfn_table[xpfn] << PAGE_SHIFT;
}
@@ -345,9 +338,6 @@ int xc_linux_restore(int xc_handle,
{
xpfn = ppage[k] >> PAGE_SHIFT;
-/*printf("L2 i=%d pfn=%d mfn=%d k=%d pte=%08lx xpfn=%d\n",
- i,pfn,mfn,k,ppage[k],xpfn);*/
-
if ( xpfn >= nr_pfns )
{
ERROR("Frame number in type %d page table is out of range. i=%d k=%d pfn=%d nr_pfns=%d",region_pfn_type[i]>>29,i,k,xpfn,nr_pfns);
@@ -383,7 +373,8 @@ int xc_linux_restore(int xc_handle,
n+=j; // crude stats
}
-printf("RECEIVED ALL PAGES\n");
+
+ DPRINTF("Received all pages\n");
mfn_mapper_close( region_mapper );
@@ -445,8 +436,6 @@ printf("RECEIVED ALL PAGES\n");
p_srec->resume_info.flags = 0;
unmap_pfn(pm_handle, p_srec);
-printf("new shared info is %lx\n", shared_info_frame);
-
/* Uncanonicalise each GDT frame number. */
if ( ctxt.gdt_ents > 8192 )
{
@@ -554,9 +543,9 @@ printf("new shared info is %lx\n", shared_info_frame);
op.u.builddomain.ctxt = &ctxt;
rc = do_dom0_op(xc_handle, &op);
-printf("NORMAL EXIT RESTORE\n");
+ DPRINTF("Everything OK!\n");
+
out:
-printf("EXIT RESTORE\n");
if ( mmu != NULL )
free(mmu);
diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c
index cbb1d66fd1..37dd7c6fce 100644
--- a/tools/xc/lib/xc_linux_save.c
+++ b/tools/xc/lib/xc_linux_save.c
@@ -11,6 +11,14 @@
#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */
+#define DEBUG 0
+
+#if DEBUG
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
/* This may allow us to create a 'quiet' command-line option, if necessary. */
#define verbose_printf(_f, _a...) \
do { \
@@ -64,7 +72,7 @@ int xc_linux_save(int xc_handle,
int rc = 1, i, j, k, n, last_iter, iter = 0;
unsigned long mfn;
int verbose = flags & XCFLAGS_VERBOSE;
- int live = 1; //flags & XCFLAGS_LIVE; // XXXXXXXXXXXXXXXXXXX
+ int live = flags & XCFLAGS_LIVE;
int sent_last_iter, sent_this_iter, max_iters;
/* Remember if we stopped the guest, so we can restart it on exit. */
@@ -149,15 +157,12 @@ int xc_linux_save(int xc_handle,
printf("Sleep for 1ms\n");
}
-#if 1
/* A cheesy test to see whether the domain contains valid state. */
if ( ctxt.pt_base == 0 )
{
ERROR("Domain is not in a valid Linux guest OS state");
goto out;
}
-#endif
-
/* Map the suspend-record MFN to pin it. The page must be owned by
domid for this to succeed. */
@@ -225,16 +230,23 @@ int xc_linux_save(int xc_handle,
goto out;
}
- for(i=0;i<(nr_pfns+1023)/1024 ;i++)
- printf("LF: %d %x\n",i,live_pfn_to_mfn_frame_list[i]);
+ /* Canonicalise the pfn-to-mfn table frame-number list. */
+ memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
+ for ( i = 0; i < nr_pfns; i += 1024 )
+ {
+ if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
+ {
+ ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
+ goto out;
+ }
+ }
- /* At this point, we can start the domain again if we're doign a
+ /* At this point, we can start the domain again if we're doing a
live suspend */
if( live )
{
-#if 1
if ( xc_shadow_control( xc_handle, domid,
DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
NULL, 0 ) < 0 )
@@ -242,16 +254,16 @@ int xc_linux_save(int xc_handle,
ERROR("Couldn't enable shadow mode");
goto out;
}
-#endif
+
if ( xc_domain_start( xc_handle, domid ) < 0 )
{
ERROR("Couldn't restart domain");
goto out;
}
-//exit(-1);
+
last_iter = 0;
sent_last_iter = 1<<20; // 4GB's worth of pages
- max_iters = 8; // limit us to 9 time round loop
+ max_iters = 9; // limit us to 10 time round loop
}
else
last_iter = 1;
@@ -297,7 +309,7 @@ int xc_linux_save(int xc_handle,
/*
* Quick belt and braces sanity check.
*/
-
+#if DEBUG
for ( i = 0; i < nr_pfns; i++ )
{
mfn = live_pfn_to_mfn_table[i];
@@ -306,17 +318,7 @@ int xc_linux_save(int xc_handle,
printf("i=0x%x mfn=%x live_mfn_to_pfn_table=%x\n",
i,mfn,live_mfn_to_pfn_table[mfn]);
}
-
- /* Canonicalise the pfn-to-mfn table frame-number list. */
- memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
- for ( i = 0; i < nr_pfns; i += 1024 )
- {
- if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
- {
- ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
- goto out;
- }
- }
+#endif
/* Map the shared info frame */
live_shinfo = mfn_mapper_map_single(xc_handle, domid,
@@ -374,28 +376,16 @@ int xc_linux_save(int xc_handle,
if( pfn_type[batch] == 0x80000004 )
{
- //printf("Skip netbuf pfn %lx. mfn %lx\n",n,pfn_type[batch]);
+ DPRINTF("Skip netbuf pfn %lx. mfn %lx\n",n,pfn_type[batch]);
continue;
}
-//if(iter>1) printf("pfn=%x mfn=%x\n",n,pfn_type[batch]);
+ if(iter>1) { DPRINTF("pfn=%x mfn=%x\n",n,pfn_type[batch]); }
batch++;
}
-
- for( j = 0; j < batch; j++ )
- {
-
- if( (pfn_type[j] &0xfffff) == 0x0000004 )
- {
- printf("XXXXXXXXSkip netbuf entry %d mfn %lx\n",j,pfn_type[j]);
- }
-
-
- }
-
- printf("batch %d:%d (n=%d)\n",iter,batch,n);
+ DPRINTF("batch %d:%d (n=%d)\n",iter,batch,n);
if(batch == 0) goto skip; // vanishingly unlikely...
@@ -418,10 +408,9 @@ int xc_linux_save(int xc_handle,
{
if((pfn_type[j]>>29) == 7)
{
- //printf("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
+ DPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
continue;
}
-//if((pfn_type[j] & PGT_type_mask) == L2TAB) printf("L2 pfn=%08lx mfn=%lx\n",pfn_type[j],live_mfn_to_pfn_table[pfn_type[j]&~PGT_type_mask]);
/* canonicalise mfn->pfn */
pfn_type[j] = (pfn_type[j] & PGT_type_mask) |
@@ -448,7 +437,7 @@ int xc_linux_save(int xc_handle,
if((pfn_type[j]>>29) == 7)
{
- //printf("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
+ DPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
continue;
}
@@ -471,26 +460,28 @@ int xc_linux_save(int xc_handle,
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
{
+ // I don't think this should ever happen
+
printf("FNI %d : [%08lx,%d] pte=%08lx, mfn=%08lx, pfn=%08lx [mfn]=%08lx\n",
j, pfn_type[j], k,
page[k], mfn, live_mfn_to_pfn_table[mfn],
(live_mfn_to_pfn_table[mfn]<nr_pfns)?
- live_pfn_to_mfn_table[live_mfn_to_pfn_table[mfn]]: 0xdeadbeef);
- pfn = 0; // be suspicious
+ live_pfn_to_mfn_table[live_mfn_to_pfn_table[mfn]]: 0xdeadbeef);
+
+ pfn = 0; // be suspicious, very suspicious
-// ERROR("Frame number in pagetable page is invalid");
-// goto out;
+ //goto out; // let's try our luck
}
page[k] &= PAGE_SIZE - 1;
page[k] |= pfn << PAGE_SHIFT;
- /*
- printf("L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx xpfn=%d\n",
- pfn_type[j]>>29,
- j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
- */
+#if DEBUG
+ printf("L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx xpfn=%d\n",
+ pfn_type[j]>>29,
+ j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
+#endif
} /* end of page table rewrite for loop */
@@ -526,11 +517,8 @@ int xc_linux_save(int xc_handle,
if ( live )
{
- if ( sent_this_iter < (sent_last_iter * 0.95) && iter < max_iters )
- {
- // we seem to be doing OK, keep going
- }
- else
+ if ( ( sent_this_iter > (sent_last_iter * 0.95) ) ||
+ (iter >= max_iters) || (sent_this_iter < 10) )
{
printf("Start last iteration\n");
last_iter = 1;
@@ -547,17 +535,13 @@ int xc_linux_save(int xc_handle,
goto out;
}
-#if 0
- if(last_iter) memset(to_send, 0xff, (nr_pfns+7)/8 );
-#endif
-
sent_last_iter = sent_this_iter;
}
} /* end of while 1 */
-printf("All memory is saved\n");
+ DPRINTF("All memory is saved\n");
/* Success! */
rc = 0;
@@ -579,14 +563,14 @@ printf("All memory is saved\n");
PERROR("Could not get info on domain");
goto out;
}
-printf("A\n");
+
/* Canonicalise the suspend-record frame number. */
if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) )
{
ERROR("State record is not in range of pseudophys map");
goto out;
}
-printf("B\n");
+
/* Canonicalise each GDT frame number. */
for ( i = 0; i < ctxt.gdt_ents; i += 512 )
{
@@ -596,7 +580,7 @@ printf("B\n");
goto out;
}
}
-printf("C\n");
+
/* Canonicalise the page table base pointer. */
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
{
@@ -604,7 +588,7 @@ printf("C\n");
goto out;
}
ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
-printf("D\n");
+
if ( (*writerfn)(writerst, &ctxt, sizeof(ctxt)) ||
(*writerfn)(writerst, live_shinfo, PAGE_SIZE) )
{
@@ -612,7 +596,7 @@ printf("D\n");
goto out;
}
munmap(live_shinfo, PAGE_SIZE);
-printf("E\n");
+
out:
/* Restart the domain if we had to stop it to save its state. */
if ( we_stopped_it )
diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c
index 47931f28ec..41eb2e744a 100644
--- a/tools/xc/lib/xc_private.c
+++ b/tools/xc/lib/xc_private.c
@@ -379,19 +379,24 @@ int finish_mmu_updates(int xc_handle, mmu_t *mmu)
int xc_domain_stop_sync( int xc_handle, domid_t domid )
{
dom0_op_t op;
+ int i;
+
- while (1)
+ op.cmd = DOM0_STOPDOMAIN;
+ op.u.stopdomain.domain = (domid_t)domid;
+ if ( do_dom0_op(xc_handle, &op) != 0 )
{
- 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;
- }
+ PERROR("Stopping target domain failed");
+ goto out;
+ }
+
+ usleep(100); // 100us
- usleep(1000); // 1ms
- printf("Sleep for 1ms\n");
+ 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;
@@ -405,10 +410,11 @@ int xc_domain_stop_sync( int xc_handle, domid_t domid )
if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
{
- printf("Domain %lld stopped\n",domid);
+ printf("\nDomain %lld stopped\n",domid);
return 0;
}
-
+
+ usleep(1000);
}
out:
diff --git a/tools/xc/py/Xc.c b/tools/xc/py/Xc.c
index 3b3081e262..b2ae143eda 100644
--- a/tools/xc/py/Xc.c
+++ b/tools/xc/py/Xc.c
@@ -191,7 +191,7 @@ static PyObject *pyxc_linux_save(PyObject *self,
u64 dom;
char *state_file;
- int progress = 1, live = 0;
+ int progress = 1, live = -1;
unsigned int flags = 0;
static char *kwd_list[] = { "dom", "state_file", "progress", "live", NULL };
@@ -200,8 +200,8 @@ static PyObject *pyxc_linux_save(PyObject *self,
&dom, &state_file, &progress, &live) )
return NULL;
- if (progress) flags |= XCFLAGS_VERBOSE;
- if (live) flags |= XCFLAGS_LIVE;
+ if (progress) flags |= XCFLAGS_VERBOSE;
+ if (live == 1) flags |= XCFLAGS_LIVE;
if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 )
{
@@ -226,6 +226,8 @@ static PyObject *pyxc_linux_save(PyObject *self,
return 0;
}
+ if (live == -1) flags |= XCFLAGS_LIVE; // default to live for tcp
+
strncpy( server, state_file+strlen("tcp://"), max_namelen);
server[max_namelen-1]='\0';
if ( (port_s = strchr(server,':')) != NULL )