From 5018bf31377c6416f0c5a250a0afdabdc810ef2b Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Wed, 30 Jun 2004 15:31:23 +0000 Subject: [PATCH 1/2] bitkeeper revision 1.1041.2.1 (40e2dccbwLPMSsarwzAscW72tSfuEg) Add resource tracking for pfn mappings in libxc. --- tools/libxc/xc_linux_build.c | 20 +-- tools/libxc/xc_linux_restore.c | 257 +++++++++++++++++++-------------- tools/libxc/xc_netbsd_build.c | 11 +- tools/libxc/xc_private.c | 139 ++++++++++++++---- tools/libxc/xc_private.h | 10 +- 5 files changed, 287 insertions(+), 150 deletions(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index ceace01b00..c2228b5e9e 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -18,7 +18,7 @@ static int readelfimage_base_and_size(char *elfbase, unsigned long *pkernstart, unsigned long *pkernend, unsigned long *pkernentry); -static int loadelfimage(char *elfbase, int pmh, unsigned long *parray, +static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray, unsigned long vstart); static long get_tot_pages(int xc_handle, u32 domid) @@ -53,7 +53,7 @@ static int get_pfn_list(int xc_handle, return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; } -static int copy_to_domain_page(int pm_handle, +static int copy_to_domain_page(void *pm_handle, unsigned long dst_pfn, void *src_page) { @@ -86,7 +86,8 @@ static int setup_guestos(int xc_handle, extended_start_info_t *start_info; shared_info_t *shared_info; mmu_t *mmu = NULL; - int pm_handle=-1, rc; + void *pm_handle=NULL; + int rc; unsigned long nr_pt_pages; unsigned long ppt_alloc; @@ -165,7 +166,7 @@ static int setup_guestos(int xc_handle, v_start, v_end); printf(" ENTRY ADDRESS: %08lx\n", vkern_entry); - if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 ) + if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL ) goto error_out; if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) @@ -307,7 +308,7 @@ static int setup_guestos(int xc_handle, error_out: if ( mmu != NULL ) free(mmu); - if ( pm_handle >= 0 ) + if ( pm_handle != NULL ) (void)close_pfn_mapper(pm_handle); if ( page_array != NULL ) free(page_array); @@ -629,7 +630,7 @@ static int readelfimage_base_and_size(char *elfbase, return 0; } -static int loadelfimage(char *elfbase, int pmh, unsigned long *parray, +static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray, unsigned long vstart) { Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase; @@ -649,11 +650,11 @@ static int loadelfimage(char *elfbase, int pmh, unsigned long *parray, { pa = (phdr->p_vaddr + done) - vstart; va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]); - va += pa & (PAGE_SIZE-1); chunksz = phdr->p_filesz - done; if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) ) chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1)); - memcpy(va, elfbase + phdr->p_offset + done, chunksz); + memcpy(va + (pa & (PAGE_SIZE-1)), + elfbase + phdr->p_offset + done, chunksz); unmap_pfn(pmh, va); } @@ -661,11 +662,10 @@ static int loadelfimage(char *elfbase, int pmh, unsigned long *parray, { pa = (phdr->p_vaddr + done) - vstart; va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]); - va += pa & (PAGE_SIZE-1); chunksz = phdr->p_memsz - done; if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) ) chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1)); - memset(va, 0, chunksz); + memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz); unmap_pfn(pmh, va); } } diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index badba75162..f091914dba 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -19,7 +19,6 @@ #define DPRINTF(_f, _a...) ((void)0) #endif - static int get_pfn_list(int xc_handle, u32 domain_id, unsigned long *pfn_buf, @@ -53,23 +52,28 @@ static int get_pfn_list(int xc_handle, * @param ioctxt i/o context * @return 0 on success, non-zero on error. */ -static int read_vmconfig(XcIOContext *ioctxt){ +static int read_vmconfig(XcIOContext *ioctxt) +{ int err = -1; - if(xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))){ + + if ( xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n)) ) goto exit; - } + ioctxt->vmconfig = malloc(ioctxt->vmconfig_n + 1); - if(!ioctxt->vmconfig) goto exit; - if(xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)){ + if ( ioctxt->vmconfig == NULL ) goto exit; - } + + if ( xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n) ) + goto exit; + ioctxt->vmconfig[ioctxt->vmconfig_n] = '\0'; err = 0; + exit: - if(err){ - if(ioctxt->vmconfig){ + if ( err ) + { + if ( ioctxt->vmconfig != NULL ) free(ioctxt->vmconfig); - } ioctxt->vmconfig = NULL; ioctxt->vmconfig_n = 0; } @@ -126,12 +130,13 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) mmu_t *mmu = NULL; - int pm_handle = -1; + void *pm_handle = NULL; /* used by debug verify code */ unsigned long buf[PAGE_SIZE/sizeof(unsigned long)]; - if ( mlock(&ctxt, sizeof(ctxt) ) ) { + 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"); @@ -140,24 +145,28 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* Start writing out the saved-domain record. */ if ( xcio_read(ioctxt, signature, 16) || - (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) { + (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) + { xcio_error(ioctxt, "Unrecognised state format -- no signature found"); goto out; } if ( xcio_read(ioctxt, name, sizeof(name)) || xcio_read(ioctxt, &nr_pfns, sizeof(unsigned long)) || - xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) { + xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) + { xcio_error(ioctxt, "Error reading header"); goto out; } - if(read_vmconfig(ioctxt)){ + if ( read_vmconfig(ioctxt) ) + { xcio_error(ioctxt, "Error writing vmconfig"); goto out; } - for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) { + for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) + { if ( name[i] == '\0' ) break; if ( name[i] & 0x80 ) { @@ -167,7 +176,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) } name[MAX_DOMAIN_NAME-1] = '\0'; - if ( nr_pfns > 1024*1024 ) { + if ( nr_pfns > 1024*1024 ) + { xcio_error(ioctxt, "Invalid state file -- pfn count out of range"); goto out; } @@ -177,19 +187,23 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) pfn_type = calloc(1, 4 * nr_pfns); region_mfn = calloc(1, 4 * MAX_BATCH_SIZE); - if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) || - (region_mfn == NULL) ) { + if ( (pfn_to_mfn_table == NULL) || + (pfn_type == NULL) || + (region_mfn == NULL) ) + { errno = ENOMEM; goto out; } - if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) { + if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) + { xcio_error(ioctxt, "Could not mlock region_mfn"); goto out; } /* Set the domain's name to that from the restore file */ - if ( xc_domain_setname( xc_handle, dom, name ) ) { + if ( xc_domain_setname( xc_handle, dom, name ) ) + { xcio_error(ioctxt, "Could not set domain name"); goto out; } @@ -208,24 +222,26 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)dom; op.u.getdomaininfo.ctxt = NULL; - if ( do_dom0_op(xc_handle, &op) < 0 ) { + if ( do_dom0_op(xc_handle, &op) < 0 ) + { xcio_error(ioctxt, "Could not get information on new domain"); goto out; } shared_info_frame = op.u.getdomaininfo.shared_info_frame; - if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 ) + if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL ) goto out; - - /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */ - if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) { - xcio_error(ioctxt, "Did not read correct number of frame numbers for new dom"); + if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) + { + xcio_error(ioctxt, "Did not read correct number of frame " + "numbers for new dom"); goto out; } - if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) { + if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) + { xcio_error(ioctxt, "Could not initialise for MMU updates"); goto out; } @@ -238,33 +254,39 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) */ prev_pc = 0; - n=0; - while(1) { + n = 0; + while ( 1 ) + { int j; unsigned long region_pfn_type[MAX_BATCH_SIZE]; this_pc = (n * 100) / nr_pfns; - if ( (this_pc - prev_pc) >= 5 ) { + if ( (this_pc - prev_pc) >= 5 ) + { xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc); prev_pc = this_pc; } - if ( xcio_read(ioctxt, &j, sizeof(int)) ) { + if ( xcio_read(ioctxt, &j, sizeof(int)) ) + { xcio_error(ioctxt, "Error when reading from state file"); goto out; } DPRINTF("batch %d\n",j); - if ( j == -1 ) { + if ( j == -1 ) + { verify = 1; printf("Entering page verify mode\n"); continue; } - if ( j == 0 ) break; /* our work here is done */ + if ( j == 0 ) + break; /* our work here is done */ - if( j > MAX_BATCH_SIZE ) { + if ( j > MAX_BATCH_SIZE ) + { xcio_error(ioctxt, "Max batch size exceeded. Giving up."); goto out; } @@ -274,10 +296,14 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) goto out; } - for(i=0; inr_pfns) { + if (pfn>nr_pfns) + { xcio_error(ioctxt, "pfn out of range"); goto out; } @@ -309,32 +338,36 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) mfn = pfn_to_mfn_table[pfn]; - if ( verify ) { + if ( verify ) ppage = (unsigned long*) buf; /* debug case */ - } else { + else ppage = (unsigned long*) (region_base + i*PAGE_SIZE); - } - if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) { + if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) + { xcio_error(ioctxt, "Error when reading from state file"); goto out; } - switch( region_pfn_type[i] ) { + switch( region_pfn_type[i] ) + { case 0: break; case L1TAB: { - for ( k = 0; k < 1024; k++ ) { - if ( ppage[k] & _PAGE_PRESENT ) { + for ( k = 0; k < 1024; k++ ) + { + if ( ppage[k] & _PAGE_PRESENT ) + { xpfn = ppage[k] >> PAGE_SHIFT; - - if ( xpfn >= nr_pfns ) { - xcio_error(ioctxt, "Frame number in type %lu page table is " - "out of range. i=%d k=%d pfn=0x%lx " - "nr_pfns=%lu", region_pfn_type[i]>>28, i, - k, xpfn, nr_pfns); + if ( xpfn >= nr_pfns ) + { + xcio_error(ioctxt, "Frame number in type %lu page " + "table is out of range. i=%d k=%d " + "pfn=0x%lx nr_pfns=%lu", + region_pfn_type[i]>>28, i, + k, xpfn, nr_pfns); goto out; } @@ -350,15 +383,19 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) { for ( k = 0; k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); - k++ ) { - if ( ppage[k] & _PAGE_PRESENT ) { + k++ ) + { + if ( ppage[k] & _PAGE_PRESENT ) + { xpfn = ppage[k] >> PAGE_SHIFT; - if ( xpfn >= nr_pfns ) { - xcio_error(ioctxt, "Frame number in type %lu page table is " - "out of range. i=%d k=%d pfn=%lu nr_pfns=%lu", - region_pfn_type[i]>>28, i, k, xpfn, nr_pfns); - + if ( xpfn >= nr_pfns ) + { + xcio_error(ioctxt, "Frame number in type %lu page" + " table is out of range. i=%d k=%d " + "pfn=%lu nr_pfns=%lu", + region_pfn_type[i]>>28, i, k, + xpfn, nr_pfns); goto out; } @@ -371,21 +408,25 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) break; default: - xcio_error(ioctxt, "Bogus page type %lx page table is out of range." - " i=%d nr_pfns=%lu", region_pfn_type[i], i, nr_pfns); + xcio_error(ioctxt, "Bogus page type %lx page table is " + "out of range. i=%d nr_pfns=%lu", + region_pfn_type[i], i, nr_pfns); goto out; } /* end of page type switch statement */ - if ( verify ) { + if ( verify ) + { int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE ); - if (res) { + if ( res ) + { int v; printf("************** pfn=%lx type=%lx gotcs=%08lx " "actualcs=%08lx\n", pfn, pfn_type[pfn], csum_page(region_base + i*PAGE_SIZE), csum_page(buf)); - for ( v = 0; v < 4; v++ ) { + for ( v = 0; v < 4; v++ ) + { unsigned long *p = (unsigned long *) (region_base + i*PAGE_SIZE); if ( buf[v] != p[v] ) @@ -396,7 +437,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) } if ( add_mmu_update(xc_handle, mmu, - (mfn< 8192 ) { + if ( ctxt.gdt_ents > 8192 ) + { xcio_error(ioctxt, "GDT entry count out of range"); goto out; } - for ( i = 0; i < ctxt.gdt_ents; i += 512 ) { + for ( i = 0; i < ctxt.gdt_ents; i += 512 ) + { pfn = ctxt.gdt_frames[i]; - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) { + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) + { xcio_error(ioctxt, "GDT frame number is bad"); goto out; } @@ -478,7 +527,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* Uncanonicalise the page table base pointer. */ pfn = ctxt.pt_base >> PAGE_SHIFT; - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) { + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) + { printf("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n", pfn, nr_pfns, pfn_type[pfn], (unsigned long)L2TAB); xcio_error(ioctxt, "PT base is bad."); @@ -499,11 +549,13 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* Uncanonicalise the pfn-to-mfn table frame-number list. */ - for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) { + for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) + { unsigned long pfn, mfn; pfn = pfn_to_mfn_frame_list[i]; - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) { + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) + { xcio_error(ioctxt, "PFN-to-MFN frame number is bad"); goto out; } @@ -515,15 +567,16 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) mfn_mapper_map_batch(xc_handle, dom, PROT_WRITE, pfn_to_mfn_frame_list, - (nr_pfns+1023)/1024 )) == 0 ) { + (nr_pfns+1023)/1024 )) == 0 ) + { xcio_error(ioctxt, "Couldn't map pfn_to_mfn table"); goto out; } - memcpy( live_pfn_to_mfn_table, pfn_to_mfn_table, - nr_pfns*sizeof(unsigned long) ); + memcpy(live_pfn_to_mfn_table, pfn_to_mfn_table, + nr_pfns*sizeof(unsigned long) ); - munmap( live_pfn_to_mfn_table, ((nr_pfns+1023)/1024)*PAGE_SIZE ); + munmap(live_pfn_to_mfn_table, ((nr_pfns+1023)/1024)*PAGE_SIZE); /* * Safety checking of saved context: @@ -538,20 +591,18 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) * 9. debugregs are checked by Xen. * 10. callback code selectors need checking. */ - for ( i = 0; i < 256; i++ ) { + 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_GUESTOS_CS; } - if ( (ctxt.guestos_ss & 3) == 0 ){ + if ( (ctxt.guestos_ss & 3) == 0 ) ctxt.guestos_ss = FLAT_GUESTOS_DS; - } - if ( (ctxt.event_callback_cs & 3) == 0 ){ + if ( (ctxt.event_callback_cs & 3) == 0 ) ctxt.event_callback_cs = FLAT_GUESTOS_CS; - } - if ( (ctxt.failsafe_callback_cs & 3) == 0 ){ + if ( (ctxt.failsafe_callback_cs & 3) == 0 ) ctxt.failsafe_callback_cs = FLAT_GUESTOS_CS; - } if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) || (ctxt.ldt_ents > 8192) || (ctxt.ldt_base > HYPERVISOR_VIRT_START) || @@ -568,7 +619,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* don't start the domain as we have console etc to set up */ - if( rc == 0 ) { + if ( rc == 0 ) + { /* Success: print the domain id. */ xcio_info(ioctxt, "DOM=%lu\n", dom); return 0; @@ -576,25 +628,20 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) out: - if ( (rc != 0) && (dom != 0) ){ + if ( (rc != 0) && (dom != 0) ) xc_domain_destroy(xc_handle, dom); - } - if ( mmu != NULL ){ + if ( mmu != NULL ) free(mmu); - } - if ( pm_handle >= 0 ){ + if ( pm_handle != NULL ) (void)close_pfn_mapper(pm_handle); - } - if ( pfn_to_mfn_table != NULL ){ + if ( pfn_to_mfn_table != NULL ) free(pfn_to_mfn_table); - } - if ( pfn_type != NULL ){ + if ( pfn_type != NULL ) free(pfn_type); - } - if ( rc == 0 ){ + if ( rc == 0 ) ioctxt->domain = dom; - } + DPRINTF("Restore exit with rc=%d\n",rc); return rc; } diff --git a/tools/libxc/xc_netbsd_build.c b/tools/libxc/xc_netbsd_build.c index 04a47b5068..833a533ab6 100644 --- a/tools/libxc/xc_netbsd_build.c +++ b/tools/libxc/xc_netbsd_build.c @@ -13,7 +13,7 @@ #define DPRINTF(x) #endif -static int loadelfimage(gzFile, int, unsigned long *, unsigned long, +static int loadelfimage(gzFile, void *, unsigned long *, unsigned long, unsigned long *, unsigned long *, unsigned long *, unsigned long *); @@ -77,9 +77,10 @@ static int setup_guestos(int xc_handle, shared_info_t *shared_info; unsigned long ksize; mmu_t *mmu = NULL; - int pm_handle, i; + void *pm_handle = NULL; + int i; - if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 ) + if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL ) goto error_out; if ( (page_array = malloc(tot_pages * sizeof(unsigned long))) == NULL ) @@ -201,7 +202,7 @@ static int setup_guestos(int xc_handle, error_out: if ( mmu != NULL ) free(mmu); - if ( pm_handle >= 0 ) + if ( pm_handle != NULL ) (void)close_pfn_mapper(pm_handle); if ( page_array == NULL ) free(page_array); @@ -412,7 +413,7 @@ myseek(gzFile gfd, off_t offset, int whence) #define IS_BSS(p) (p.p_filesz < p.p_memsz) static int -loadelfimage(gzFile kernel_gfd, int pm_handle, unsigned long *page_array, +loadelfimage(gzFile kernel_gfd, void *pm_handle, unsigned long *page_array, unsigned long tot_pages, unsigned long *virt_load_addr, unsigned long *ksize, unsigned long *symtab_addr, unsigned long *symtab_len) diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 344f48254d..8807f8a9bf 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -6,51 +6,140 @@ #include "xc_private.h" -int init_pfn_mapper(domid_t domid) +#define MAX_EXTENTS 8 +typedef struct { + int fd; + struct { + void *base; + unsigned long length; + } extent[MAX_EXTENTS]; +} mapper_desc_t; + +void *init_pfn_mapper(domid_t domid) { - int fd = open("/dev/mem", O_RDWR); - if ( fd >= 0 ) - (void)ioctl(fd, _IO('M', 1), (unsigned long)domid); - return fd; + int fd = open("/dev/mem", O_RDWR); + mapper_desc_t *desc; + + if ( fd < 0 ) + return NULL; + + if ( (desc = malloc(sizeof(*desc))) == NULL ) + { + close(fd); + return NULL; + } + + (void)ioctl(fd, _IO('M', 1), (unsigned long)domid); + + memset(desc, 0, sizeof(*desc)); + desc->fd = fd; + + return desc; } -int close_pfn_mapper(int pm_handle) +int close_pfn_mapper(void *pm_handle) { - return close(pm_handle); + mapper_desc_t *desc = pm_handle; + int i; + + for ( i = 0; i < MAX_EXTENTS; i++ ) + { + if ( desc->extent[i].base != NULL ) + (void)munmap(desc->extent[i].base, desc->extent[i].length); + } + + close(desc->fd); + free(desc); + + return 0; } -void *map_pfn_writeable(int pm_handle, unsigned long pfn) +static int get_free_offset(mapper_desc_t *desc) { - void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, - MAP_SHARED, pm_handle, pfn << PAGE_SHIFT); + int i; + + for ( i = 0; i < MAX_EXTENTS; i++ ) + { + if ( desc->extent[i].base == NULL ) + break; + } + + if ( i == MAX_EXTENTS ) + { + fprintf(stderr, "Extent overflow in map_pfn_*()!\n"); + fflush(stderr); + *(int*)0=0; /* XXX */ + } + + return i; +} + +void *map_pfn_writeable(void *pm_handle, unsigned long pfn) +{ + mapper_desc_t *desc = pm_handle; + void *vaddr; + int off; + + vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, desc->fd, pfn << PAGE_SHIFT); if ( vaddr == MAP_FAILED ) return NULL; + + off = get_free_offset(desc); + desc->extent[off].base = vaddr; + desc->extent[off].length = PAGE_SIZE; + return vaddr; } -void *map_pfn_readonly(int pm_handle, unsigned long pfn) +void *map_pfn_readonly(void *pm_handle, unsigned long pfn) { - void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ, - MAP_SHARED, pm_handle, pfn << PAGE_SHIFT); + mapper_desc_t *desc = pm_handle; + void *vaddr; + int off; + + vaddr = mmap(NULL, PAGE_SIZE, PROT_READ, + MAP_SHARED, desc->fd, pfn << PAGE_SHIFT); if ( vaddr == MAP_FAILED ) return NULL; + + off = get_free_offset(desc); + desc->extent[off].base = vaddr; + desc->extent[off].length = PAGE_SIZE; + return vaddr; } -void unmap_pfn(int pm_handle, void *vaddr) +void unmap_pfn(void *pm_handle, void *vaddr) { - (void)munmap(vaddr, PAGE_SIZE); + mapper_desc_t *desc = pm_handle; + int i; + unsigned long len = 0; + + for ( i = 0; i < MAX_EXTENTS; i++ ) + { + if ( desc->extent[i].base == vaddr ) + { + desc->extent[i].base = NULL; + len = desc->extent[i].length; + } + } + + if ( len == 0 ) + *(int*)0 = 0; /* XXX */ + + (void)munmap(vaddr, len); } /*******************/ -void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot, - unsigned long *arr, int num ) +void *mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot, + unsigned long *arr, int num ) { privcmd_mmapbatch_t ioctlx; void *addr; - addr = mmap( NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0 ); - if (addr) + addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0); + if ( addr != NULL ) { ioctlx.num=num; ioctlx.dom=dom; @@ -69,15 +158,15 @@ void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot, /*******************/ -void * mfn_mapper_map_single(int xc_handle, domid_t dom, - int size, int prot, - unsigned long mfn ) +void *mfn_mapper_map_single(int xc_handle, domid_t dom, + int size, int prot, + unsigned long mfn ) { privcmd_mmap_t ioctlx; privcmd_mmap_entry_t entry; void *addr; - addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 ); - if (addr) + addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0); + if ( addr != NULL ) { ioctlx.num=1; ioctlx.dom=dom; @@ -85,7 +174,7 @@ void * mfn_mapper_map_single(int xc_handle, domid_t dom, entry.va=(unsigned long) addr; entry.mfn=mfn; entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT; - if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) <0 ) + if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) < 0 ) { munmap(addr, size); return 0; diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index 742185161b..aff7a80463 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -131,11 +131,11 @@ static inline int do_multicall_op(int xc_handle, /* * PFN mapping. */ -int init_pfn_mapper(domid_t domid); -int close_pfn_mapper(int pm_handle); -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); +void *init_pfn_mapper(domid_t domid); +int close_pfn_mapper(void *pm_handle); +void *map_pfn_writeable(void *pm_handle, unsigned long pfn); +void *map_pfn_readonly(void *pm_handle, unsigned long pfn); +void unmap_pfn(void *pm_handle, void *vaddr); int get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr); unsigned long csum_page (void * page); From 38cdd514306953a19c4b522c61eec3a7ecba7942 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Wed, 30 Jun 2004 16:36:18 +0000 Subject: [PATCH 2/2] bitkeeper revision 1.1041.2.2 (40e2ec02psfxj9RKCAgBaiEIUJeF7A) Add explicit synchronous connect/disconnect methods to port objects in xend. --- tools/python/xen/lowlevel/xu/xu.c | 188 ++++++++++++---------- tools/python/xen/xend/server/SrvDaemon.py | 14 +- tools/python/xen/xend/server/channel.py | 14 +- 3 files changed, 115 insertions(+), 101 deletions(-) diff --git a/tools/python/xen/lowlevel/xu/xu.c b/tools/python/xen/lowlevel/xu/xu.c index ae11ce6885..55a5795209 100644 --- a/tools/python/xen/lowlevel/xu/xu.c +++ b/tools/python/xen/lowlevel/xu/xu.c @@ -38,9 +38,6 @@ #define EVTCHN_DEV_NAME "/dev/xen/evtchn" #define EVTCHN_DEV_MAJOR 10 #define EVTCHN_DEV_MINOR 200 -#define PORT_NORMAL 0x0000 /* A standard event notification. */ -#define PORT_EXCEPTION 0x8000 /* An exceptional notification. */ -#define PORTIDX_MASK 0x7fff /* Strip subtype to obtain port index. */ /* /dev/xen/evtchn ioctls: */ /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */ #define EVTCHN_RESET _IO('E', 1) @@ -81,7 +78,7 @@ static PyObject *xu_notifier_read(PyObject *self, PyObject *args) } if ( bytes == sizeof(v) ) - return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK); + return PyInt_FromLong(v); none: Py_INCREF(Py_None); @@ -145,7 +142,7 @@ static PyMethodDef xu_notifier_methods[] = { { "read", (PyCFunction)xu_notifier_read, METH_VARARGS, - "Read a (@port, @type) pair.\n" }, + "Read a @port with pending notifications.\n" }, { "unmask", (PyCFunction)xu_notifier_unmask, @@ -199,10 +196,6 @@ static PyObject *xu_notifier_new(PyObject *self, PyObject *args) static PyObject *xu_notifier_getattr(PyObject *obj, char *name) { - if ( strcmp(name, "EXCEPTION") == 0 ) - return PyInt_FromLong(PORT_EXCEPTION); - if ( strcmp(name, "NORMAL") == 0 ) - return PyInt_FromLong(PORT_NORMAL); return Py_FindMethod(xu_notifier_methods, obj, name); } @@ -686,43 +679,6 @@ typedef struct xu_port_object { static PyObject *port_error; -static int xup_connect(xu_port_object *xup, domid_t dom, - int local_port, int remote_port){ - // From our prespective rx = producer, tx = consumer. - int err = 0; - printf("%s> dom=%u %d:%d\n", __FUNCTION__, (unsigned int)dom, - local_port, remote_port); - - // Consumer = tx. - //xup->interface->tx_resp_prod = 0; - //xup->interface->tx_req_prod = 0; - xup->tx_resp_prod = xup->interface->tx_resp_prod; - xup->tx_req_cons = xup->interface->tx_resp_prod; - printf("%s> tx: %u %u : %u %u\n", __FUNCTION__, - (unsigned int)xup->interface->tx_resp_prod, - (unsigned int)xup->tx_resp_prod, - (unsigned int)xup->tx_req_cons, - (unsigned int)xup->interface->tx_req_prod); - - // Producer = rx. - //xup->interface->rx_req_prod = 0; - //xup->interface->rx_resp_prod = 0; - xup->rx_req_prod = xup->interface->rx_req_prod; - xup->rx_resp_cons = xup->interface->rx_resp_prod; - printf("%s> rx: %u %u : %u %u\n", __FUNCTION__, - (unsigned int)xup->rx_resp_cons, - (unsigned int)xup->interface->rx_resp_prod, - (unsigned int)xup->interface->rx_req_prod, - (unsigned int)xup->rx_req_prod); - - xup->remote_dom = dom; - xup->local_port = local_port; - xup->remote_port = remote_port; - - printf("%s< err=%d\n", __FUNCTION__, err); - return err; -} - static PyObject *xu_port_notify(PyObject *self, PyObject *args) { xu_port_object *xup = (xu_port_object *)self; @@ -913,6 +869,86 @@ static PyObject *xu_port_space_to_write_response( return PyInt_FromLong(1); } +static int __xu_port_connect(xu_port_object *xup) +{ + xc_dominfo_t info; + + if ( xup->mem_fd != -1 ) + return 0; + + if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 ) + { + PyErr_SetString(port_error, "Could not open '/dev/mem'"); + return -1; + } + + /* Set the General-Purpose Subject whose page frame will be mapped. */ + (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)xup->remote_dom); + + if ( (xc_domain_getinfo(xup->xc_handle, xup->remote_dom, 1, &info) != 1) || + (info.domid != xup->remote_dom) ) + { + PyErr_SetString(port_error, "Failed to obtain domain status"); + (void)close(xup->mem_fd); + xup->mem_fd = -1; + return -1; + } + + xup->interface = + map_control_interface(xup->mem_fd, info.shared_info_frame); + if ( xup->interface == NULL ) + { + PyErr_SetString(port_error, "Failed to map domain control interface"); + (void)close(xup->mem_fd); + xup->mem_fd = -1; + return -1; + } + + /* Synchronise ring indexes. */ + xup->tx_resp_prod = xup->interface->tx_resp_prod; + xup->tx_req_cons = xup->interface->tx_resp_prod; + xup->rx_req_prod = xup->interface->rx_req_prod; + xup->rx_resp_cons = xup->interface->rx_resp_prod; + + return 0; +} + +static void __xu_port_disconnect(xu_port_object *xup) +{ + if ( xup->mem_fd == -1 ) + return; + unmap_control_interface(xup->mem_fd, xup->interface); + (void)close(xup->mem_fd); + xup->mem_fd = -1; +} + +static PyObject *xu_port_connect(PyObject *self, PyObject *args) +{ + xu_port_object *xup = (xu_port_object *)self; + + if ( !PyArg_ParseTuple(args, "") ) + return NULL; + + if ( __xu_port_connect(xup) != 0 ) + return NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *xu_port_disconnect(PyObject *self, PyObject *args) +{ + xu_port_object *xup = (xu_port_object *)self; + + if ( !PyArg_ParseTuple(args, "") ) + return NULL; + + __xu_port_disconnect(xup); + + Py_INCREF(Py_None); + return Py_None; +} + static PyMethodDef xu_port_methods[] = { { "notify", (PyCFunction)xu_port_notify, @@ -959,6 +995,16 @@ static PyMethodDef xu_port_methods[] = { METH_VARARGS, "Returns TRUE if there is space to write a response message.\n" }, + { "connect", + (PyCFunction)xu_port_connect, + METH_VARARGS, + "Synchronously connect to remote domain.\n" }, + + { "disconnect", + (PyCFunction)xu_port_disconnect, + METH_VARARGS, + "Synchronously disconnect from remote domain.\n" }, + { NULL, NULL, 0, NULL } }; @@ -969,26 +1015,19 @@ static PyObject *xu_port_new(PyObject *self, PyObject *args) xu_port_object *xup; u32 dom; int port1, port2; - xc_dominfo_t info; if ( !PyArg_ParseTuple(args, "i", &dom) ) return NULL; xup = PyObject_New(xu_port_object, &xu_port_type); - if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 ) - { - PyErr_SetString(port_error, "Could not open '/dev/mem'"); - goto fail1; - } - - /* Set the General-Purpose Subject whose page frame will be mapped. */ - (void)ioctl(xup->mem_fd, _IO('M', 1), (unsigned long)dom); + xup->remote_dom = dom; + xup->mem_fd = -1; /* currently disconnected */ if ( (xup->xc_handle = xc_interface_open()) == -1 ) { PyErr_SetString(port_error, "Could not open Xen control interface"); - goto fail2; + goto fail1; } if ( dom == 0 ) @@ -1002,7 +1041,7 @@ static PyObject *xu_port_new(PyObject *self, PyObject *args) if ( port1 < 0 ) { PyErr_SetString(port_error, "Could not open channel to DOM0"); - goto fail3; + goto fail2; } } else if ( xc_evtchn_bind_interdomain(xup->xc_handle, @@ -1010,34 +1049,22 @@ static PyObject *xu_port_new(PyObject *self, PyObject *args) &port1, &port2) != 0 ) { PyErr_SetString(port_error, "Could not open channel to domain"); + goto fail2; + } + + xup->local_port = port1; + xup->remote_port = port2; + + if ( __xu_port_connect(xup) != 0 ) goto fail3; - } - if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) || - (info.domid != dom) ) - { - PyErr_SetString(port_error, "Failed to obtain domain status"); - goto fail4; - } - - xup->interface = - map_control_interface(xup->mem_fd, info.shared_info_frame); - if ( xup->interface == NULL ) - { - PyErr_SetString(port_error, "Failed to map domain control interface"); - goto fail4; - } - - xup_connect(xup, dom, port1, port2); return (PyObject *)xup; - - fail4: - (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1); fail3: - (void)xc_interface_close(xup->xc_handle); + if ( dom != 0 ) + (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1); fail2: - (void)close(xup->mem_fd); + (void)xc_interface_close(xup->xc_handle); fail1: PyObject_Del((PyObject *)xup); return NULL; @@ -1058,11 +1085,10 @@ static PyObject *xu_port_getattr(PyObject *obj, char *name) static void xu_port_dealloc(PyObject *self) { xu_port_object *xup = (xu_port_object *)self; - unmap_control_interface(xup->mem_fd, xup->interface); + __xu_port_disconnect(xup); if ( xup->remote_dom != 0 ) (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port); (void)xc_interface_close(xup->xc_handle); - (void)close(xup->mem_fd); PyObject_Del(self); } diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index 31ace1b84e..1f66ecc933 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -169,13 +169,10 @@ class NotifierProtocol(protocol.Protocol): def __init__(self, channelFactory): self.channelFactory = channelFactory - def notificationReceived(self, idx, type): - #print 'NotifierProtocol>notificationReceived>', idx, type + def notificationReceived(self, idx): channel = self.channelFactory.getChannel(idx) - if not channel: - return - #print 'NotifierProtocol>notificationReceived> channel', channel - channel.notificationReceived(type) + if channel: + channel.notificationReceived() def connectionLost(self, reason=None): pass @@ -251,9 +248,8 @@ class NotifierPort(abstract.FileDescriptor): notification = self.notifier.read() if not notification: break - (idx, type) = notification - self.protocol.notificationReceived(idx, type) - self.notifier.unmask(idx) + self.protocol.notificationReceived(notification) + self.notifier.unmask(notification) count += 1 #print 'NotifierPort>doRead<' diff --git a/tools/python/xen/xend/server/channel.py b/tools/python/xen/xend/server/channel.py index d68f84fa37..214020214b 100755 --- a/tools/python/xen/xend/server/channel.py +++ b/tools/python/xen/xend/server/channel.py @@ -107,22 +107,14 @@ class BaseChannel: """ return self.idx - def notificationReceived(self, type): + def notificationReceived(self): """Called when a notification is received. Closes the channel on error, otherwise calls handleNotification(type), which should be defined in a subclass. """ - #print 'notificationReceived> type=', type, self - if self.closed: return - if type == self.factory.notifier.EXCEPTION: - print 'notificationReceived> EXCEPTION' - info = xc.evtchn_status(self.idx) - if info['status'] == 'unbound': - print 'notificationReceived> EXCEPTION closing...' - self.close() - return - self.handleNotification(type) + if not self.closed: + self.handleNotification(type) def close(self): """Close the channel. Calls channelClosed() on the factory.