diff options
author | iap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk> | 2004-04-30 16:56:08 +0000 |
---|---|---|
committer | iap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk> | 2004-04-30 16:56:08 +0000 |
commit | 0780b0730b169a1ef80c7308cffc760ddc03268e (patch) | |
tree | d10f790fdb7ea8e1de43546daf43cf15e265a406 | |
parent | 33e4a0c224e38eefd0654f8627363d928247b3a6 (diff) | |
download | xen-0780b0730b169a1ef80c7308cffc760ddc03268e.tar.gz xen-0780b0730b169a1ef80c7308cffc760ddc03268e.tar.bz2 xen-0780b0730b169a1ef80c7308cffc760ddc03268e.zip |
bitkeeper revision 1.881 (409285285QhBEC23wsKBevdQUow-YA)
faster suspend
-rw-r--r-- | tools/Makefile | 4 | ||||
-rwxr-xr-x | tools/examples/xc_dom_control.py | 1 | ||||
-rw-r--r-- | tools/xc/lib/Makefile | 2 | ||||
-rw-r--r-- | tools/xc/lib/xc_linux_restore.c | 2 | ||||
-rw-r--r-- | tools/xc/lib/xc_linux_save.c | 220 | ||||
-rw-r--r-- | tools/xc/lib/xc_private.c | 126 | ||||
-rw-r--r-- | tools/xc/lib/xc_private.h | 14 | ||||
-rw-r--r-- | xen/common/kernel.c | 3 | ||||
-rw-r--r-- | xen/common/memory.c | 18 | ||||
-rw-r--r-- | xen/include/xen/sched.h | 3 | ||||
-rw-r--r-- | xen/net/dev.c | 5 | ||||
-rw-r--r-- | xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c | 9 | ||||
-rw-r--r-- | xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c | 24 | ||||
-rw-r--r-- | xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h | 1 |
14 files changed, 303 insertions, 129 deletions
diff --git a/tools/Makefile b/tools/Makefile index 0d4c43fb24..9ddf5f25a2 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -17,6 +17,10 @@ install: all $(MAKE) -C xenctl install $(MAKE) -C xend install +dist: $(TARGET) + $(MAKE) prefix=`pwd`/../../install dist=yes install + + clean: $(MAKE) -C balloon clean $(MAKE) -C xc clean diff --git a/tools/examples/xc_dom_control.py b/tools/examples/xc_dom_control.py index ea97a45f0e..080af6f366 100755 --- a/tools/examples/xc_dom_control.py +++ b/tools/examples/xc_dom_control.py @@ -137,6 +137,7 @@ elif cmd == 'suspend': os.kill(pid, signal.SIGTERM) xc.domain_stop( dom=dom ) + time.sleep(0.1); rc = xc.linux_save( dom=dom, state_file=file, progress=1) if rc == 0 : xc.domain_destroy( dom=dom, force=1 ) diff --git a/tools/xc/lib/Makefile b/tools/xc/lib/Makefile index 79dce046df..f542935167 100644 --- a/tools/xc/lib/Makefile +++ b/tools/xc/lib/Makefile @@ -4,7 +4,7 @@ MINOR = 0 SONAME = libxc.so.$(MAJOR) CC = gcc -CFLAGS = -c -Wall -O3 -fno-strict-aliasing +CFLAGS = -c -Werror -O3 -fno-strict-aliasing CFLAGS += -I../../../xen/include/hypervisor-ifs CFLAGS += -I../../xend/lib CFLAGS += -I../../../xenolinux-sparse/include diff --git a/tools/xc/lib/xc_linux_restore.c b/tools/xc/lib/xc_linux_restore.c index 239df65984..893cd0cef4 100644 --- a/tools/xc/lib/xc_linux_restore.c +++ b/tools/xc/lib/xc_linux_restore.c @@ -246,7 +246,7 @@ int xc_linux_restore(int xc_handle, { if ( (pfn = ppage[j] >> PAGE_SHIFT) >= 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 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) ) diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c index e6e8f8864d..0a367234de 100644 --- a/tools/xc/lib/xc_linux_save.c +++ b/tools/xc/lib/xc_linux_save.c @@ -24,7 +24,7 @@ */ #define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \ (((_mfn) < (1024*1024)) && \ - (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn))) + (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == (_mfn))) /* Returns TRUE if MFN is successfully converted to a PFN. */ #define translate_mfn_to_pfn(_pmfn) \ @@ -34,7 +34,7 @@ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) \ _res = 0; \ else \ - *(_pmfn) = mfn_to_pfn_table[mfn]; \ + *(_pmfn) = live_mfn_to_pfn_table[mfn]; \ _res; \ }) @@ -80,7 +80,7 @@ int xc_linux_save(int xc_handle, int verbose) { dom0_op_t op; - int rc = 1, i, j; + int rc = 1, i, j, k, n; unsigned long mfn; unsigned int prev_pc, this_pc; @@ -103,25 +103,25 @@ int xc_linux_save(int xc_handle, unsigned long *pfn_type = NULL; /* A temporary mapping, and a copy, of one frame of guest memory. */ - unsigned long *ppage, page[1024]; + unsigned long page[1024]; /* A copy of the pfn-to-mfn table frame list. */ - unsigned long *pfn_to_mfn_frame_list; - /* A live mapping of the pfn-to-mfn table frame list. */ unsigned long *live_pfn_to_mfn_frame_list; + unsigned long pfn_to_mfn_frame_list[1024]; - /* A table translating each PFN to its current MFN. */ - unsigned long *pfn_to_mfn_table = NULL; /* Live mapping of the table mapping each PFN to its current MFN. */ unsigned long *live_pfn_to_mfn_table = NULL; - /* A table translating each current MFN to its canonical PFN. */ - unsigned long *mfn_to_pfn_table = NULL; + /* Live mapping of system MFN to PFN table. */ + unsigned long *live_mfn_to_pfn_table = NULL; /* Live mapping of shared info structure */ unsigned long *live_shinfo; + /* base of the region in which domain memory is mapped */ + unsigned char *region_base; + /* A temporary mapping, and a copy, of the guest's suspend record. */ - suspend_record_t *srec; + suspend_record_t *p_srec, srec; /* The name and descriptor of the file that we are writing to. */ int fd; @@ -187,118 +187,126 @@ int xc_linux_save(int xc_handle, } - /* Map the suspend-record MFN to pin it */ - srec = mfn_mapper_map_single(xc_handle, PROT_READ, - ctxt.cpu_ctxt.esi, sizeof(*srec)); + /* Map the suspend-record MFN to pin it. The page must be owned by + domid for this to succeed. */ + p_srec = mfn_mapper_map_single(xc_handle, domid, + sizeof(srec), PROT_READ, + ctxt.cpu_ctxt.esi ); - /* Is the suspend-record MFN actually valid for this domain? */ - if ( !check_pfn_ownership(xc_handle, ctxt.cpu_ctxt.esi, domid) ) + if (!p_srec) { - ERROR("Invalid state record pointer"); + ERROR("Couldn't map state record"); goto out; } + memcpy( &srec, p_srec, sizeof(srec) ); + /* cheesy sanity check */ - if ( srec->nr_pfns > 1024*1024 ) + if ( srec.nr_pfns > 1024*1024 ) { ERROR("Invalid state record -- pfn count out of range"); goto out; } - /* the pfn_to_mfn_frame_list fits in a single page */ live_pfn_to_mfn_frame_list = - mfn_mapper_map_single(xc_handle, PROT_WRITE, - srec->pfn_to_mfn_frame_list, - PAGE_SIZE); + mfn_mapper_map_single(xc_handle, domid, + PAGE_SIZE, PROT_READ, + srec.pfn_to_mfn_frame_list ); - if ( !check_pfn_ownership(xc_handle, - srec->pfn_to_mfn_frame_list, domid) ) + if (!live_pfn_to_mfn_frame_list) { - ERROR("Invalid pfn-to-mfn frame list pointer"); - goto out; + ERROR("Couldn't map pfn_to_mfn_frame_list"); + goto out; } + - memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE ); - - if ( (mapper_handle1 = mfn_mapper_init(xc_handle, 1024*1024, PROT_READ )) + if ( (mapper_handle1 = mfn_mapper_init(xc_handle, domid, + 1024*1024, PROT_READ )) == NULL ) goto out; - for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ ) + for ( i = 0; i < (srec.nr_pfns+1023)/1024; i++ ) { /* Grab a copy of the pfn-to-mfn table frame list. This has the effect of preventing the page from being freed and given to another domain. (though the domain is stopped anyway...) */ mfn_mapper_queue_entry( mapper_handle1, i<<PAGE_SHIFT, - pfn_to_mfn_frame_list[i], + live_pfn_to_mfn_frame_list[i], PAGE_SIZE ); } - mfn_mapper_flush_queue(mapper_handle1); - - /* Now they're pined, check they're the right dom. We assume - they're not going to change, otherwise the suspend is going to fail, - with only itself to blame. */ - - for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ ) + if ( mfn_mapper_flush_queue(mapper_handle1) ) { - if ( !check_pfn_ownership(xc_handle, - pfn_to_mfn_frame_list[i], domid) ) - { - ERROR("Invalid pfn-to-mfn frame list pointer"); - goto out; - } + ERROR("Couldn't map pfn_to_mfn table"); + goto out; } live_pfn_to_mfn_table = mfn_mapper_base( mapper_handle1 ); + + /* We want zeroed memory so use calloc rather than malloc. */ - mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024); - pfn_to_mfn_table = calloc(1, 4 * srec->nr_pfns); - pfn_type = calloc(1, 4 * srec->nr_pfns); + pfn_type = calloc(1, 4 * srec.nr_pfns); - if ( (mfn_to_pfn_table == NULL) || - (pfn_to_mfn_table == NULL) || - (pfn_type == NULL) ) + if ( (pfn_type == NULL) ) { errno = ENOMEM; goto out; } + + /* Track the mfn_to_pfn table down from the domains PT */ + { + unsigned long *pgd; + unsigned long mfn_to_pfn_table_start_mfn; + + 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 ); + } + + /* * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this * loop we have each MFN mapped at most once. Note that there may be MFNs * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP. */ - for ( i = 0; i < srec->nr_pfns; i++ ) + for ( i = 0; i < srec.nr_pfns; i++ ) { mfn = live_pfn_to_mfn_table[i]; - if ( !check_pfn_ownership(xc_handle, mfn, domid) ) - { - ERROR("Invalid frame specified with pfn-to-mfn table"); - goto out; - } +#if 1 /* XXX use the master mfn_to_pfn table???? */ - /* Did we map this MFN already? That would be invalid! */ - if ( mfn_to_pfn_table[mfn] ) - { - ERROR("A machine frame appears twice in pseudophys space"); - goto out; - } - mfn_to_pfn_table[mfn] = i; - pfn_to_mfn_table[i] = live_pfn_to_mfn_table[i]; + if( live_mfn_to_pfn_table[mfn] != i ) + printf("i=%d mfn=%d live_mfn_to_pfn_table=%d\n", + i,mfn,live_mfn_to_pfn_table[mfn]); /* Query page type by MFN, but store it by PFN. */ if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) == GETPFN_ERR ) goto out; +#endif + } + + /* Canonicalise the suspend-record frame number. */ if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ) { @@ -322,9 +330,10 @@ int xc_linux_save(int xc_handle, ERROR("PT base is not in range of pseudophys map"); goto out; } - ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT; + ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT; /* Canonicalise the pfn-to-mfn table frame-number list. */ + memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE ); for ( i = 0; i < srec.nr_pfns; i += 1024 ) { if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ) @@ -335,8 +344,15 @@ int xc_linux_save(int xc_handle, } /* Start writing out the saved-domain record. */ - live_shinfo = mfn_mapper_map_single(xc_handle, PROT_READ, - shared_info_frame, PAGE_SIZE); + live_shinfo = mfn_mapper_map_single(xc_handle, domid, + PAGE_SIZE, PROT_READ, + shared_info_frame); + + if (!live_shinfo) + { + ERROR("Couldn't map live_shinfo"); + goto out; + } /* Belts and braces safety check on the shared info record */ if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) ) @@ -360,7 +376,9 @@ int xc_linux_save(int xc_handle, verbose_printf("Saving memory pages: 0%%"); - if ( (mapper_handle2 = mfn_mapper_init(xc_handle, +#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */ + + if ( (mapper_handle2 = mfn_mapper_init(xc_handle, domid, BATCH_SIZE*4096, PROT_READ )) == NULL ) goto out; @@ -383,12 +401,19 @@ int xc_linux_save(int xc_handle, { /* queue up mappings for all of the pages in this batch */ +//printf("region n=%d j=%d i=%d mfn=%d\n",n,j,i,live_pfn_to_mfn_table[i]); mfn_mapper_queue_entry( mapper_handle2, j<<PAGE_SHIFT, - pfn_to_mfn_frame_list[i], + live_pfn_to_mfn_table[i], PAGE_SIZE ); } - mfn_mapper_flush_queue(mapper_handle2); - + + if( mfn_mapper_flush_queue(mapper_handle2) ) + { + ERROR("Couldn't map page region"); + goto out; + } + +#if 0 typer_handle = get_type_init( xc_handle, BATCH_SIZE ) for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) @@ -399,42 +424,51 @@ int xc_linux_save(int xc_handle, pfn_to_mfn_frame_list[i] ); } - region_type = get_type; +#endif + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) { /* write out pages in batch */ - mfn = pfn_to_mfn_table[i]; - - ppage = map_pfn_readonly(pm_handle, mfn); - memcpy(page, ppage, PAGE_SIZE); - unmap_pfn(pm_handle, ppage); - if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) ) { - for ( j = 0; - j < ((pfn_type[i] == L2TAB) ? + + memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE); + + for ( k = 0; + k < ((pfn_type[i] == L2TAB) ? (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); - j++ ) + k++ ) { - if ( !(page[j] & _PAGE_PRESENT) ) continue; - mfn = page[j] >> PAGE_SHIFT; + if ( !(page[k] & _PAGE_PRESENT) ) continue; + mfn = page[k] >> PAGE_SHIFT; if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) { ERROR("Frame number in pagetable page is invalid"); goto out; } - page[j] &= PAGE_SIZE - 1; - page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT; + page[k] &= PAGE_SIZE - 1; + page[k] |= live_mfn_to_pfn_table[mfn] << PAGE_SHIFT; + + } + + if ( !checked_write(gfd, page, PAGE_SIZE) ) + { + ERROR("Error when writing to state file"); + goto out; } - } - if ( !checked_write(gfd, page, PAGE_SIZE) ) + + } + else { - ERROR("Error when writing to state file"); - goto out; + if ( !checked_write(gfd, region_base + (PAGE_SIZE*j), PAGE_SIZE) ) + { + ERROR("Error when writing to state file"); + goto out; + } } } @@ -450,6 +484,7 @@ out: /* Restart the domain if we had to stop it to save its state. */ if ( we_stopped_it ) { + printf("Restart domain\n"); op.cmd = DOM0_STARTDOMAIN; op.u.startdomain.domain = (domid_t)domid; (void)do_dom0_op(xc_handle, &op); @@ -457,13 +492,6 @@ out: gzclose(gfd); - if ( pm_handle >= 0 ) - (void)close_pfn_mapper(pm_handle); - - if ( pfn_to_mfn_table != NULL ) - free(pfn_to_mfn_table); - if ( mfn_to_pfn_table != NULL ) - free(mfn_to_pfn_table); if ( pfn_type != NULL ) free(pfn_type); diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c index 796da64ad7..0c9092b607 100644 --- a/tools/xc/lib/xc_private.c +++ b/tools/xc/lib/xc_private.c @@ -47,8 +47,9 @@ void unmap_pfn(int pm_handle, void *vaddr) /*******************/ -void * mfn_mapper_map_single(int xc_handle, int prot, - unsigned long mfn, int size) +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; @@ -57,6 +58,7 @@ void * mfn_mapper_map_single(int xc_handle, int prot, if (addr) { ioctlx.num=1; + ioctlx.dom=dom; ioctlx.entry=&entry; entry.va=(unsigned long) addr; entry.mfn=mfn; @@ -67,7 +69,7 @@ void * mfn_mapper_map_single(int xc_handle, int prot, return addr; } -mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot) +mfn_mapper_t * mfn_mapper_init(int xc_handle, domid_t dom, int size, int prot) { mfn_mapper_t * t; t = calloc( 1, sizeof(mfn_mapper_t)+ @@ -76,6 +78,7 @@ mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot) t->xc_handle = xc_handle; t->size = size; t->prot = prot; + t->error = 0; t->max_queue_size = mfn_mapper_queue_size; t->addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 ); if (!t->addr) @@ -84,6 +87,7 @@ mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot) return NULL; } t->ioctl.num = 0; + t->ioctl.dom = dom; t->ioctl.entry = (privcmd_mmap_entry_t *) &t[1]; return t; } @@ -99,14 +103,29 @@ void mfn_mapper_close(mfn_mapper_t *t) free(t); } +static int __mfn_mapper_flush_queue(mfn_mapper_t *t) +{ + int rc; + rc = ioctl( t->xc_handle, IOCTL_PRIVCMD_MMAP, &t->ioctl ); + t->ioctl.num = 0; + if(rc && !t->error) + t->error = rc; + return rc; +} + int mfn_mapper_flush_queue(mfn_mapper_t *t) { int rc; + + rc = __mfn_mapper_flush_queue(t); - rc = ioctl( t->xc_handle, IOCTL_PRIVCMD_MMAP, &t->ioctl ); - if (rc<0) return rc; - t->ioctl.num = 0; - return 0; + if ( t->error ) + { + rc = t->error; + } + + t->error = 0; + return rc; } void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, @@ -123,30 +142,113 @@ void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, { prev = &t->ioctl.entry[t->ioctl.num-1]; - if ( (prev->va+(prev->npages*PAGE_SIZE)) == (t->addr+offset) && + if ( (prev->va+(prev->npages*PAGE_SIZE)) == + ((unsigned long)t->addr+offset) && (prev->mfn+prev->npages) == mfn ) { prev->npages += pages; -printf("merge\n"); return t->addr+offset; } } - entry->va = t->addr+offset; + entry->va = (unsigned long)t->addr+offset; entry->mfn = mfn; entry->npages = pages; t->ioctl.num++; if(t->ioctl.num == t->max_queue_size) { - if ( mfn_mapper_flush_queue(t) ) - return 0; + if ( __mfn_mapper_flush_queue(t) ) + return 0; } return t->addr+offset; } +/*******************/ + +typedef struct dom0_op_compact_getpageframeinfo { + unsigned long cmd; + unsigned long interface_version; /* DOM0_INTERFACE_VERSION */ + dom0_getpageframeinfo_t getpageframeinfo; +} dom0_op_compact_getpageframeinfo_t; + + +typedef struct mfn_typer { + domid_t dom; + int max; + int nr_multicall_ents; + multicall_entry_t *multicall_list; + dom0_op_compact_getpageframeinfo_t *gpf_list; +} mfn_typer_t; + + +mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ); + +void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ); + +int mfn_typer_flush_queue(mfn_typer_t *t); + +unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx); + +mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ) +{ + mfn_typer_t *t; + multicall_entry_t *m; + dom0_op_compact_getpageframeinfo_t *d; + + t = calloc(1, sizeof(mfn_typer_t) ); + m = calloc(1, sizeof(multicall_entry_t)*num ); + d = calloc(1, sizeof(dom0_op_compact_getpageframeinfo_t)*num ); + + if (!t || !m || !d) + { + if(t) free(t); + if(m) free(m); + if(d) free(d); + return NULL; + } + + t->max = num; + t->nr_multicall_ents=0; + t->multicall_list=m; + t->gpf_list=d; + t->dom = dom; + + return t; +} + +void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ) +{ + int i = t->nr_multicall_ents; + multicall_entry_t *m = &t->multicall_list[i]; + dom0_op_compact_getpageframeinfo_t *d = &t->gpf_list[i]; + + d->cmd = DOM0_GETPAGEFRAMEINFO; + d->interface_version = DOM0_INTERFACE_VERSION; + d->getpageframeinfo.pfn = mfn; + d->getpageframeinfo.domain = t->dom; + d->getpageframeinfo.type = ~0UL; + + m->op = __HYPERVISOR_dom0_op; + m->args[0] = (unsigned long)d; + + t->nr_multicall_ents++; +} + +int mfn_typer_flush_queue(mfn_typer_t *t) +{ + if (t->nr_multicall_ents == 0) return 0; + (void)HYPERVISOR_multicall(t->multicall_list, t->nr_multicall_ents); + t->nr_multicall_ents = 0; +} + +unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx) +{ + return t->gpf_list[idx].getpageframeinfo.type; +} + /*******************/ diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h index d173e58e46..198c703eaf 100644 --- a/tools/xc/lib/xc_private.h +++ b/tools/xc/lib/xc_private.h @@ -16,8 +16,6 @@ #include "xc.h" -#include <asm-xen/proc_cmd.h> - /* from xen/include/hypervisor-ifs */ #include <hypervisor-if.h> #include <dom0_ops.h> @@ -25,6 +23,10 @@ #include <event_channel.h> #include <sched_ctl.h> +#include <asm-xen/proc_cmd.h> + + + /* from xend/lib */ #include <domain_controller.h> @@ -188,6 +190,7 @@ typedef struct privcmd_mmap_entry { typedef struct privcmd_mmap { int num; + domid_t dom; privcmd_mmap_entry_t *entry; } privcmd_mmap_t; */ @@ -198,16 +201,17 @@ typedef struct mfn_mapper { int xc_handle; int size; int prot; + int error; int max_queue_size; void * addr; privcmd_mmap_t ioctl; } mfn_mapper_t; -void * mfn_mapper_map_single(int xc_handle, int prot, - unsigned long mfn, int size); +void * mfn_mapper_map_single(int xc_handle, domid_t dom, int size, int prot, + unsigned long mfn ); -mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot); +mfn_mapper_t * mfn_mapper_init(int xc_handle, domid_t dom, int size, int prot); void * mfn_mapper_base(mfn_mapper_t *t); diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 3c10cf3ca2..d8d5d03251 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -255,6 +255,9 @@ void cmain(unsigned long magic, multiboot_info_t *mbi) start_of_day(); + /* Add CPU0 idle task to the task hash list */ + task_hash[TASK_HASH(IDLE_DOMAIN_ID)] = &idle0_task; + /* Create initial domain 0. */ dom0_params.memory_kb = opt_dom0_mem; new_dom = do_createdomain(0, 0); diff --git a/xen/common/memory.c b/xen/common/memory.c index 1ffc207bdf..ed2e5b6e17 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -194,6 +194,9 @@ static struct { */ void __init init_frametable(unsigned long nr_pages) { + int i; + unsigned long mfn; + memset(percpu_info, 0, sizeof(percpu_info)); max_page = nr_pages; @@ -206,8 +209,20 @@ void __init init_frametable(unsigned long nr_pages) INIT_LIST_HEAD(&free_list); free_pfns = 0; + /* so that we can map them latter, set the ownership of pages + belonging to the machine_to_phys_mapping to CPU0 idle task */ + + mfn = virt_to_phys((void *)RDWR_MPT_VIRT_START)>>PAGE_SHIFT; +// for(i=0;i<nr_pages;i+=1024,mfn++) + for(i=0;i<1024*1024;i+=1024,mfn++) + { + frame_table[mfn].count_and_flags = 1 | PGC_allocated; + frame_table[mfn].type_and_flags = 1 | PGT_gdt_page; // anything non RW + frame_table[mfn].u.domain = &idle0_task; + } } + void add_to_domain_alloc_list(unsigned long ps, unsigned long pe) { struct pfn_info *pf; @@ -895,7 +910,8 @@ static int do_extended_command(unsigned long ptr, unsigned long val) break; case MMUEXT_SET_SUBJECTDOM_H: - percpu_info[cpu].subject_id |= (domid_t)((ptr&~0xFFFF)|(val>>16))<<32; + percpu_info[cpu].subject_id |= ((domid_t)((ptr&~0xFFFF)|(val>>16)))<<32; + if ( !IS_PRIV(current) ) { MEM_LOG("Dom %llu has no privilege to set subject domain", diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 14f4019ac1..c9b072aaa0 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -209,7 +209,8 @@ struct task_struct mm: IDLE0_MM, \ addr_limit: KERNEL_DS, \ thread: INIT_THREAD, \ - flags: 1<<PF_IDLETASK \ + flags: 1<<PF_IDLETASK, \ + refcnt: ATOMIC_INIT(1) \ } extern struct task_struct idle0_task; diff --git a/xen/net/dev.c b/xen/net/dev.c index e4e1092840..5ab01092f0 100644 --- a/xen/net/dev.c +++ b/xen/net/dev.c @@ -2156,8 +2156,9 @@ static void get_rx_bufs(net_vif_t *vif) 0) != (PGC_allocated | PGC_tlb_flush_on_type_change | 2)) ) { - DPRINTK("Page held more than once %08x\n", - buf_page->count_and_flags); + DPRINTK("Page held more than once %08x %s\n", + buf_page->count_and_flags, + (buf_page->u.domain)?buf_page->u.domain->name:"None"); if ( !get_page_type(buf_page, PGT_writeable_page) ) put_page(buf_page); else if ( cmpxchg(ptep, pte & ~_PAGE_PRESENT, pte) != diff --git a/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c b/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c index a94b016fb7..4e507081be 100644 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c @@ -67,7 +67,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, #define PRIVCMD_MMAP_SZ 32 privcmd_mmap_t mmapcmd; privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p; - int i; + int i, rc; if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) ) return -EFAULT; @@ -95,12 +95,13 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, if (msg[j].va + (msg[j].npages<<PAGE_SHIFT) > vma->vm_end) return -EINVAL; - if (direct_remap_area_pages(vma->vm_mm, + if (rc = direct_remap_area_pages(vma->vm_mm, msg[j].va&PAGE_MASK, msg[j].mfn<<PAGE_SHIFT, msg[j].npages<<PAGE_SHIFT, - vma->vm_page_prot)) - return -EINVAL; + vma->vm_page_prot, + mmapcmd.dom)) + return rc; } } ret = 0; diff --git a/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c b/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c index 6474d4c6ed..7b4d1ff0a9 100644 --- a/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c +++ b/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c @@ -27,7 +27,7 @@ #define direct_mk_pte_phys(physpage, pgprot) \ __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot) -static inline void direct_remap_area_pte(pte_t *pte, +static inline int direct_remap_area_pte(pte_t *pte, unsigned long address, unsigned long size, unsigned long machine_addr, @@ -39,6 +39,9 @@ static inline void direct_remap_area_pte(pte_t *pte, mmu_update_t *u, *v; u = v = vmalloc(3*PAGE_SIZE); /* plenty */ + if (!u) + return -ENOMEM; + /* If not I/O mapping then specify General-Purpose Subject Domain (GPS). */ if ( domid != 0 ) { @@ -74,10 +77,15 @@ static inline void direct_remap_area_pte(pte_t *pte, pte++; } while (address && (address < end)); - if ( ((v-u) != 0) && (HYPERVISOR_mmu_update(u, v-u) < 0) ) + if ( ((v-u) > 2) && (HYPERVISOR_mmu_update(u, v-u) < 0) ) + { printk(KERN_WARNING "Failed to ioremap %08lx->%08lx (%08lx)\n", end-size, end, machine_addr-size); + return -EINVAL; + } + vfree(u); + return 0; } static inline int direct_remap_area_pmd(struct mm_struct *mm, @@ -89,6 +97,7 @@ static inline int direct_remap_area_pmd(struct mm_struct *mm, domid_t domid) { unsigned long end; + int rc; address &= ~PGDIR_MASK; end = address + size; @@ -101,8 +110,11 @@ static inline int direct_remap_area_pmd(struct mm_struct *mm, pte_t * pte = pte_alloc(mm, pmd, address); if (!pte) return -ENOMEM; - direct_remap_area_pte(pte, address, end - address, - address + machine_addr, prot, domid); + + if ( rc = direct_remap_area_pte(pte, address, end - address, + address + machine_addr, prot, domid) ) + return rc; + address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address && (address < end)); @@ -120,8 +132,8 @@ int direct_remap_area_pages(struct mm_struct *mm, pgd_t * dir; unsigned long end = address + size; -printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n", - address, machine_addr, size); +/*printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n", + address, machine_addr, size);*/ machine_addr -= address; dir = pgd_offset(mm, address); diff --git a/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h b/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h index 205355fa9c..30cec9aff5 100644 --- a/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h +++ b/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h @@ -21,6 +21,7 @@ typedef struct privcmd_mmap_entry { typedef struct privcmd_mmap { int num; + domid_t dom; /* target domain */ privcmd_mmap_entry_t *entry; } privcmd_mmap_t; |