diff options
author | iap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk> | 2004-05-04 16:24:42 +0000 |
---|---|---|
committer | iap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk> | 2004-05-04 16:24:42 +0000 |
commit | 19c472bc9f66da83cbadbd3d14be99007b013035 (patch) | |
tree | 65a64082bf07fd8d09a9c239f1a33af68d0e7f03 /tools/xc/lib/xc_linux_restore.c | |
parent | 0720bf34a431e000c7e02d5f7f55c2374637fceb (diff) | |
parent | 7b2eb5ed360b124204f8a216bd1c0e3b6f04eaba (diff) | |
download | xen-19c472bc9f66da83cbadbd3d14be99007b013035.tar.gz xen-19c472bc9f66da83cbadbd3d14be99007b013035.tar.bz2 xen-19c472bc9f66da83cbadbd3d14be99007b013035.zip |
bitkeeper revision 1.889 (4097c3catd8FeHBrQzC16T5v8TLJKg)
Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xeno.bk
Diffstat (limited to 'tools/xc/lib/xc_linux_restore.c')
-rw-r--r-- | tools/xc/lib/xc_linux_restore.c | 86 |
1 files changed, 44 insertions, 42 deletions
diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c index e27221281a..65ba875aef 100644 --- a/tools/xc/lib/xc_linux_restore.c +++ b/tools/xc/lib/xc_linux_restore.c @@ -45,25 +45,20 @@ static int get_pfn_list(int xc_handle, return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; } -static int checked_read(gzFile fd, void *buf, size_t count) -{ - int rc; - while ( ((rc = gzread(fd, buf, count)) == -1) && (errno == EINTR) ) - continue; - return rc == count; -} int xc_linux_restore(int xc_handle, u64 dom, - const char *state_file, - int verbose, + unsigned int flags, + int (*readerfn)(void *, void *, size_t), + void *readerst, u64 *pdomid) { dom0_op_t op; int rc = 1, i, j, n, k; unsigned long mfn, pfn, xpfn; unsigned int prev_pc, this_pc; - + int verbose = flags & XCFLAGS_VERBOSE; + /* Number of page frames in use by this Linux session. */ unsigned long nr_pfns; @@ -98,26 +93,10 @@ int xc_linux_restore(int xc_handle, mfn_mapper_t *region_mapper, *mapper_handle1; char *region_base; - /* The name and descriptor of the file that we are reading from. */ - int fd; - gzFile gfd; - mmu_t *mmu = NULL; int pm_handle = -1; - if ( (fd = open(state_file, O_RDONLY)) == -1 ) - { - PERROR("Could not open state file for reading"); - return 1; - } - - if ( (gfd = gzdopen(fd, "rb")) == NULL ) - { - ERROR("Could not allocate decompression state for state file"); - close(fd); - return 1; - } if ( mlock(&ctxt, sizeof(ctxt) ) ) { @@ -128,18 +107,18 @@ int xc_linux_restore(int xc_handle, } /* Start writing out the saved-domain record. */ - if ( !checked_read(gfd, signature, 16) || + if ( (*readerfn)(readerst, signature, 16) || (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) { ERROR("Unrecognised state format -- no signature found"); goto out; } - if ( !checked_read(gfd, name, sizeof(name)) || - !checked_read(gfd, &nr_pfns, sizeof(unsigned long)) || - !checked_read(gfd, &ctxt, sizeof(ctxt)) || - !checked_read(gfd, shared_info, PAGE_SIZE) || - !checked_read(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ) + if ( (*readerfn)(readerst, name, sizeof(name)) || + (*readerfn)(readerst, &nr_pfns, sizeof(unsigned long)) || + (*readerfn)(readerst, &ctxt, sizeof(ctxt)) || + (*readerfn)(readerst, shared_info, PAGE_SIZE) || + (*readerfn)(readerst, pfn_to_mfn_frame_list, PAGE_SIZE) ) { ERROR("Error when reading from state file"); goto out; @@ -250,7 +229,7 @@ int xc_linux_restore(int xc_handle, prev_pc = this_pc; } - if ( !checked_read(gfd, &j, sizeof(int)) ) + if ( (*readerfn)(readerst, &j, sizeof(int)) ) { ERROR("Error when reading from state file"); goto out; @@ -260,7 +239,7 @@ int xc_linux_restore(int xc_handle, if(j==0) break; // our work here is done - if ( !checked_read(gfd, region_pfn_type, j*sizeof(unsigned long)) ) + if ( (*readerfn)(readerst, region_pfn_type, j*sizeof(unsigned long)) ) { ERROR("Error when reading from state file"); goto out; @@ -306,21 +285,31 @@ int xc_linux_restore(int xc_handle, ppage = (unsigned long*) (region_base + i*PAGE_SIZE); - if ( !checked_read(gfd, ppage, PAGE_SIZE) ) + if ( (*readerfn)(readerst, ppage, PAGE_SIZE) ) { ERROR("Error when reading from state file"); goto out; } - if ( region_pfn_type[i] == L1TAB ) + switch( region_pfn_type[i] ) + { + case 0: + break; + + case L1TAB: { for ( k = 0; k < 1024; k++ ) { if ( ppage[k] & _PAGE_PRESENT ) { - if ( (xpfn = ppage[k] >> PAGE_SHIFT) >= nr_pfns ) + 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=%d nr_pfns=%d",region_pfn_type[i],i,k,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); goto out; } #if 0 @@ -335,15 +324,23 @@ int xc_linux_restore(int xc_handle, } } } - else if ( region_pfn_type[i] == L2TAB ) + break; + + case L2TAB: { for ( k = 0; k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); k++ ) { if ( ppage[k] & _PAGE_PRESENT ) { - if ( (xpfn = ppage[k] >> PAGE_SHIFT) >= nr_pfns ) + 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 page table is out of range"); + 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); + goto out; } #if 0 @@ -358,6 +355,12 @@ int xc_linux_restore(int xc_handle, } } } + break; + + default: + ERROR("Bogus page type %x page table is out of range. i=%d nr_pfns=%d",region_pfn_type[i],i,nr_pfns); + goto out; + } if ( add_mmu_update(xc_handle, mmu, (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) ) @@ -545,7 +548,6 @@ int xc_linux_restore(int xc_handle, if ( pfn_type != NULL ) free(pfn_type); - gzclose(gfd); if ( rc == 0 ) *pdomid = dom; |