ia64/xen-unstable

changeset 1334:f7c9d0a33a21

bitkeeper revision 1.882 (4092efb3iUwNww3oOZDLfH3rovuyhg)

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