ia64/xen-unstable
changeset 1334:f7c9d0a33a21
bitkeeper revision 1.882 (4092efb3iUwNww3oOZDLfH3rovuyhg)
suspend uses new batched getpageinfo interface
suspend uses new batched getpageinfo interface
author | iap10@labyrinth.cl.cam.ac.uk |
---|---|
date | Sat May 01 00:30:43 2004 +0000 (2004-05-01) |
parents | 80919e3d24af |
children | 99a0fa51b992 |
files | tools/examples/xc_dom_control.py tools/xc/lib/xc_linux_save.c tools/xc/lib/xc_private.c tools/xc/lib/xc_private.h xen/common/dom0_ops.c xen/include/hypervisor-ifs/dom0_ops.h |
line diff
1.1 --- a/tools/examples/xc_dom_control.py Fri Apr 30 16:56:08 2004 +0000 1.2 +++ b/tools/examples/xc_dom_control.py Sat May 01 00:30:43 2004 +0000 1.3 @@ -137,7 +137,10 @@ elif cmd == 'suspend': 1.4 os.kill(pid, signal.SIGTERM) 1.5 1.6 xc.domain_stop( dom=dom ) 1.7 - time.sleep(0.1); 1.8 + 1.9 + while not xc.domain_getinfo( first_dom=dom, max_doms=1 )[0]['stopped']: 1.10 + time.sleep(0.1); 1.11 + 1.12 rc = xc.linux_save( dom=dom, state_file=file, progress=1) 1.13 if rc == 0 : xc.domain_destroy( dom=dom, force=1 ) 1.14
2.1 --- a/tools/xc/lib/xc_linux_save.c Fri Apr 30 16:56:08 2004 +0000 2.2 +++ b/tools/xc/lib/xc_linux_save.c Sat May 01 00:30:43 2004 +0000 2.3 @@ -10,6 +10,8 @@ 2.4 #include <asm-xen/suspend.h> 2.5 #include <zlib.h> 2.6 2.7 +#define BATCH_SIZE 512 /* 1024 pages (4MB) at a time */ 2.8 + 2.9 /* This may allow us to create a 'quiet' command-line option, if necessary. */ 2.10 #define verbose_printf(_f, _a...) \ 2.11 do { \ 2.12 @@ -38,33 +40,7 @@ 2.13 _res; \ 2.14 }) 2.15 2.16 -static int check_pfn_ownership(int xc_handle, 2.17 - unsigned long mfn, 2.18 - u64 dom) 2.19 -{ 2.20 - dom0_op_t op; 2.21 - op.cmd = DOM0_GETPAGEFRAMEINFO; 2.22 - op.u.getpageframeinfo.pfn = mfn; 2.23 - op.u.getpageframeinfo.domain = (domid_t)dom; 2.24 - return (do_dom0_op(xc_handle, &op) >= 0); 2.25 -} 2.26 2.27 -#define GETPFN_ERR (~0U) 2.28 -static unsigned int get_pfn_type(int xc_handle, 2.29 - unsigned long mfn, 2.30 - u64 dom) 2.31 -{ 2.32 - dom0_op_t op; 2.33 - op.cmd = DOM0_GETPAGEFRAMEINFO; 2.34 - op.u.getpageframeinfo.pfn = mfn; 2.35 - op.u.getpageframeinfo.domain = (domid_t)dom; 2.36 - if ( do_dom0_op(xc_handle, &op) < 0 ) 2.37 - { 2.38 - PERROR("Unexpected failure when getting page frame info!"); 2.39 - return GETPFN_ERR; 2.40 - } 2.41 - return op.u.getpageframeinfo.type; 2.42 -} 2.43 2.44 static int checked_write(gzFile fd, void *buf, size_t count) 2.45 { 2.46 @@ -281,28 +257,59 @@ int xc_linux_save(int xc_handle, 2.47 2.48 2.49 /* 2.50 - * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this 2.51 - * loop we have each MFN mapped at most once. Note that there may be MFNs 2.52 - * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP. 2.53 + * Quick sanity check. 2.54 */ 2.55 2.56 for ( i = 0; i < srec.nr_pfns; i++ ) 2.57 { 2.58 mfn = live_pfn_to_mfn_table[i]; 2.59 2.60 -#if 1 /* XXX use the master mfn_to_pfn table???? */ 2.61 - 2.62 - 2.63 if( live_mfn_to_pfn_table[mfn] != i ) 2.64 printf("i=%d mfn=%d live_mfn_to_pfn_table=%d\n", 2.65 i,mfn,live_mfn_to_pfn_table[mfn]); 2.66 + } 2.67 2.68 - /* Query page type by MFN, but store it by PFN. */ 2.69 - if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) == 2.70 - GETPFN_ERR ) 2.71 - goto out; 2.72 -#endif 2.73 + 2.74 +/* test new pfn_type stuff */ 2.75 + { 2.76 + int n, i, j; 2.77 + 2.78 + if ( mlock( pfn_type, srec.nr_pfns * sizeof(unsigned long) ) ) 2.79 + { 2.80 + ERROR("Unable to mlock"); 2.81 + goto out; 2.82 + } 2.83 + for ( n = 0; n < srec.nr_pfns; ) 2.84 + { 2.85 + 2.86 + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) 2.87 + { 2.88 + pfn_type[i] = live_pfn_to_mfn_table[i]; 2.89 + } 2.90 2.91 + if ( get_pfn_type_batch(xc_handle, domid, j, &pfn_type[n]) ) 2.92 + { 2.93 + ERROR("get_pfn_type_batch failed"); 2.94 + goto out; 2.95 + } 2.96 + 2.97 + for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ ) 2.98 + { 2.99 + 2.100 + pfn_type[i] >>= 29; 2.101 + 2.102 + if(pfn_type[i] == 7) 2.103 + { 2.104 + ERROR("bogus page"); 2.105 + goto out; 2.106 + } 2.107 + 2.108 +/* if(pfn_type[i]) 2.109 + printf("i=%d type=%d\n",i,pfn_type[i]); */ 2.110 + } 2.111 + 2.112 + n+=j; 2.113 + } 2.114 } 2.115 2.116 2.117 @@ -354,13 +361,6 @@ int xc_linux_save(int xc_handle, 2.118 goto out; 2.119 } 2.120 2.121 - /* Belts and braces safety check on the shared info record */ 2.122 - if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) ) 2.123 - { 2.124 - ERROR("Invalid shared_info_frame"); 2.125 - goto out; 2.126 - } 2.127 - 2.128 if ( !checked_write(gfd, "LinuxGuestRecord", 16) || 2.129 !checked_write(gfd, name, sizeof(name)) || 2.130 !checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) || 2.131 @@ -376,8 +376,6 @@ int xc_linux_save(int xc_handle, 2.132 2.133 verbose_printf("Saving memory pages: 0%%"); 2.134 2.135 -#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */ 2.136 - 2.137 if ( (mapper_handle2 = mfn_mapper_init(xc_handle, domid, 2.138 BATCH_SIZE*4096, PROT_READ )) 2.139 == NULL )
3.1 --- a/tools/xc/lib/xc_private.c Fri Apr 30 16:56:08 2004 +0000 3.2 +++ b/tools/xc/lib/xc_private.c Sat May 01 00:30:43 2004 +0000 3.3 @@ -168,29 +168,7 @@ void * mfn_mapper_queue_entry(mfn_mapper 3.4 3.5 /*******************/ 3.6 3.7 -typedef struct dom0_op_compact_getpageframeinfo { 3.8 - unsigned long cmd; 3.9 - unsigned long interface_version; /* DOM0_INTERFACE_VERSION */ 3.10 - dom0_getpageframeinfo_t getpageframeinfo; 3.11 -} dom0_op_compact_getpageframeinfo_t; 3.12 - 3.13 - 3.14 -typedef struct mfn_typer { 3.15 - domid_t dom; 3.16 - int max; 3.17 - int nr_multicall_ents; 3.18 - multicall_entry_t *multicall_list; 3.19 - dom0_op_compact_getpageframeinfo_t *gpf_list; 3.20 -} mfn_typer_t; 3.21 - 3.22 - 3.23 -mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ); 3.24 - 3.25 -void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ); 3.26 - 3.27 -int mfn_typer_flush_queue(mfn_typer_t *t); 3.28 - 3.29 -unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx); 3.30 +#if 0 3.31 3.32 mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ) 3.33 { 3.34 @@ -199,8 +177,8 @@ mfn_typer_t *mfn_typer_init(int xc_handl 3.35 dom0_op_compact_getpageframeinfo_t *d; 3.36 3.37 t = calloc(1, sizeof(mfn_typer_t) ); 3.38 - m = calloc(1, sizeof(multicall_entry_t)*num ); 3.39 - d = calloc(1, sizeof(dom0_op_compact_getpageframeinfo_t)*num ); 3.40 + m = calloc(num, sizeof(multicall_entry_t)); 3.41 + d = calloc(num, sizeof(dom0_op_compact_getpageframeinfo_t)); 3.42 3.43 if (!t || !m || !d) 3.44 { 3.45 @@ -210,6 +188,16 @@ mfn_typer_t *mfn_typer_init(int xc_handl 3.46 return NULL; 3.47 } 3.48 3.49 +printf("sizeof(m)=%d sizeof(d)=%d m=%p d=%p\n",sizeof(multicall_entry_t), sizeof(dom0_op_compact_getpageframeinfo_t),m,d); 3.50 + 3.51 + if ( (mlock(m, sizeof(multicall_entry_t)*num ) != 0) || 3.52 + (mlock(d, sizeof(dom0_op_compact_getpageframeinfo_t)*num ) != 0) ) 3.53 + { 3.54 + PERROR("Could not lock memory for Xen hypercall"); 3.55 + return NULL; 3.56 + } 3.57 + 3.58 + t->xc_handle = xc_handle; 3.59 t->max = num; 3.60 t->nr_multicall_ents=0; 3.61 t->multicall_list=m; 3.62 @@ -229,7 +217,7 @@ void mfn_typer_queue_entry(mfn_typer_t * 3.63 d->interface_version = DOM0_INTERFACE_VERSION; 3.64 d->getpageframeinfo.pfn = mfn; 3.65 d->getpageframeinfo.domain = t->dom; 3.66 - d->getpageframeinfo.type = ~0UL; 3.67 + d->getpageframeinfo.type = 1000; //~0UL; 3.68 3.69 m->op = __HYPERVISOR_dom0_op; 3.70 m->args[0] = (unsigned long)d; 3.71 @@ -240,7 +228,7 @@ void mfn_typer_queue_entry(mfn_typer_t * 3.72 int mfn_typer_flush_queue(mfn_typer_t *t) 3.73 { 3.74 if (t->nr_multicall_ents == 0) return 0; 3.75 - (void)HYPERVISOR_multicall(t->multicall_list, t->nr_multicall_ents); 3.76 + do_multicall_op(t->xc_handle, t->multicall_list, t->nr_multicall_ents); 3.77 t->nr_multicall_ents = 0; 3.78 } 3.79 3.80 @@ -249,6 +237,38 @@ unsigned int mfn_typer_get_result(mfn_ty 3.81 return t->gpf_list[idx].getpageframeinfo.type; 3.82 } 3.83 3.84 +#endif 3.85 + 3.86 +/* NB: arr must be mlock'ed */ 3.87 + 3.88 +int get_pfn_type_batch(int xc_handle, 3.89 + u64 dom, int num, unsigned long *arr) 3.90 +{ 3.91 + dom0_op_t op; 3.92 + op.cmd = DOM0_GETPAGEFRAMEINFO2; 3.93 + op.u.getpageframeinfo2.domain = (domid_t)dom; 3.94 + op.u.getpageframeinfo2.num = num; 3.95 + op.u.getpageframeinfo2.array = arr; 3.96 + return do_dom0_op(xc_handle, &op); 3.97 +} 3.98 + 3.99 +#define GETPFN_ERR (~0U) 3.100 +unsigned int get_pfn_type(int xc_handle, 3.101 + unsigned long mfn, 3.102 + u64 dom) 3.103 +{ 3.104 + dom0_op_t op; 3.105 + op.cmd = DOM0_GETPAGEFRAMEINFO; 3.106 + op.u.getpageframeinfo.pfn = mfn; 3.107 + op.u.getpageframeinfo.domain = (domid_t)dom; 3.108 + if ( do_dom0_op(xc_handle, &op) < 0 ) 3.109 + { 3.110 + PERROR("Unexpected failure when getting page frame info!"); 3.111 + return GETPFN_ERR; 3.112 + } 3.113 + return op.u.getpageframeinfo.type; 3.114 +} 3.115 + 3.116 3.117 3.118 /*******************/
4.1 --- a/tools/xc/lib/xc_private.h Fri Apr 30 16:56:08 2004 +0000 4.2 +++ b/tools/xc/lib/xc_private.h Sat May 01 00:30:43 2004 +0000 4.3 @@ -110,6 +110,27 @@ static inline int do_dom0_op(int xc_hand 4.4 out1: return ret; 4.5 } 4.6 4.7 +static inline int do_multicall_op(int xc_handle, 4.8 + void *call_list, int nr_calls) 4.9 +{ 4.10 + int ret = -1; 4.11 + privcmd_hypercall_t hypercall; 4.12 + 4.13 + hypercall.op = __HYPERVISOR_multicall; 4.14 + hypercall.arg[0] = (unsigned long)call_list; 4.15 + hypercall.arg[1] = (unsigned long)nr_calls; 4.16 + 4.17 + if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) 4.18 + { 4.19 + if ( errno == EACCES ) 4.20 + fprintf(stderr, "Dom0 operation failed -- need to" 4.21 + " rebuild the user-space tool set?\n"); 4.22 + goto out1; 4.23 + } 4.24 + 4.25 + out1: return ret; 4.26 +} 4.27 + 4.28 static inline int do_network_op(int xc_handle, network_op_t *op) 4.29 { 4.30 int ret = -1; 4.31 @@ -222,5 +243,31 @@ int mfn_mapper_flush_queue(mfn_mapper_t 4.32 void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 4.33 unsigned long mfn, int size ); 4.34 4.35 +/*********************/ 4.36 + 4.37 + 4.38 +#if 0 4.39 +typedef struct mfn_typer { 4.40 + domid_t dom; 4.41 + int xc_handle; 4.42 + int max; 4.43 + dom0_op_t op; 4.44 +} mfn_typer_t; 4.45 + 4.46 + 4.47 +mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num ); 4.48 + 4.49 +void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn ); 4.50 + 4.51 +int mfn_typer_flush_queue(mfn_typer_t *t); 4.52 +#endif 4.53 + 4.54 +int get_pfn_type_batch(int xc_handle, 4.55 + u64 dom, int num, unsigned long *arr); 4.56 + 4.57 +unsigned int get_pfn_type(int xc_handle, 4.58 + unsigned long mfn, 4.59 + u64 dom); 4.60 + 4.61 4.62 #endif /* __XC_PRIVATE_H__ */
5.1 --- a/xen/common/dom0_ops.c Fri Apr 30 16:56:08 2004 +0000 5.2 +++ b/xen/common/dom0_ops.c Sat May 01 00:30:43 2004 +0000 5.3 @@ -564,6 +564,84 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 5.4 } 5.5 break; 5.6 5.7 + case DOM0_GETPAGEFRAMEINFO2: 5.8 + { 5.9 +#define GPF2_BATCH 128 5.10 + int n,j; 5.11 + int num = op->u.getpageframeinfo2.num; 5.12 + domid_t dom = op->u.getpageframeinfo2.domain; 5.13 + unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array; 5.14 + struct task_struct *p; 5.15 + unsigned long l_arr[GPF2_BATCH]; 5.16 + ret = -ESRCH; 5.17 + 5.18 + if ( unlikely((p = find_domain_by_id(dom)) == NULL) ) 5.19 + break; 5.20 + 5.21 + if ( unlikely(num>1024) ) 5.22 + { 5.23 + ret = -E2BIG; 5.24 + break; 5.25 + } 5.26 + 5.27 + ret = 0; 5.28 + for(n=0;n<num;) 5.29 + { 5.30 + int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n); 5.31 + 5.32 + if( copy_from_user( l_arr, &s_ptr[n], k*sizeof(unsigned long) ) ) 5.33 + { 5.34 + ret = -EINVAL; 5.35 + break; 5.36 + } 5.37 + 5.38 + for(j=0;j<k;j++) 5.39 + { 5.40 + struct pfn_info *page; 5.41 + unsigned long mfn = l_arr[j]; 5.42 + 5.43 + if ( unlikely(mfn >= max_page) ) 5.44 + goto e2_err; 5.45 + 5.46 + page = &frame_table[mfn]; 5.47 + 5.48 + if ( likely(get_page(page, p)) ) 5.49 + { 5.50 + unsigned long type = 0; 5.51 + switch( page->type_and_flags & PGT_type_mask ) 5.52 + { 5.53 + case PGT_l1_page_table: 5.54 + case PGT_l2_page_table: 5.55 + case PGT_l3_page_table: 5.56 + case PGT_l4_page_table: 5.57 + type = page->type_and_flags & PGT_type_mask; 5.58 + 5.59 + } 5.60 + l_arr[j] |= type; 5.61 + put_page(page); 5.62 + } 5.63 + else 5.64 + { 5.65 + e2_err: 5.66 + l_arr[j] |= PGT_type_mask; /* error */ 5.67 + } 5.68 + 5.69 + } 5.70 + 5.71 + if( copy_to_user( &s_ptr[n], l_arr, k*sizeof(unsigned long) ) ) 5.72 + { 5.73 + ret = -EINVAL; 5.74 + break; 5.75 + } 5.76 + 5.77 + n+=j; 5.78 + } 5.79 + 5.80 + put_task_struct(p); 5.81 + 5.82 + } 5.83 + break; 5.84 + 5.85 default: 5.86 ret = -ENOSYS; 5.87
6.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h Fri Apr 30 16:56:08 2004 +0000 6.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h Sat May 01 00:30:43 2004 +0000 6.3 @@ -266,6 +266,16 @@ typedef struct dom0_setdomainmaxmem_st 6.4 unsigned int max_memkb; 6.5 } dom0_setdomainmaxmem_t; 6.6 6.7 +#define DOM0_GETPAGEFRAMEINFO2 29 /* batched interface */ 6.8 +typedef struct dom0_getpageframeinfo2_st 6.9 +{ 6.10 + /* IN variables. */ 6.11 + domid_t domain; /* To which domain do frames belong? */ 6.12 + int num; 6.13 + /* IN/OUT variables. */ 6.14 + unsigned long *array; 6.15 +} dom0_getpageframeinfo2_t; 6.16 + 6.17 6.18 typedef struct dom0_op_st 6.19 { 6.20 @@ -297,6 +307,7 @@ typedef struct dom0_op_st 6.21 dom0_setdomainname_t setdomainname; 6.22 dom0_setdomaininitialmem_t setdomaininitialmem; 6.23 dom0_setdomainmaxmem_t setdomainmaxmem; 6.24 + dom0_getpageframeinfo2_t getpageframeinfo2; 6.25 } u; 6.26 } dom0_op_t; 6.27