aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_linux_restore.c
diff options
context:
space:
mode:
authorHollis Blanchard <hollisb@us.ibm.com>2006-11-29 14:16:36 -0600
committerHollis Blanchard <hollisb@us.ibm.com>2006-11-29 14:16:36 -0600
commitab26a6a563a0acb589af87a8e063c0e171d75665 (patch)
tree71a432bde5d016e928ab3ad7860fca01312ec787 /tools/libxc/xc_linux_restore.c
parentd3be8a6ca1aa9312cc01e780a2fea56ab8ec12b4 (diff)
parent1c804664cf63f0c2e80d0420e52d5f82c3956685 (diff)
downloadxen-ab26a6a563a0acb589af87a8e063c0e171d75665.tar.gz
xen-ab26a6a563a0acb589af87a8e063c0e171d75665.tar.bz2
xen-ab26a6a563a0acb589af87a8e063c0e171d75665.zip
Merge with xen-unstable.hg.
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
Diffstat (limited to 'tools/libxc/xc_linux_restore.c')
-rw-r--r--tools/libxc/xc_linux_restore.c145
1 files changed, 54 insertions, 91 deletions
diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c
index 6243701911..1d28226bd6 100644
--- a/tools/libxc/xc_linux_restore.c
+++ b/tools/libxc/xc_linux_restore.c
@@ -57,7 +57,7 @@ read_exact(int fd, void *buf, size_t count)
** This function inverts that operation, replacing the pfn values with
** the (now known) appropriate mfn values.
*/
-int uncanonicalize_pagetable(unsigned long type, void *page)
+static int uncanonicalize_pagetable(unsigned long type, void *page)
{
int i, pte_last;
unsigned long pfn;
@@ -79,7 +79,7 @@ int uncanonicalize_pagetable(unsigned long type, void *page)
if(pfn >= max_pfn) {
/* This "page table page" is probably not one; bail. */
- ERR("Frame number in type %lu page table is out of range: "
+ ERROR("Frame number in type %lu page table is out of range: "
"i=%d pfn=0x%lx max_pfn=%lu",
type >> 28, i, pfn, max_pfn);
return 0;
@@ -158,24 +158,24 @@ int xc_linux_restore(int xc_handle, int io_fd,
if(!get_platform_info(xc_handle, dom,
&max_mfn, &hvirt_start, &pt_levels)) {
- ERR("Unable to get platform info.");
+ ERROR("Unable to get platform info.");
return 1;
}
- if (mlock(&ctxt, sizeof(ctxt))) {
+ if (lock_pages(&ctxt, sizeof(ctxt))) {
/* needed for build domctl, but might as well do early */
- ERR("Unable to mlock ctxt");
+ ERROR("Unable to lock ctxt");
return 1;
}
if (!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
- ERR("Couldn't allocate p2m_frame_list array");
+ ERROR("Couldn't allocate p2m_frame_list array");
goto out;
}
/* Read first entry of P2M list, or extended-info signature (~0UL). */
if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
- ERR("read extended-info signature failed");
+ ERROR("read extended-info signature failed");
goto out;
}
@@ -184,7 +184,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Next 4 bytes: total size of following extended info. */
if (!read_exact(io_fd, &tot_bytes, sizeof(tot_bytes))) {
- ERR("read extended-info size failed");
+ ERROR("read extended-info size failed");
goto out;
}
@@ -195,7 +195,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* 4-character chunk signature + 4-byte remaining chunk size. */
if (!read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) ||
!read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes))) {
- ERR("read extended-info chunk signature failed");
+ ERROR("read extended-info chunk signature failed");
goto out;
}
tot_bytes -= 8;
@@ -203,7 +203,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* VCPU context structure? */
if (!strncmp(chunk_sig, "vcpu", 4)) {
if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
- ERR("read extended-info vcpu context failed");
+ ERROR("read extended-info vcpu context failed");
goto out;
}
tot_bytes -= sizeof(struct vcpu_guest_context);
@@ -219,7 +219,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if ( sz > P2M_FL_SIZE )
sz = P2M_FL_SIZE;
if (!read_exact(io_fd, p2m_frame_list, sz)) {
- ERR("read-and-discard extended-info chunk bytes failed");
+ ERROR("read-and-discard extended-info chunk bytes failed");
goto out;
}
chunk_bytes -= sz;
@@ -229,14 +229,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Now read the real first entry of P2M list. */
if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
- ERR("read first entry of p2m_frame_list failed");
+ ERROR("read first entry of p2m_frame_list failed");
goto out;
}
}
/* First entry is already read into the p2m array. */
if (!read_exact(io_fd, &p2m_frame_list[1], P2M_FL_SIZE - sizeof(long))) {
- ERR("read p2m_frame_list failed");
+ ERROR("read p2m_frame_list failed");
goto out;
}
@@ -246,13 +246,13 @@ int xc_linux_restore(int xc_handle, int io_fd,
region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
if ((p2m == NULL) || (pfn_type == NULL) || (region_mfn == NULL)) {
- ERR("memory alloc failed");
+ ERROR("memory alloc failed");
errno = ENOMEM;
goto out;
}
- if (mlock(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
- ERR("Could not mlock region_mfn");
+ if (lock_pages(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
+ ERROR("Could not lock region_mfn");
goto out;
}
@@ -260,37 +260,33 @@ int xc_linux_restore(int xc_handle, int io_fd,
domctl.cmd = XEN_DOMCTL_getdomaininfo;
domctl.domain = (domid_t)dom;
if (xc_domctl(xc_handle, &domctl) < 0) {
- ERR("Could not get information on new domain");
+ ERROR("Could not get information on new domain");
goto out;
}
shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
- if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) {
+ if (xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) {
errno = ENOMEM;
goto out;
}
- if(xc_domain_memory_increase_reservation(
- xc_handle, dom, max_pfn, 0, 0, NULL) != 0) {
- ERR("Failed to increase reservation by %lx KB", PFN_TO_KB(max_pfn));
+ for ( pfn = 0; pfn < max_pfn; pfn++ )
+ p2m[pfn] = pfn;
+
+ if (xc_domain_memory_populate_physmap(xc_handle, dom, max_pfn,
+ 0, 0, p2m) != 0) {
+ ERROR("Failed to increase reservation by %lx KB", PFN_TO_KB(max_pfn));
errno = ENOMEM;
goto out;
}
DPRINTF("Increased domain reservation by %lx KB\n", PFN_TO_KB(max_pfn));
- /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
- if (xc_get_pfn_list(xc_handle, dom, p2m, max_pfn) != max_pfn) {
- ERR("Did not read correct number of frame numbers for new dom");
- goto out;
- }
-
if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
- ERR("Could not initialise for MMU updates");
+ ERROR("Could not initialise for MMU updates");
goto out;
}
-
DPRINTF("Reloading memory pages: 0%%\n");
/*
@@ -312,7 +308,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
}
if (!read_exact(io_fd, &j, sizeof(int))) {
- ERR("Error when reading batch size");
+ ERROR("Error when reading batch size");
goto out;
}
@@ -328,12 +324,12 @@ int xc_linux_restore(int xc_handle, int io_fd,
break; /* our work here is done */
if (j > MAX_BATCH_SIZE) {
- ERR("Max batch size exceeded. Giving up.");
+ ERROR("Max batch size exceeded. Giving up.");
goto out;
}
if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
- ERR("Error when reading region pfn types");
+ ERROR("Error when reading region pfn types");
goto out;
}
@@ -353,7 +349,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
xc_handle, dom, PROT_WRITE, region_mfn, j);
if ( region_base == NULL )
{
- ERR("map batch failed");
+ ERROR("map batch failed");
goto out;
}
@@ -371,7 +367,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if ( pfn > max_pfn )
{
- ERR("pfn out of range");
+ ERROR("pfn out of range");
goto out;
}
@@ -383,7 +379,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
if (!read_exact(io_fd, page, PAGE_SIZE)) {
- ERR("Error when reading page (type was %lx)", pagetype);
+ ERROR("Error when reading page (type was %lx)", pagetype);
goto out;
}
@@ -422,7 +418,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
}
else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB )
{
- ERR("Bogus page type %lx page table is out of range: "
+ ERROR("Bogus page type %lx page table is out of range: "
"i=%d max_pfn=%lu", pagetype, i, max_pfn);
goto out;
@@ -455,7 +451,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if (xc_add_mmu_update(xc_handle, mmu,
(((unsigned long long)mfn) << PAGE_SHIFT)
| MMU_MACHPHYS_UPDATE, pfn)) {
- ERR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
+ ERROR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
goto out;
}
} /* end of 'batch' for loop */
@@ -469,7 +465,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
* reallocations below.
*/
if (xc_finish_mmu_updates(xc_handle, mmu)) {
- ERR("Error doing finish_mmu_updates()");
+ ERROR("Error doing finish_mmu_updates()");
goto out;
}
@@ -512,7 +508,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
munmap(l3tab, PAGE_SIZE);
if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) {
- ERR("Couldn't get a page below 4GB :-(");
+ ERROR("Couldn't get a page below 4GB :-(");
goto out;
}
@@ -521,7 +517,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
(((unsigned long long)new_mfn)
<< PAGE_SHIFT) |
MMU_MACHPHYS_UPDATE, i)) {
- ERR("Couldn't m2p on PAE root pgdir");
+ ERROR("Couldn't m2p on PAE root pgdir");
goto out;
}
@@ -554,14 +550,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
if (!(region_base = xc_map_foreign_batch(
xc_handle, dom, PROT_READ | PROT_WRITE,
region_mfn, j))) {
- ERR("map batch failed");
+ ERROR("map batch failed");
goto out;
}
for(k = 0; k < j; k++) {
if(!uncanonicalize_pagetable(XEN_DOMCTL_PFINFO_L1TAB,
region_base + k*PAGE_SIZE)) {
- ERR("failed uncanonicalize pt!");
+ ERROR("failed uncanonicalize pt!");
goto out;
}
}
@@ -572,7 +568,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
}
if (xc_finish_mmu_updates(xc_handle, mmu)) {
- ERR("Error doing finish_mmu_updates()");
+ ERROR("Error doing finish_mmu_updates()");
goto out;
}
}
@@ -615,7 +611,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Batch full? Then flush. */
if (nr_pins == MAX_PIN_BATCH) {
if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) {
- ERR("Failed to pin batch of %d page tables", nr_pins);
+ ERROR("Failed to pin batch of %d page tables", nr_pins);
goto out;
}
nr_pins = 0;
@@ -624,7 +620,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Flush final partial batch. */
if ((nr_pins != 0) && (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0)) {
- ERR("Failed to pin batch of %d page tables", nr_pins);
+ ERROR("Failed to pin batch of %d page tables", nr_pins);
goto out;
}
@@ -638,17 +634,17 @@ int xc_linux_restore(int xc_handle, int io_fd,
int rc;
if (!read_exact(io_fd, &count, sizeof(count))) {
- ERR("Error when reading pfn count");
+ ERROR("Error when reading pfn count");
goto out;
}
if(!(pfntab = malloc(sizeof(unsigned long) * count))) {
- ERR("Out of memory");
+ ERROR("Out of memory");
goto out;
}
if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
- ERR("Error when reading pfntab");
+ ERROR("Error when reading pfntab");
goto out;
}
@@ -675,7 +671,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
&reservation)) != count) {
- ERR("Could not decrease reservation : %d", rc);
+ ERROR("Could not decrease reservation : %d", rc);
goto out;
} else
DPRINTF("Decreased reservation by %d pages\n", count);
@@ -684,14 +680,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
if (!read_exact(io_fd, &ctxt, sizeof(ctxt)) ||
!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
- ERR("Error when reading ctxt or shared info page");
+ ERROR("Error when reading ctxt or shared info page");
goto out;
}
/* Uncanonicalise the suspend-record frame number and poke resume rec. */
pfn = ctxt.user_regs.edx;
if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
- ERR("Suspend record frame number is bad");
+ ERROR("Suspend record frame number is bad");
goto out;
}
ctxt.user_regs.edx = mfn = p2m[pfn];
@@ -709,14 +705,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Uncanonicalise each GDT frame number. */
if (ctxt.gdt_ents > 8192) {
- ERR("GDT entry count out of range");
+ ERROR("GDT entry count out of range");
goto out;
}
for (i = 0; i < ctxt.gdt_ents; i += 512) {
pfn = ctxt.gdt_frames[i];
if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
- ERR("GDT frame number is bad");
+ ERROR("GDT frame number is bad");
goto out;
}
ctxt.gdt_frames[i] = p2m[pfn];
@@ -726,14 +722,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
if (pfn >= max_pfn) {
- ERR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx",
+ ERROR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx",
pfn, max_pfn, pfn_type[pfn]);
goto out;
}
if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
- ERR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
+ ERROR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
pfn, max_pfn, pfn_type[pfn],
(unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
@@ -757,7 +753,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
for (i = 0; i < P2M_FL_ENTRIES; i++) {
pfn = p2m_frame_list[i];
if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
- ERR("PFN-to-MFN frame number is bad");
+ ERROR("PFN-to-MFN frame number is bad");
goto out;
}
@@ -767,46 +763,13 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Copy the P2M we've constructed to the 'live' P2M */
if (!(live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
p2m_frame_list, P2M_FL_ENTRIES))) {
- ERR("Couldn't map p2m table");
+ ERROR("Couldn't map p2m table");
goto out;
}
memcpy(live_p2m, p2m, P2M_SIZE);
munmap(live_p2m, P2M_SIZE);
- /*
- * Safety checking of saved context:
- * 1. user_regs is fine, as Xen checks that on context switch.
- * 2. fpu_ctxt is fine, as it can't hurt Xen.
- * 3. trap_ctxt needs the code selectors checked.
- * 4. ldt base must be page-aligned, no more than 8192 ents, ...
- * 5. gdt already done, and further checking is done by Xen.
- * 6. check that kernel_ss is safe.
- * 7. pt_base is already done.
- * 8. debugregs are checked by Xen.
- * 9. callback code selectors need checking.
- */
- for ( i = 0; i < 256; i++ ) {
- ctxt.trap_ctxt[i].vector = i;
- if ((ctxt.trap_ctxt[i].cs & 3) == 0)
- ctxt.trap_ctxt[i].cs = FLAT_KERNEL_CS;
- }
- if ((ctxt.kernel_ss & 3) == 0)
- ctxt.kernel_ss = FLAT_KERNEL_DS;
-#if defined(__i386__)
- if ((ctxt.event_callback_cs & 3) == 0)
- ctxt.event_callback_cs = FLAT_KERNEL_CS;
- if ((ctxt.failsafe_callback_cs & 3) == 0)
- ctxt.failsafe_callback_cs = FLAT_KERNEL_CS;
-#endif
- if (((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
- (ctxt.ldt_ents > 8192) ||
- (ctxt.ldt_base > hvirt_start) ||
- ((ctxt.ldt_base + ctxt.ldt_ents*8) > hvirt_start)) {
- ERR("Bad LDT base or size");
- goto out;
- }
-
DPRINTF("Domain ready to be built.\n");
domctl.cmd = XEN_DOMCTL_setvcpucontext;
@@ -816,7 +779,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
rc = xc_domctl(xc_handle, &domctl);
if (rc != 0) {
- ERR("Couldn't build the domain");
+ ERROR("Couldn't build the domain");
goto out;
}