diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/xc/lib/xc_linux_restore.c | 41 | ||||
-rw-r--r-- | tools/xc/lib/xc_linux_save.c | 114 | ||||
-rw-r--r-- | tools/xc/lib/xc_private.c | 30 | ||||
-rw-r--r-- | tools/xc/py/Xc.c | 8 |
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 ) |