diff options
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/examples/xc_dom_control.py | 5 | ||||
-rw-r--r-- | tools/xc/lib/xc_linux_save.c | 90 | ||||
-rw-r--r-- | tools/xc/lib/xc_private.c | 74 | ||||
-rw-r--r-- | tools/xc/lib/xc_private.h | 47 |
4 files changed, 142 insertions, 74 deletions
diff --git a/tools/examples/xc_dom_control.py b/tools/examples/xc_dom_control.py index 080af6f366..4f0bd5de52 100755 --- a/tools/examples/xc_dom_control.py +++ b/tools/examples/xc_dom_control.py @@ -137,7 +137,10 @@ elif cmd == 'suspend': os.kill(pid, signal.SIGTERM) xc.domain_stop( dom=dom ) - time.sleep(0.1); + + while not xc.domain_getinfo( first_dom=dom, max_doms=1 )[0]['stopped']: + 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/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c index 0a367234de..fb6fbd6f57 100644 --- a/tools/xc/lib/xc_linux_save.c +++ b/tools/xc/lib/xc_linux_save.c @@ -10,6 +10,8 @@ #include <asm-xen/suspend.h> #include <zlib.h> +#define BATCH_SIZE 512 /* 1024 pages (4MB) at a time */ + /* This may allow us to create a 'quiet' command-line option, if necessary. */ #define verbose_printf(_f, _a...) \ do { \ @@ -38,33 +40,7 @@ _res; \ }) -static int check_pfn_ownership(int xc_handle, - unsigned long mfn, - u64 dom) -{ - dom0_op_t op; - op.cmd = DOM0_GETPAGEFRAMEINFO; - op.u.getpageframeinfo.pfn = mfn; - op.u.getpageframeinfo.domain = (domid_t)dom; - return (do_dom0_op(xc_handle, &op) >= 0); -} -#define GETPFN_ERR (~0U) -static unsigned int get_pfn_type(int xc_handle, - unsigned long mfn, - u64 dom) -{ - dom0_op_t op; - op.cmd = DOM0_GETPAGEFRAMEINFO; - op.u.getpageframeinfo.pfn = mfn; - op.u.getpageframeinfo.domain = (domid_t)dom; - if ( do_dom0_op(xc_handle, &op) < 0 ) - { - PERROR("Unexpected failure when getting page frame info!"); - return GETPFN_ERR; - } - return op.u.getpageframeinfo.type; -} static int checked_write(gzFile fd, void *buf, size_t count) { @@ -281,28 +257,59 @@ int xc_linux_save(int xc_handle, /* - * 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. + * Quick sanity check. */ for ( i = 0; i < srec.nr_pfns; i++ ) { mfn = live_pfn_to_mfn_table[i]; -#if 1 /* XXX use the master mfn_to_pfn table???? */ - - 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 +/* 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; + } } @@ -354,13 +361,6 @@ int xc_linux_save(int xc_handle, goto out; } - /* Belts and braces safety check on the shared info record */ - if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) ) - { - ERROR("Invalid shared_info_frame"); - goto out; - } - if ( !checked_write(gfd, "LinuxGuestRecord", 16) || !checked_write(gfd, name, sizeof(name)) || !checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) || @@ -376,8 +376,6 @@ int xc_linux_save(int xc_handle, verbose_printf("Saving memory pages: 0%%"); -#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 ) diff --git a/tools/xc/lib/xc_private.c b/tools/xc/lib/xc_private.c index 0c9092b607..d137176ca8 100644 --- a/tools/xc/lib/xc_private.c +++ b/tools/xc/lib/xc_private.c @@ -168,29 +168,7 @@ void * mfn_mapper_queue_entry(mfn_mapper_t *t, int 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); +#if 0 mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ) { @@ -199,8 +177,8 @@ mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ) 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 ); + m = calloc(num, sizeof(multicall_entry_t)); + d = calloc(num, sizeof(dom0_op_compact_getpageframeinfo_t)); if (!t || !m || !d) { @@ -210,6 +188,16 @@ mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ) return NULL; } +printf("sizeof(m)=%d sizeof(d)=%d m=%p d=%p\n",sizeof(multicall_entry_t), sizeof(dom0_op_compact_getpageframeinfo_t),m,d); + + if ( (mlock(m, sizeof(multicall_entry_t)*num ) != 0) || + (mlock(d, sizeof(dom0_op_compact_getpageframeinfo_t)*num ) != 0) ) + { + PERROR("Could not lock memory for Xen hypercall"); + return NULL; + } + + t->xc_handle = xc_handle; t->max = num; t->nr_multicall_ents=0; t->multicall_list=m; @@ -229,7 +217,7 @@ void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ) d->interface_version = DOM0_INTERFACE_VERSION; d->getpageframeinfo.pfn = mfn; d->getpageframeinfo.domain = t->dom; - d->getpageframeinfo.type = ~0UL; + d->getpageframeinfo.type = 1000; //~0UL; m->op = __HYPERVISOR_dom0_op; m->args[0] = (unsigned long)d; @@ -240,7 +228,7 @@ void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ) 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); + do_multicall_op(t->xc_handle, t->multicall_list, t->nr_multicall_ents); t->nr_multicall_ents = 0; } @@ -249,6 +237,38 @@ unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx) return t->gpf_list[idx].getpageframeinfo.type; } +#endif + +/* NB: arr must be mlock'ed */ + +int get_pfn_type_batch(int xc_handle, + u64 dom, int num, unsigned long *arr) +{ + dom0_op_t op; + op.cmd = DOM0_GETPAGEFRAMEINFO2; + op.u.getpageframeinfo2.domain = (domid_t)dom; + op.u.getpageframeinfo2.num = num; + op.u.getpageframeinfo2.array = arr; + return do_dom0_op(xc_handle, &op); +} + +#define GETPFN_ERR (~0U) +unsigned int get_pfn_type(int xc_handle, + unsigned long mfn, + u64 dom) +{ + dom0_op_t op; + op.cmd = DOM0_GETPAGEFRAMEINFO; + op.u.getpageframeinfo.pfn = mfn; + op.u.getpageframeinfo.domain = (domid_t)dom; + if ( do_dom0_op(xc_handle, &op) < 0 ) + { + PERROR("Unexpected failure when getting page frame info!"); + return GETPFN_ERR; + } + return op.u.getpageframeinfo.type; +} + /*******************/ diff --git a/tools/xc/lib/xc_private.h b/tools/xc/lib/xc_private.h index 198c703eaf..eaa301772d 100644 --- a/tools/xc/lib/xc_private.h +++ b/tools/xc/lib/xc_private.h @@ -110,6 +110,27 @@ static inline int do_dom0_op(int xc_handle, dom0_op_t *op) out1: return ret; } +static inline int do_multicall_op(int xc_handle, + void *call_list, int nr_calls) +{ + int ret = -1; + privcmd_hypercall_t hypercall; + + hypercall.op = __HYPERVISOR_multicall; + hypercall.arg[0] = (unsigned long)call_list; + hypercall.arg[1] = (unsigned long)nr_calls; + + if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) + { + if ( errno == EACCES ) + fprintf(stderr, "Dom0 operation failed -- need to" + " rebuild the user-space tool set?\n"); + goto out1; + } + + out1: return ret; +} + static inline int do_network_op(int xc_handle, network_op_t *op) { int ret = -1; @@ -222,5 +243,31 @@ int mfn_mapper_flush_queue(mfn_mapper_t *t); void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, unsigned long mfn, int size ); +/*********************/ + + +#if 0 +typedef struct mfn_typer { + domid_t dom; + int xc_handle; + int max; + dom0_op_t op; +} 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); +#endif + +int get_pfn_type_batch(int xc_handle, + u64 dom, int num, unsigned long *arr); + +unsigned int get_pfn_type(int xc_handle, + unsigned long mfn, + u64 dom); + #endif /* __XC_PRIVATE_H__ */ |