From: iap10@labyrinth.cl.cam.ac.uk Date: Sat, 1 May 2004 22:14:05 +0000 (+0000) Subject: bitkeeper revision 1.883 (4094212dXJnedPkykZkVt9oqyUah3w) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~18238 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=c96334de98b3b468ef9ab9efa5d5d991fc56368d;p=xen.git bitkeeper revision 1.883 (4094212dXJnedPkykZkVt9oqyUah3w) move full execution context out-of-line from dom0_op_t. further changes to save/restore. --- diff --git a/tools/xc/lib/xc_domain.c b/tools/xc/lib/xc_domain.c index ec28f2686b..1d77bfc016 100644 --- a/tools/xc/lib/xc_domain.c +++ b/tools/xc/lib/xc_domain.c @@ -84,6 +84,7 @@ int xc_domain_getinfo(int xc_handle, { op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)next_domid; + op.u.getdomaininfo.ctxt = NULL; // no exec context info, thanks. if ( do_dom0_op(xc_handle, &op) < 0 ) break; info->domid = (u64)op.u.getdomaininfo.domain; diff --git a/tools/xc/lib/xc_linux_build.c b/tools/xc/lib/xc_linux_build.c index 7f81c924ad..42696666a8 100644 --- a/tools/xc/lib/xc_linux_build.c +++ b/tools/xc/lib/xc_linux_build.c @@ -26,6 +26,7 @@ static long get_tot_pages(int xc_handle, u64 domid) dom0_op_t op; op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)domid; + op.u.getdomaininfo.ctxt = NULL; return (do_dom0_op(xc_handle, &op) < 0) ? -1 : op.u.getdomaininfo.tot_pages; } @@ -70,7 +71,7 @@ static int setup_guestos(int xc_handle, gzFile initrd_gfd, unsigned long initrd_len, unsigned long nr_pages, unsigned long *pvsi, unsigned long *pvke, - dom0_builddomain_t *builddomain, + full_execution_context_t *ctxt, const char *cmdline, unsigned long shared_info_frame, unsigned int control_evtchn) @@ -163,8 +164,6 @@ static int setup_guestos(int xc_handle, v_start, v_end); printf(" ENTRY ADDRESS: %08lx\n", vkern_entry); - memset(builddomain, 0, sizeof(*builddomain)); - if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 ) goto error_out; @@ -205,7 +204,7 @@ static int setup_guestos(int xc_handle, /* First allocate page for page dir. */ ppt_alloc = (vpt_start - v_start) >> PAGE_SHIFT; l2tab = page_array[ppt_alloc++] << PAGE_SHIFT; - builddomain->ctxt.pt_base = l2tab; + ctxt->pt_base = l2tab; /* Initialise the page tables. */ if ( (vl2tab = map_pfn_writeable(pm_handle, l2tab >> PAGE_SHIFT)) == NULL ) @@ -388,7 +387,7 @@ int xc_linux_build(int xc_handle, int initrd_fd = -1; gzFile initrd_gfd = NULL; int rc, i; - full_execution_context_t *ctxt; + full_execution_context_t st_ctxt, *ctxt = &st_ctxt; unsigned long nr_pages; char *image = NULL; unsigned long image_size, initrd_size=0; @@ -420,8 +419,15 @@ int xc_linux_build(int xc_handle, } } + if ( mlock(&st_ctxt, sizeof(st_ctxt) ) ) + { + PERROR("Unable to mlock ctxt"); + return 1; + } + 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) ) { @@ -429,7 +435,7 @@ int xc_linux_build(int xc_handle, goto error_out; } if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) || - (op.u.getdomaininfo.ctxt.pt_base != 0) ) + (ctxt->pt_base != 0) ) { ERROR("Domain is already constructed"); goto error_out; @@ -438,7 +444,7 @@ int xc_linux_build(int xc_handle, if ( setup_guestos(xc_handle, domid, image, image_size, initrd_gfd, initrd_size, nr_pages, &vstartinfo_start, &vkern_entry, - &launch_op.u.builddomain, cmdline, + ctxt, cmdline, op.u.getdomaininfo.shared_info_frame, control_evtchn) < 0 ) { @@ -453,8 +459,6 @@ int xc_linux_build(int xc_handle, if ( image != NULL ) free(image); - ctxt = &launch_op.u.builddomain.ctxt; - ctxt->flags = 0; /* @@ -507,8 +511,11 @@ int xc_linux_build(int xc_handle, ctxt->failsafe_callback_cs = FLAT_GUESTOS_CS; ctxt->failsafe_callback_eip = 0; + memset( &launch_op, 0, sizeof(launch_op) ); + launch_op.u.builddomain.domain = (domid_t)domid; launch_op.u.builddomain.num_vifs = 1; + launch_op.u.builddomain.ctxt = ctxt; launch_op.cmd = DOM0_BUILDDOMAIN; rc = do_dom0_op(xc_handle, &launch_op); diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c index 893cd0cef4..00acc5a687 100644 --- a/tools/xc/lib/xc_linux_restore.c +++ b/tools/xc/lib/xc_linux_restore.c @@ -58,8 +58,8 @@ int xc_linux_restore(int xc_handle, u64 *pdomid) { dom0_op_t op; - int rc = 1, i, j; - unsigned long mfn, pfn; + int rc = 1, i, j, n, k; + unsigned long mfn, pfn, xpfn; unsigned int prev_pc, this_pc; /* Number of page frames in use by this Linux session. */ @@ -114,6 +114,14 @@ int xc_linux_restore(int xc_handle, return 1; } + if ( mlock(&ctxt, sizeof(ctxt) ) ) + { + /* needed for when we do the build dom0 op, + but might as well do early */ + PERROR("Unable to mlock ctxt"); + return 1; + } + /* Start writing out the saved-domain record. */ if ( !checked_read(gfd, signature, 16) || (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) @@ -159,12 +167,6 @@ int xc_linux_restore(int xc_handle, goto out; } - if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) ) - { - ERROR("Error when reading from state file"); - goto out; - } - /* Set the domain's name to that from the restore file */ if ( xc_domain_setname( xc_handle, dom, name ) ) { @@ -184,6 +186,7 @@ int xc_linux_restore(int xc_handle, /* Get the domain's shared-info frame. */ op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)dom; + op.u.getdomaininfo.ctxt = NULL; if ( do_dom0_op(xc_handle, &op) < 0 ) { ERROR("Could not get information on new domain"); @@ -219,73 +222,119 @@ int xc_linux_restore(int xc_handle, * We uncanonicalise page tables as we go. */ prev_pc = 0; - for ( i = 0; i < nr_pfns; i++ ) + + n=0; + while(1) { - this_pc = (i * 100) / nr_pfns; + int j; + unsigned long region_pfn_type[1024]; + + this_pc = (n * 100) / nr_pfns; if ( (this_pc - prev_pc) >= 5 ) { verbose_printf("\b\b\b\b%3d%%", this_pc); prev_pc = this_pc; } - mfn = pfn_to_mfn_table[i]; - - ppage = map_pfn_writeable(pm_handle, mfn); - - if ( !checked_read(gfd, ppage, PAGE_SIZE) ) + if ( !checked_read(gfd, &j, sizeof(int)) ) { ERROR("Error when reading from state file"); goto out; } - if ( pfn_type[i] == L1TAB ) - { - for ( j = 0; j < 1024; j++ ) - { - if ( ppage[j] & _PAGE_PRESENT ) - { - if ( (pfn = ppage[j] >> PAGE_SHIFT) >= nr_pfns ) - { - ERROR("Frame number in type %d page table is out of range. i=%d j=%d pfn=%d nr_pfns=%d",pfn_type[i],i,j,pfn,nr_pfns); - goto out; - } - if ( (pfn_type[pfn] != NONE) && (ppage[j] & _PAGE_RW) ) - { - ERROR("Write access requested for a restricted frame"); - goto out; - } - ppage[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT); - ppage[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT; - } - } - } - else if ( pfn_type[i] == L2TAB ) + printf("batch=%d\n",j); + + if(j==0) break; // our work here is done + + if ( !checked_read(gfd, region_pfn_type, j*sizeof(unsigned long)) ) { - for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ ) - { - if ( ppage[j] & _PAGE_PRESENT ) - { - if ( (pfn = ppage[j] >> PAGE_SHIFT) >= nr_pfns ) - { - ERROR("Frame number in page table is out of range"); - goto out; - } - if ( pfn_type[pfn] != L1TAB ) - { - ERROR("Page table mistyping"); - goto out; - } - ppage[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE); - ppage[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT; - } - } + ERROR("Error when reading from state file"); + goto out; } - unmap_pfn(pm_handle, ppage); + for(i=0;inr_pfns) + { + ERROR("pfn out of range"); + goto out; + } + + region_pfn_type[i] &= PGT_type_mask; + + pfn_type[pfn] = region_pfn_type[i]; + + 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 = map_pfn_writeable(pm_handle, mfn); + + if ( !checked_read(gfd, ppage, PAGE_SIZE) ) + { + ERROR("Error when reading from state file"); + goto out; + } + + if ( region_pfn_type[i] == L1TAB ) + { + for ( k = 0; k < 1024; k++ ) + { + if ( ppage[k] & _PAGE_PRESENT ) + { + if ( (xpfn = ppage[k] >> PAGE_SHIFT) >= 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); + 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; + } + } + } + else if ( region_pfn_type[i] == 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 ) + { + ERROR("Frame number in page table is out of range"); + goto out; + } +#if 0 + if ( region_pfn_type[pfn] != L1TAB ) + { + ERROR("Page table mistyping"); + goto out; + } +#endif + ppage[k] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE); + ppage[k] |= pfn_to_mfn_table[xpfn] << PAGE_SHIFT; + } + } + } + + unmap_pfn(pm_handle, ppage); + + if ( add_mmu_update(xc_handle, mmu, + (mfn<> PAGE_SHIFT; if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) { - ERROR("PT base is bad"); + printf("PT base is bad. pfn=%d nr=%d type=%08lx %08lx\n", + pfn, nr_pfns, pfn_type[pfn], L2TAB); + ERROR("PT base is bad."); goto out; } ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT; @@ -406,11 +457,11 @@ int xc_linux_restore(int xc_handle, ERROR("Bad LDT base or size"); goto out; } - + op.cmd = DOM0_BUILDDOMAIN; op.u.builddomain.domain = (domid_t)dom; op.u.builddomain.num_vifs = 1; - memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt)); + op.u.builddomain.ctxt = &ctxt; rc = do_dom0_op(xc_handle, &op); out: diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c index fb6fbd6f57..88ed9e15d7 100644 --- a/tools/xc/lib/xc_linux_save.c +++ b/tools/xc/lib/xc_linux_save.c @@ -10,7 +10,7 @@ #include #include -#define BATCH_SIZE 512 /* 1024 pages (4MB) at a time */ +#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */ /* This may allow us to create a 'quiet' command-line option, if necessary. */ #define verbose_printf(_f, _a...) \ @@ -122,11 +122,18 @@ int xc_linux_save(int xc_handle, return 1; } + if ( mlock(&ctxt, sizeof(ctxt) ) ) + { + PERROR("Unable to mlock ctxt"); + return 1; + } + /* 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) ) { @@ -134,7 +141,6 @@ int xc_linux_save(int xc_handle, goto out; } - memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt)); memcpy(name, op.u.getdomaininfo.name, sizeof(name)); shared_info_frame = op.u.getdomaininfo.shared_info_frame; @@ -223,7 +229,7 @@ int xc_linux_save(int xc_handle, /* We want zeroed memory so use calloc rather than malloc. */ - pfn_type = calloc(1, 4 * srec.nr_pfns); + pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long)); if ( (pfn_type == NULL) ) { @@ -231,6 +237,11 @@ int xc_linux_save(int xc_handle, goto out; } + if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ) + { + ERROR("Unable to mlock"); + goto out; + } /* Track the mfn_to_pfn table down from the domains PT */ @@ -238,26 +249,22 @@ int xc_linux_save(int xc_handle, unsigned long *pgd; unsigned long mfn_to_pfn_table_start_mfn; - pgd = mfn_mapper_map_single(xc_handle, domid, + pgd = mfn_mapper_map_single(xc_handle, domid, PAGE_SIZE, PROT_READ, ctxt.pt_base>>PAGE_SHIFT); -/* - printf("pt mfn=%d pfn=%d type=%08x pte=%08x\n",ctxt.pt_base>>PAGE_SHIFT, - mfn_to_pfn_table[ctxt.pt_base>>PAGE_SHIFT], - pfn_type[mfn_to_pfn_table[ctxt.pt_base>>PAGE_SHIFT]], - pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT] ); -*/ - mfn_to_pfn_table_start_mfn = pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT]>>PAGE_SHIFT; - - live_mfn_to_pfn_table = - mfn_mapper_map_single(xc_handle, ~0ULL, - PAGE_SIZE*1024, PROT_READ, - mfn_to_pfn_table_start_mfn ); + + mfn_to_pfn_table_start_mfn = + pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT]>>PAGE_SHIFT; + + live_mfn_to_pfn_table = + mfn_mapper_map_single(xc_handle, ~0ULL, + PAGE_SIZE*1024, PROT_READ, + mfn_to_pfn_table_start_mfn ); } /* - * Quick sanity check. + * Quick belt and braces sanity check. */ for ( i = 0; i < srec.nr_pfns; i++ ) @@ -270,50 +277,6 @@ int xc_linux_save(int xc_handle, } -/* test new pfn_type stuff */ - { - int n, i, j; - - if ( mlock( pfn_type, srec.nr_pfns * sizeof(unsigned long) ) ) - { - ERROR("Unable to mlock"); - goto out; - } - for ( n = 0; n < srec.nr_pfns; ) - { - - for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) - { - pfn_type[i] = live_pfn_to_mfn_table[i]; - } - - if ( get_pfn_type_batch(xc_handle, domid, j, &pfn_type[n]) ) - { - ERROR("get_pfn_type_batch failed"); - goto out; - } - - for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) - { - - pfn_type[i] >>= 29; - - if(pfn_type[i] == 7) - { - ERROR("bogus page"); - goto out; - } - -/* if(pfn_type[i]) - printf("i=%d type=%d\n",i,pfn_type[i]); */ - } - - n+=j; - } - } - - - /* Canonicalise the suspend-record frame number. */ if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ) { @@ -366,8 +329,7 @@ int xc_linux_save(int xc_handle, !checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) || !checked_write(gfd, &ctxt, sizeof(ctxt)) || !checked_write(gfd, live_shinfo, PAGE_SIZE) || - !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) || - !checked_write(gfd, pfn_type, 4 * srec.nr_pfns) ) + !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ) { ERROR("Error when writing to state file"); goto out; @@ -394,6 +356,11 @@ int xc_linux_save(int xc_handle, prev_pc = this_pc; } + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) + { + pfn_type[j] = live_pfn_to_mfn_table[i]; + } + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) { @@ -411,32 +378,54 @@ int xc_linux_save(int xc_handle, goto out; } -#if 0 - typer_handle = get_type_init( xc_handle, BATCH_SIZE ) - + if ( get_pfn_type_batch(xc_handle, domid, j, pfn_type) ) + { + ERROR("get_pfn_type_batch failed"); + goto out; + } + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) { - /* queue up ownership and type checks for all pages in batch */ + if((pfn_type[j]>>29) == 7) + { + ERROR("bogus page"); + goto out; + } - get_type_queue_entry( typer_handle, domain, - pfn_to_mfn_frame_list[i] ); + /* canonicalise mfn->pfn */ + pfn_type[j] = (pfn_type[j] & PGT_type_mask) | + live_mfn_to_pfn_table[pfn_type[j]&~PGT_type_mask]; + +/* if(pfn_type[j]>>29) + printf("i=%d type=%d\n",i,pfn_type[i]); */ } - region_type = get_type; -#endif + if ( !checked_write(gfd, &j, sizeof(int) ) ) + { + ERROR("Error when writing to state file"); + goto out; + } + + if ( !checked_write(gfd, pfn_type, sizeof(unsigned long)*j ) ) + { + ERROR("Error when writing to state file"); + goto out; + } + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) { /* write out pages in batch */ - if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) ) + if ( ((pfn_type[j] & PGT_type_mask) == L1TAB) || + ((pfn_type[j] & PGT_type_mask) == L2TAB) ) { memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE); for ( k = 0; - k < ((pfn_type[i] == L2TAB) ? + k < (((pfn_type[j] & PGT_type_mask) == L2TAB) ? (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); k++ ) { @@ -478,6 +467,14 @@ int xc_linux_save(int xc_handle, /* Success! */ rc = 0; + /* Zero terminate */ + if ( !checked_write(gfd, &rc, sizeof(int)) ) + { + ERROR("Error when writing to state file"); + goto out; + } + + 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_netbsd_build.c b/tools/xc/lib/xc_netbsd_build.c index 8793a512f2..7c67d57d71 100644 --- a/tools/xc/lib/xc_netbsd_build.c +++ b/tools/xc/lib/xc_netbsd_build.c @@ -27,6 +27,7 @@ static long get_tot_pages(int xc_handle, u64 domid) dom0_op_t op; op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)domid; + op.u.getdomaininfo.ctxt = NULL; return (do_dom0_op(xc_handle, &op) < 0) ? -1 : op.u.getdomaininfo.tot_pages; } @@ -59,7 +60,7 @@ static int setup_guestos(int xc_handle, unsigned long tot_pages, unsigned long *virt_startinfo_addr, unsigned long *virt_load_addr, - dom0_builddomain_t *builddomain, + full_execution_context_t *ctxt, const char *cmdline, unsigned long shared_info_frame, unsigned int control_evtchn) @@ -78,8 +79,6 @@ static int setup_guestos(int xc_handle, mmu_t *mmu = NULL; int pm_handle, i; - memset(builddomain, 0, sizeof(*builddomain)); - if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 ) goto error_out; @@ -119,7 +118,7 @@ static int setup_guestos(int xc_handle, */ l2tab = page_array[alloc_index] << PAGE_SHIFT; alloc_index--; - builddomain->ctxt.pt_base = l2tab; + ctxt->pt_base = l2tab; if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) goto error_out; @@ -221,7 +220,7 @@ int xc_netbsd_build(int xc_handle, int kernel_fd = -1; gzFile kernel_gfd = NULL; int rc, i; - full_execution_context_t *ctxt; + full_execution_context_t st_ctxt, *ctxt = &st_ctxt; unsigned long virt_startinfo_addr; if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 ) @@ -244,8 +243,15 @@ int xc_netbsd_build(int xc_handle, return 1; } + if ( mlock(&st_ctxt, sizeof(st_ctxt) ) ) + { + PERROR("Unable to mlock ctxt"); + return 1; + } + 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) ) { @@ -253,7 +259,7 @@ int xc_netbsd_build(int xc_handle, goto error_out; } if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) || - (op.u.getdomaininfo.ctxt.pt_base != 0) ) + (op.u.getdomaininfo.ctxt->pt_base != 0) ) { ERROR("Domain is already constructed"); goto error_out; @@ -261,7 +267,7 @@ int xc_netbsd_build(int xc_handle, if ( setup_guestos(xc_handle, domid, kernel_gfd, tot_pages, &virt_startinfo_addr, - &load_addr, &launch_op.u.builddomain, cmdline, + &load_addr, &st_ctxt, cmdline, op.u.getdomaininfo.shared_info_frame, control_evtchn) < 0 ) { @@ -274,8 +280,6 @@ int xc_netbsd_build(int xc_handle, if( kernel_gfd ) gzclose(kernel_gfd); - ctxt = &launch_op.u.builddomain.ctxt; - ctxt->flags = 0; /* @@ -328,9 +332,11 @@ int xc_netbsd_build(int xc_handle, ctxt->failsafe_callback_cs = FLAT_GUESTOS_CS; ctxt->failsafe_callback_eip = 0; + memset( &launch_op, 0, sizeof(launch_op) ); + launch_op.u.builddomain.domain = (domid_t)domid; launch_op.u.builddomain.num_vifs = 1; - + launch_op.u.builddomain.ctxt = ctxt; launch_op.cmd = DOM0_BUILDDOMAIN; rc = do_dom0_op(xc_handle, &launch_op); diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index ef0ab2e81b..67c26e303a 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -53,24 +53,19 @@ static void read_msr_for(void *unused) long do_dom0_op(dom0_op_t *u_dom0_op) { long ret = 0; - dom0_op_t *op; + dom0_op_t curop,*op=&curop; if ( !IS_PRIV(current) ) return -EPERM; - if ( (op = kmalloc(sizeof(*op), GFP_KERNEL)) == NULL ) - return -ENOMEM; - if ( copy_from_user(op, u_dom0_op, sizeof(*op)) ) { - ret = -EFAULT; - goto out; + return -EFAULT; } if ( op->interface_version != DOM0_INTERFACE_VERSION ) { - ret = -EACCES; - goto out; + return -EACCES; } switch ( op->cmd ) @@ -269,15 +264,17 @@ long do_dom0_op(dom0_op_t *u_dom0_op) for_each_domain ( p ) { if ( p->domain >= op->u.getdomaininfo.domain ) - break; + break; } if ( p == NULL ) { ret = -ESRCH; + goto gdi_out; } else { +printk("AAAA %p\n",op->u.getdomaininfo.ctxt); op->u.getdomaininfo.domain = p->domain; strcpy (op->u.getdomaininfo.name, p->name); op->u.getdomaininfo.processor = p->processor; @@ -291,59 +288,81 @@ long do_dom0_op(dom0_op_t *u_dom0_op) op->u.getdomaininfo.cpu_time = p->cpu_time; op->u.getdomaininfo.shared_info_frame = __pa(p->shared_info) >> PAGE_SHIFT; - if ( p->state == TASK_STOPPED ) + + if ( p->state == TASK_STOPPED && op->u.getdomaininfo.ctxt ) { + full_execution_context_t *c=NULL; + + if ( (c = kmalloc(sizeof(*c), GFP_KERNEL)) == NULL ) + { + ret= -ENOMEM; + goto gdi_out; + } + rmb(); /* Ensure that we see saved register state. */ - op->u.getdomaininfo.ctxt.flags = 0; - memcpy(&op->u.getdomaininfo.ctxt.cpu_ctxt, + c->flags = 0; + memcpy(&c->cpu_ctxt, &p->shared_info->execution_context, sizeof(p->shared_info->execution_context)); if ( test_bit(PF_DONEFPUINIT, &p->flags) ) - op->u.getdomaininfo.ctxt.flags |= ECF_I387_VALID; - memcpy(&op->u.getdomaininfo.ctxt.fpu_ctxt, + c->flags |= ECF_I387_VALID; + memcpy(&c->fpu_ctxt, &p->thread.i387, sizeof(p->thread.i387)); - memcpy(&op->u.getdomaininfo.ctxt.trap_ctxt, + memcpy(&c->trap_ctxt, p->thread.traps, sizeof(p->thread.traps)); #ifdef ARCH_HAS_FAST_TRAP if ( (p->thread.fast_trap_desc.a == 0) && (p->thread.fast_trap_desc.b == 0) ) - op->u.getdomaininfo.ctxt.fast_trap_idx = 0; + c->fast_trap_idx = 0; else - op->u.getdomaininfo.ctxt.fast_trap_idx = + c->fast_trap_idx = p->thread.fast_trap_idx; #endif - op->u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base; - op->u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents; - op->u.getdomaininfo.ctxt.gdt_ents = 0; + c->ldt_base = p->mm.ldt_base; + c->ldt_ents = p->mm.ldt_ents; + c->gdt_ents = 0; if ( GET_GDT_ADDRESS(p) == GDT_VIRT_START ) { for ( i = 0; i < 16; i++ ) - op->u.getdomaininfo.ctxt.gdt_frames[i] = + c->gdt_frames[i] = l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]); - op->u.getdomaininfo.ctxt.gdt_ents = + c->gdt_ents = (GET_GDT_ENTRIES(p) + 1) >> 3; } - op->u.getdomaininfo.ctxt.guestos_ss = p->thread.guestos_ss; - op->u.getdomaininfo.ctxt.guestos_esp = p->thread.guestos_sp; - op->u.getdomaininfo.ctxt.pt_base = + c->guestos_ss = p->thread.guestos_ss; + c->guestos_esp = p->thread.guestos_sp; + c->pt_base = pagetable_val(p->mm.pagetable); - memcpy(op->u.getdomaininfo.ctxt.debugreg, + memcpy(c->debugreg, p->thread.debugreg, sizeof(p->thread.debugreg)); - op->u.getdomaininfo.ctxt.event_callback_cs = + c->event_callback_cs = p->event_selector; - op->u.getdomaininfo.ctxt.event_callback_eip = + c->event_callback_eip = p->event_address; - op->u.getdomaininfo.ctxt.failsafe_callback_cs = + c->failsafe_callback_cs = p->failsafe_selector; - op->u.getdomaininfo.ctxt.failsafe_callback_eip = + c->failsafe_callback_eip = p->failsafe_address; + + if( copy_to_user(op->u.getdomaininfo.ctxt, c, sizeof(*c)) ) + { +printk("URGHT %p\n",op->u.getdomaininfo.ctxt); + ret = -EINVAL; + } + + if (c) kfree(c); } } + + if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + ret = -EINVAL; + + gdi_out: read_unlock_irqrestore(&tasklist_lock, flags); - copy_to_user(u_dom0_op, op, sizeof(*op)); + } break; @@ -647,7 +666,5 @@ long do_dom0_op(dom0_op_t *u_dom0_op) } - out: - kfree(op); return ret; } diff --git a/xen/common/domain.c b/xen/common/domain.c index 2b1372a6af..24f15e886b 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -535,45 +535,58 @@ void release_task(struct task_struct *p) int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain) { unsigned long phys_basetab; - int i; + int i, rc = 0; + full_execution_context_t *c; + + if ( (c = kmalloc(sizeof(*c), GFP_KERNEL)) == NULL ) + return -ENOMEM; if ( test_bit(PF_CONSTRUCTED, &p->flags) ) - return -EINVAL; + { + rc = -EINVAL; + goto out; + } + + if ( copy_from_user(c, builddomain->ctxt, sizeof(*c)) ) + { + rc = -EFAULT; + goto out; + } clear_bit(PF_DONEFPUINIT, &p->flags); - if ( builddomain->ctxt.flags & ECF_I387_VALID ) + if ( c->flags & ECF_I387_VALID ) set_bit(PF_DONEFPUINIT, &p->flags); memcpy(&p->shared_info->execution_context, - &builddomain->ctxt.cpu_ctxt, + &c->cpu_ctxt, sizeof(p->shared_info->execution_context)); memcpy(&p->thread.i387, - &builddomain->ctxt.fpu_ctxt, + &c->fpu_ctxt, sizeof(p->thread.i387)); memcpy(p->thread.traps, - &builddomain->ctxt.trap_ctxt, + &c->trap_ctxt, sizeof(p->thread.traps)); #ifdef ARCH_HAS_FAST_TRAP SET_DEFAULT_FAST_TRAP(&p->thread); - (void)set_fast_trap(p, builddomain->ctxt.fast_trap_idx); + (void)set_fast_trap(p, c->fast_trap_idx); #endif - p->mm.ldt_base = builddomain->ctxt.ldt_base; - p->mm.ldt_ents = builddomain->ctxt.ldt_ents; + p->mm.ldt_base = c->ldt_base; + p->mm.ldt_ents = c->ldt_ents; SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES); SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS); - if ( builddomain->ctxt.gdt_ents != 0 ) + if ( c->gdt_ents != 0 ) (void)set_gdt(p, - builddomain->ctxt.gdt_frames, - builddomain->ctxt.gdt_ents); - p->thread.guestos_ss = builddomain->ctxt.guestos_ss; - p->thread.guestos_sp = builddomain->ctxt.guestos_esp; + c->gdt_frames, + c->gdt_ents); + p->thread.guestos_ss = c->guestos_ss; + p->thread.guestos_sp = c->guestos_esp; for ( i = 0; i < 8; i++ ) - (void)set_debugreg(p, i, builddomain->ctxt.debugreg[i]); - p->event_selector = builddomain->ctxt.event_callback_cs; - p->event_address = builddomain->ctxt.event_callback_eip; - p->failsafe_selector = builddomain->ctxt.failsafe_callback_cs; - p->failsafe_address = builddomain->ctxt.failsafe_callback_eip; + (void)set_debugreg(p, i, c->debugreg[i]); + p->event_selector = c->event_callback_cs; + p->event_address = c->event_callback_eip; + p->failsafe_selector = c->failsafe_callback_cs; + p->failsafe_address = c->failsafe_callback_eip; - phys_basetab = builddomain->ctxt.pt_base; + phys_basetab = c->pt_base; p->mm.pagetable = mk_pagetable(phys_basetab); get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], p, PGT_base_page_table); @@ -586,8 +599,11 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain) (void)create_net_vif(p->domain); set_bit(PF_CONSTRUCTED, &p->flags); + +out: + if (c) kfree(c); - return 0; + return rc; } static inline int is_loadable_phdr(Elf_Phdr *phdr) diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index 3bc18476af..997c5156fb 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -80,6 +80,7 @@ typedef struct dom0_getdomaininfo_st { /* IN variables. */ domid_t domain; + full_execution_context_t *ctxt; /* OUT variables. */ char name[MAX_DOMAIN_NAME]; int processor; @@ -91,7 +92,6 @@ typedef struct dom0_getdomaininfo_st unsigned int tot_pages, max_pages; long long cpu_time; unsigned long shared_info_frame; /* MFN of shared_info struct */ - full_execution_context_t ctxt; } dom0_getdomaininfo_t; #define DOM0_BUILDDOMAIN 13 @@ -100,7 +100,8 @@ typedef struct dom0_builddomain_st /* IN variables. */ domid_t domain; unsigned int num_vifs; - full_execution_context_t ctxt; + /* IN/OUT parameters */ + full_execution_context_t *ctxt; } dom0_builddomain_t; #define DOM0_IOPL 14 @@ -152,7 +153,8 @@ typedef struct dom0_getpageframeinfo_st domid_t domain; /* To which domain does the frame belong? */ /* OUT variables. */ /* Is the page PINNED to a type? */ - enum { NONE, L1TAB, L2TAB, L3TAB, L4TAB } type; + enum { NONE, L1TAB=(1<<29), L2TAB=(2<<29), L3TAB=(3<<29), L4TAB=(4<<29) } type; +#define PGT_type_mask (7<<29) } dom0_getpageframeinfo_t;