diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-02-27 15:19:27 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-02-27 15:19:27 +0000 |
commit | 852c5cea72e07706be1e778f6cdd03c8026ee966 (patch) | |
tree | 51881b783de92fce1aad9620e4964c0a2aedb56b /tools/xc | |
parent | 66090e1c4bc9de311f804ffb6a7a3dd97c6aeb71 (diff) | |
download | xen-852c5cea72e07706be1e778f6cdd03c8026ee966.tar.gz xen-852c5cea72e07706be1e778f6cdd03c8026ee966.tar.bz2 xen-852c5cea72e07706be1e778f6cdd03c8026ee966.zip |
bitkeeper revision 1.755 (403f5fffwYqT6Gw88yRJHe04lMgpjg)
Many files:
Further cleanups to the Xen pagetable interface.
Diffstat (limited to 'tools/xc')
-rw-r--r-- | tools/xc/lib/xc_linux_build.c | 60 | ||||
-rw-r--r-- | tools/xc/lib/xc_linux_restore.c | 71 | ||||
-rw-r--r-- | tools/xc/lib/xc_netbsd_build.c | 60 | ||||
-rw-r--r-- | tools/xc/lib/xc_private.c | 70 | ||||
-rw-r--r-- | tools/xc/lib/xc_private.h | 14 |
5 files changed, 134 insertions, 141 deletions
diff --git a/tools/xc/lib/xc_linux_build.c b/tools/xc/lib/xc_linux_build.c index 6c6c1c9449..32b1515557 100644 --- a/tools/xc/lib/xc_linux_build.c +++ b/tools/xc/lib/xc_linux_build.c @@ -43,27 +43,6 @@ static int get_pfn_list(int xc_handle, return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; } -static int send_pgupdates(int xc_handle, mmu_update_t *updates, int nr_updates) -{ - int ret = -1; - privcmd_hypercall_t hypercall; - - hypercall.op = __HYPERVISOR_mmu_update; - hypercall.arg[0] = (unsigned long)updates; - hypercall.arg[1] = (unsigned long)nr_updates; - - if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 ) - goto out1; - - if ( do_xen_hypercall(xc_handle, &hypercall) < 0 ) - goto out2; - - ret = 0; - - out2: (void)munlock(updates, nr_updates * sizeof(*updates)); - out1: return ret; -} - /* Read the kernel header, extracting the image size and load address. */ static int read_kernel_header(gzFile gfd, long dom_size, unsigned long *load_addr) @@ -109,16 +88,15 @@ static int setup_guestos(int xc_handle, l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; l2_pgentry_t *vl2tab=NULL, *vl2e=NULL; unsigned long *page_array = NULL; - mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL; int alloc_index, num_pt_pages; unsigned long l2tab; unsigned long l1tab; - unsigned long num_pgt_updates = 0; unsigned long count, pt_start, i, j; unsigned long initrd_addr = 0, initrd_len = 0; start_info_t *start_info; shared_info_t *shared_info; unsigned long ksize; + mmu_t *mmu = NULL; int pm_handle; memset(builddomain, 0, sizeof(*builddomain)); @@ -126,10 +104,7 @@ static int setup_guestos(int xc_handle, if ( (pm_handle = init_pfn_mapper()) < 0 ) goto error_out; - pgt_updates = malloc((tot_pages + 1) * sizeof(mmu_update_t)); - page_array = malloc(tot_pages * sizeof(unsigned long)); - pgt_update_arr = pgt_updates; - if ( (pgt_update_arr == NULL) || (page_array == NULL) ) + if ( (page_array = malloc(tot_pages * sizeof(unsigned long))) == NULL ) { PERROR("Could not allocate memory"); goto error_out; @@ -210,6 +185,9 @@ static int setup_guestos(int xc_handle, alloc_index--; builddomain->ctxt.pt_base = l2tab; + if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) + goto error_out; + /* Initialise the page tables. */ if ( (vl2tab = map_pfn_writeable(pm_handle, l2tab >> PAGE_SHIFT)) == NULL ) goto error_out; @@ -236,11 +214,10 @@ static int setup_guestos(int xc_handle, *vl1e &= ~_PAGE_RW; vl1e++; - pgt_updates->ptr = - (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; - pgt_updates->val = count; - pgt_updates++; - num_pgt_updates++; + if ( add_mmu_update(xc_handle, mmu, + (page_array[count] << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE, count) ) + goto error_out; } unmap_pfn(pm_handle, vl1tab); unmap_pfn(pm_handle, vl2tab); @@ -249,10 +226,9 @@ static int setup_guestos(int xc_handle, * Pin down l2tab addr as page dir page - causes hypervisor to provide * correct protection for the page */ - pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND; - pgt_updates->val = MMUEXT_PIN_L2_TABLE; - pgt_updates++; - num_pgt_updates++; + if ( add_mmu_update(xc_handle, mmu, + l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) ) + goto error_out; *virt_startinfo_addr = virt_load_addr + ((alloc_index-1) << PAGE_SHIFT); @@ -267,7 +243,6 @@ static int setup_guestos(int xc_handle, start_info->flags = 0; strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN); start_info->cmd_line[MAX_CMD_LEN-1] = '\0'; - unmap_pfn(pm_handle, start_info); /* shared_info page starts its life empty. */ @@ -276,20 +251,21 @@ static int setup_guestos(int xc_handle, unmap_pfn(pm_handle, shared_info); /* Send the page update requests down to the hypervisor. */ - if ( send_pgupdates(xc_handle, pgt_update_arr, num_pgt_updates) < 0 ) + if ( finish_mmu_updates(xc_handle, mmu) ) goto error_out; + free(mmu); + (void)close_pfn_mapper(pm_handle); free(page_array); - free(pgt_update_arr); return 0; error_out: + if ( mmu != NULL ) + free(mmu); if ( pm_handle >= 0 ) (void)close_pfn_mapper(pm_handle); - if ( page_array ) + if ( page_array != NULL ) free(page_array); - if ( pgt_update_arr ) - free(pgt_update_arr); return -1; } diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c index 74e7641bed..3b00a81011 100644 --- a/tools/xc/lib/xc_linux_restore.c +++ b/tools/xc/lib/xc_linux_restore.c @@ -43,56 +43,6 @@ static int get_pfn_list(int xc_handle, return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; } -#define MAX_MMU_UPDATES 1024 - -static int flush_mmu_updates(int xc_handle, - mmu_update_t *mmu_updates, - int *mmu_update_idx) -{ - int err = 0; - privcmd_hypercall_t hypercall; - - if ( *mmu_update_idx == 0 ) - return 0; - - hypercall.op = __HYPERVISOR_mmu_update; - hypercall.arg[0] = (unsigned long)mmu_updates; - hypercall.arg[1] = (unsigned long)*mmu_update_idx; - - if ( mlock(mmu_updates, sizeof(mmu_updates)) != 0 ) - { - PERROR("Could not lock pagetable update array"); - err = 1; - goto out; - } - - if ( do_xen_hypercall(xc_handle, &hypercall) < 0 ) - { - ERROR("Failure when submitting mmu updates"); - err = 1; - } - - *mmu_update_idx = 0; - - (void)munlock(mmu_updates, sizeof(mmu_updates)); - - out: - return err; -} - -static int add_mmu_update(int xc_handle, - mmu_update_t *mmu_updates, - int *mmu_update_idx, - unsigned long ptr, - unsigned long val) -{ - mmu_updates[*mmu_update_idx].ptr = ptr; - mmu_updates[*mmu_update_idx].val = val; - if ( ++*mmu_update_idx == MAX_MMU_UPDATES ) - return flush_mmu_updates(xc_handle, mmu_updates, mmu_update_idx); - return 0; -} - static int checked_read(gzFile fd, void *buf, size_t count) { int rc; @@ -147,8 +97,7 @@ int xc_linux_restore(int xc_handle, int fd; gzFile gfd; - mmu_update_t mmu_updates[MAX_MMU_UPDATES]; - int mmu_update_idx = 0; + mmu_t *mmu = NULL; int pm_handle = -1; @@ -252,6 +201,12 @@ int xc_linux_restore(int xc_handle, goto out; } + if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) + { + ERROR("Could not initialise for MMU updates"); + goto out; + } + verbose_printf("Reloading memory pages: 0%%"); /* @@ -323,7 +278,7 @@ int xc_linux_restore(int xc_handle, unmap_pfn(pm_handle, ppage); - if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx, + if ( add_mmu_update(xc_handle, mmu, (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) ) goto out; } @@ -336,7 +291,7 @@ int xc_linux_restore(int xc_handle, { if ( pfn_type[i] == L1TAB ) { - if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx, + if ( add_mmu_update(xc_handle, mmu, (pfn_to_mfn_table[i]<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L1_TABLE) ) @@ -344,7 +299,7 @@ int xc_linux_restore(int xc_handle, } else if ( pfn_type[i] == L2TAB ) { - if ( add_mmu_update(xc_handle, mmu_updates, &mmu_update_idx, + if ( add_mmu_update(xc_handle, mmu, (pfn_to_mfn_table[i]<<PAGE_SHIFT) | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) ) @@ -352,8 +307,7 @@ int xc_linux_restore(int xc_handle, } } - - if ( flush_mmu_updates(xc_handle, mmu_updates, &mmu_update_idx) ) + if ( finish_mmu_updates(xc_handle, mmu) ) goto out; verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n"); @@ -455,6 +409,9 @@ int xc_linux_restore(int xc_handle, rc = do_dom0_op(xc_handle, &op); out: + if ( mmu != NULL ) + free(mmu); + if ( rc != 0 ) { if ( dom != 0 ) diff --git a/tools/xc/lib/xc_netbsd_build.c b/tools/xc/lib/xc_netbsd_build.c index 23df4afb72..56fd35dbab 100644 --- a/tools/xc/lib/xc_netbsd_build.c +++ b/tools/xc/lib/xc_netbsd_build.c @@ -53,27 +53,6 @@ static int get_pfn_list(int xc_handle, return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; } -static int send_pgupdates(int xc_handle, mmu_update_t *updates, int nr_updates) -{ - int ret = -1; - privcmd_hypercall_t hypercall; - - hypercall.op = __HYPERVISOR_mmu_update; - hypercall.arg[0] = (unsigned long)updates; - hypercall.arg[1] = (unsigned long)nr_updates; - - if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 ) - goto out1; - - if ( do_xen_hypercall(xc_handle, &hypercall) < 0 ) - goto out2; - - ret = 0; - - out2: (void)munlock(updates, nr_updates * sizeof(*updates)); - out1: return ret; -} - static int setup_guestos(int xc_handle, u64 dom, gzFile kernel_gfd, @@ -87,16 +66,15 @@ static int setup_guestos(int xc_handle, l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; l2_pgentry_t *vl2tab=NULL, *vl2e=NULL; unsigned long *page_array = NULL; - mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL; int alloc_index, num_pt_pages; unsigned long l2tab; unsigned long l1tab; - unsigned long num_pgt_updates = 0; unsigned long count, pt_start; unsigned long symtab_addr = 0, symtab_len = 0; start_info_t *start_info; shared_info_t *shared_info; unsigned long ksize; + mmu_t *mmu = NULL; int pm_handle; memset(builddomain, 0, sizeof(*builddomain)); @@ -104,10 +82,7 @@ static int setup_guestos(int xc_handle, if ( (pm_handle = init_pfn_mapper()) < 0 ) goto error_out; - pgt_updates = malloc((tot_pages + 1) * sizeof(mmu_update_t)); - page_array = malloc(tot_pages * sizeof(unsigned long)); - pgt_update_arr = pgt_updates; - if ( (pgt_update_arr == NULL) || (page_array == NULL) ) + if ( (page_array = malloc(tot_pages * sizeof(unsigned long))) == NULL ) { PERROR("Could not allocate memory"); goto error_out; @@ -144,7 +119,10 @@ static int setup_guestos(int xc_handle, l2tab = page_array[alloc_index] << PAGE_SHIFT; alloc_index--; builddomain->ctxt.pt_base = l2tab; - + + if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) + goto error_out; + /* Initialise the page tables. */ if ( (vl2tab = map_pfn_writeable(pm_handle, l2tab >> PAGE_SHIFT)) == NULL ) goto error_out; @@ -171,11 +149,10 @@ static int setup_guestos(int xc_handle, *vl1e &= ~_PAGE_RW; vl1e++; - pgt_updates->ptr = - (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; - pgt_updates->val = count; - pgt_updates++; - num_pgt_updates++; + if ( add_mmu_update(xc_handle, mmu, + (page_array[count] << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE, count) ) + goto error_out; } unmap_pfn(pm_handle, vl1tab); unmap_pfn(pm_handle, vl2tab); @@ -184,10 +161,9 @@ static int setup_guestos(int xc_handle, * Pin down l2tab addr as page dir page - causes hypervisor to provide * correct protection for the page */ - pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND; - pgt_updates->val = MMUEXT_PIN_L2_TABLE; - pgt_updates++; - num_pgt_updates++; + if ( add_mmu_update(xc_handle, mmu, + l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) ) + goto error_out; *virt_startinfo_addr = *virt_load_addr + ((alloc_index-1) << PAGE_SHIFT); @@ -202,7 +178,6 @@ static int setup_guestos(int xc_handle, start_info->flags = 0; strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN); start_info->cmd_line[MAX_CMD_LEN-1] = '\0'; - unmap_pfn(pm_handle, start_info); /* shared_info page starts its life empty. */ @@ -211,20 +186,21 @@ static int setup_guestos(int xc_handle, unmap_pfn(pm_handle, shared_info); /* Send the page update requests down to the hypervisor. */ - if ( send_pgupdates(xc_handle, pgt_update_arr, num_pgt_updates) < 0 ) + if ( finish_mmu_updates(xc_handle, mmu) ) goto error_out; + free(mmu); + (void)close_pfn_mapper(pm_handle); free(page_array); - free(pgt_update_arr); return 0; error_out: + if ( mmu != NULL ) + free(mmu); if ( pm_handle >= 0 ) (void)close_pfn_mapper(pm_handle); if ( page_array == NULL ) free(page_array); - if ( pgt_update_arr == NULL ) - free(pgt_update_arr); return -1; } diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c index 4331cc943c..3b634148eb 100644 --- a/tools/xc/lib/xc_private.c +++ b/tools/xc/lib/xc_private.c @@ -38,3 +38,73 @@ void unmap_pfn(int pm_handle, void *vaddr) { (void)munmap(vaddr, PAGE_SIZE); } + +#define FIRST_MMU_UPDATE 2 + +static int flush_mmu_updates(int xc_handle, mmu_t *mmu) +{ + int err = 0; + privcmd_hypercall_t hypercall; + + if ( mmu->idx == FIRST_MMU_UPDATE ) + return 0; + + /* The first two requests set the correct subject domain. */ + mmu->updates[0].val = (unsigned long)(mmu->subject<<16) & ~0xFFFFUL; + mmu->updates[0].ptr = (unsigned long)(mmu->subject<< 0) & ~0xFFFFUL; + mmu->updates[1].val = (unsigned long)(mmu->subject>>16) & ~0xFFFFUL; + mmu->updates[1].ptr = (unsigned long)(mmu->subject>>32) & ~0xFFFFUL; + mmu->updates[0].ptr |= MMU_EXTENDED_COMMAND; + mmu->updates[0].val |= MMUEXT_SET_SUBJECTDOM_L; + mmu->updates[1].ptr |= MMU_EXTENDED_COMMAND; + mmu->updates[1].val |= MMUEXT_SET_SUBJECTDOM_H; + + hypercall.op = __HYPERVISOR_mmu_update; + hypercall.arg[0] = (unsigned long)mmu->updates; + hypercall.arg[1] = (unsigned long)mmu->idx; + + if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 ) + { + PERROR("Could not lock pagetable update array"); + err = 1; + goto out; + } + + if ( do_xen_hypercall(xc_handle, &hypercall) < 0 ) + { + ERROR("Failure when submitting mmu updates"); + err = 1; + } + + mmu->idx = FIRST_MMU_UPDATE; + + (void)munlock(mmu->updates, sizeof(mmu->updates)); + + out: + return err; +} + +mmu_t *init_mmu_updates(int xc_handle, domid_t dom) +{ + mmu_t *mmu = malloc(sizeof(mmu_t)); + if ( mmu == NULL ) + return mmu; + mmu->idx = FIRST_MMU_UPDATE; + mmu->subject = dom; + return mmu; +} + +int add_mmu_update(int xc_handle, mmu_t *mmu, + unsigned long ptr, unsigned long val) +{ + mmu->updates[mmu->idx].ptr = ptr; + mmu->updates[mmu->idx].val = val; + if ( ++mmu->idx == MAX_MMU_UPDATES ) + return flush_mmu_updates(xc_handle, mmu); + return 0; +} + +int finish_mmu_updates(int xc_handle, mmu_t *mmu) +{ + return flush_mmu_updates(xc_handle, mmu); +} diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h index c08a2564ec..6499c58872 100644 --- a/tools/xc/lib/xc_private.h +++ b/tools/xc/lib/xc_private.h @@ -153,4 +153,18 @@ void *map_pfn_writeable(int pm_handle, unsigned long pfn); void *map_pfn_readonly(int pm_handle, unsigned long pfn); void unmap_pfn(int pm_handle, void *vaddr); +/* + * MMU updates. + */ +#define MAX_MMU_UPDATES 1024 +typedef struct { + mmu_update_t updates[MAX_MMU_UPDATES]; + int idx; + domid_t subject; +} mmu_t; +mmu_t *init_mmu_updates(int xc_handle, domid_t dom); +int add_mmu_update(int xc_handle, mmu_t *mmu, + unsigned long ptr, unsigned long val); +int finish_mmu_updates(int xc_handle, mmu_t *mmu); + #endif /* __XC_PRIVATE_H__ */ |