direct-io.hg

changeset 5699:eef23f57f20e

The attached patch adds a new dom0_op, DOM0_GETDOMAININFOLIST. This
operation allows retrieval of the domain info structures for all domains
in one hypercall.

Using a small test program, on a system with 97 domains with
non-contiguous domain IDs, I found that with this hypercall I could
retrieve the full array of info structures 12840 times per second, an
improvement from 2380 times per second with the DOM0_GETDOMAININFO op.

The patch also adds a libxc wrapper for this new hypercall.

Signed-off-by: Josh Triplett <josht@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Jul 08 09:06:04 2005 +0000 (2005-07-08)
parents 20ff6c7413d8
children 579d1e771025
files tools/libxc/xc.h tools/libxc/xc_domain.c xen/common/dom0_ops.c xen/include/public/dom0_ops.h
line diff
     1.1 --- a/tools/libxc/xc.h	Fri Jul 08 08:48:46 2005 +0000
     1.2 +++ b/tools/libxc/xc.h	Fri Jul 08 09:06:04 2005 +0000
     1.3 @@ -192,6 +192,24 @@ int xc_domain_getinfo(int xc_handle,
     1.4                        xc_dominfo_t *info);
     1.5  
     1.6  /**
     1.7 + * This function will return information about one or more domains, using a
     1.8 + * single hypercall.  The domain information will be stored into the supplied
     1.9 + * array of xc_domaininfo_t structures.
    1.10 + *
    1.11 + * @parm xc_handle a handle to an open hypervisor interface
    1.12 + * @parm first_domain the first domain to enumerate information from.
    1.13 + *                    Domains are currently enumerate in order of creation.
    1.14 + * @parm max_domains the number of elements in info
    1.15 + * @parm info an array of max_doms size that will contain the information for
    1.16 + *            the enumerated domains.
    1.17 + * @return the number of domains enumerated or -1 on error
    1.18 + */
    1.19 +int xc_domain_getinfolist(int xc_handle,
    1.20 +                          u32 first_domain,
    1.21 +                          unsigned int max_domains,
    1.22 +                          xc_domaininfo_t *info);
    1.23 +
    1.24 +/**
    1.25   * This function returns information about one domain.  This information is
    1.26   * more detailed than the information from xc_domain_getinfo().
    1.27   *
     2.1 --- a/tools/libxc/xc_domain.c	Fri Jul 08 08:48:46 2005 +0000
     2.2 +++ b/tools/libxc/xc_domain.c	Fri Jul 08 09:06:04 2005 +0000
     2.3 @@ -125,6 +125,33 @@ int xc_domain_getinfo(int xc_handle,
     2.4      return nr_doms;
     2.5  }
     2.6  
     2.7 +int xc_domain_getinfolist(int xc_handle,
     2.8 +                          u32 first_domain,
     2.9 +                          unsigned int max_domains,
    2.10 +                          xc_domaininfo_t *info)
    2.11 +{
    2.12 +    int ret = 0;
    2.13 +    dom0_op_t op;
    2.14 +
    2.15 +    if(mlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0)
    2.16 +        return -1;
    2.17 +    
    2.18 +    op.cmd = DOM0_GETDOMAININFOLIST;
    2.19 +    op.u.getdomaininfolist.first_domain = first_domain;
    2.20 +    op.u.getdomaininfolist.max_domains  = max_domains;
    2.21 +    op.u.getdomaininfolist.buffer       = info;
    2.22 +
    2.23 +    if(xc_dom0_op(xc_handle, &op) < 0)
    2.24 +        ret = -1;
    2.25 +    else
    2.26 +        ret = op.u.getdomaininfolist.num_domains;
    2.27 +    
    2.28 +    if(munlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0)
    2.29 +        ret = -1;
    2.30 +    
    2.31 +    return ret;
    2.32 +}
    2.33 +
    2.34  int xc_domain_get_vcpu_context(int xc_handle,
    2.35                                 u32 domid,
    2.36                                 u32 vcpu,
     3.1 --- a/xen/common/dom0_ops.c	Fri Jul 08 08:48:46 2005 +0000
     3.2 +++ b/xen/common/dom0_ops.c	Fri Jul 08 09:06:04 2005 +0000
     3.3 @@ -88,6 +88,60 @@ static int allocate_domid(domid_t *pdom)
     3.4      return err;
     3.5  }
     3.6  
     3.7 +static void getdomaininfo(struct domain *d, dom0_getdomaininfo_t *info)
     3.8 +{
     3.9 +    struct vcpu   *v;
    3.10 +    u64 cpu_time = 0;
    3.11 +    int vcpu_count = 0;
    3.12 +    int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
    3.13 +    
    3.14 +    info->domain = d->domain_id;
    3.15 +    
    3.16 +    memset(&info->vcpu_to_cpu, -1, sizeof(info->vcpu_to_cpu));
    3.17 +    memset(&info->cpumap, 0, sizeof(info->cpumap));
    3.18 +    
    3.19 +    /* 
    3.20 +     * - domain is marked as paused or blocked only if all its vcpus 
    3.21 +     *   are paused or blocked 
    3.22 +     * - domain is marked as running if any of its vcpus is running
    3.23 +     * - only map vcpus that aren't down.  Note, at some point we may
    3.24 +     *   wish to demux the -1 value to indicate down vs. not-ever-booted
    3.25 +     *   
    3.26 +     */
    3.27 +    for_each_vcpu ( d, v ) {
    3.28 +        /* only map vcpus that are up */
    3.29 +        if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
    3.30 +            info->vcpu_to_cpu[v->vcpu_id] = v->processor;
    3.31 +        info->cpumap[v->vcpu_id] = v->cpumap;
    3.32 +        if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
    3.33 +            flags &= ~DOMFLAGS_PAUSED;
    3.34 +        if ( !(v->vcpu_flags & VCPUF_blocked) )
    3.35 +            flags &= ~DOMFLAGS_BLOCKED;
    3.36 +        if ( v->vcpu_flags & VCPUF_running )
    3.37 +            flags |= DOMFLAGS_RUNNING;
    3.38 +        if ( v->cpu_time > cpu_time )
    3.39 +            cpu_time += v->cpu_time;
    3.40 +        vcpu_count++;
    3.41 +    }
    3.42 +    
    3.43 +    info->cpu_time = cpu_time;
    3.44 +    info->n_vcpu = vcpu_count;
    3.45 +    
    3.46 +    info->flags = flags |
    3.47 +        ((d->domain_flags & DOMF_dying)    ? DOMFLAGS_DYING    : 0) |
    3.48 +        ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
    3.49 +        d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
    3.50 +
    3.51 +    if (d->ssid != NULL)
    3.52 +        info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
    3.53 +    else    
    3.54 +        info->ssidref = ACM_DEFAULT_SSID;
    3.55 +    
    3.56 +    info->tot_pages         = d->tot_pages;
    3.57 +    info->max_pages         = d->max_pages;
    3.58 +    info->shared_info_frame = __pa(d->shared_info) >> PAGE_SHIFT;
    3.59 +}
    3.60 +
    3.61  long do_dom0_op(dom0_op_t *u_dom0_op)
    3.62  {
    3.63      long ret = 0;
    3.64 @@ -306,10 +360,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
    3.65      case DOM0_GETDOMAININFO:
    3.66      { 
    3.67          struct domain *d;
    3.68 -        struct vcpu   *v;
    3.69 -        u64 cpu_time = 0;
    3.70 -        int vcpu_count = 0;
    3.71 -        int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
    3.72  
    3.73          read_lock(&domlist_lock);
    3.74  
    3.75 @@ -328,54 +378,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
    3.76  
    3.77          read_unlock(&domlist_lock);
    3.78  
    3.79 -        op->u.getdomaininfo.domain = d->domain_id;
    3.80 -
    3.81 -        memset(&op->u.getdomaininfo.vcpu_to_cpu, -1,
    3.82 -               sizeof(op->u.getdomaininfo.vcpu_to_cpu));
    3.83 -        memset(&op->u.getdomaininfo.cpumap, 0,
    3.84 -               sizeof(op->u.getdomaininfo.cpumap));
    3.85 -
    3.86 -        /* 
    3.87 -         * - domain is marked as paused or blocked only if all its vcpus 
    3.88 -         *   are paused or blocked 
    3.89 -         * - domain is marked as running if any of its vcpus is running
    3.90 -         * - only map vcpus that aren't down.  Note, at some point we may
    3.91 -         *   wish to demux the -1 value to indicate down vs. not-ever-booted
    3.92 -         *   
    3.93 -         */
    3.94 -        for_each_vcpu ( d, v ) {
    3.95 -            /* only map vcpus that are up */
    3.96 -            if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
    3.97 -                op->u.getdomaininfo.vcpu_to_cpu[v->vcpu_id] = v->processor;
    3.98 -            op->u.getdomaininfo.cpumap[v->vcpu_id]      = v->cpumap;
    3.99 -            if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
   3.100 -                flags &= ~DOMFLAGS_PAUSED;
   3.101 -            if ( !(v->vcpu_flags & VCPUF_blocked) )
   3.102 -                flags &= ~DOMFLAGS_BLOCKED;
   3.103 -            if ( v->vcpu_flags & VCPUF_running )
   3.104 -                flags |= DOMFLAGS_RUNNING;
   3.105 -            if ( v->cpu_time > cpu_time )
   3.106 -                cpu_time += v->cpu_time;
   3.107 -            vcpu_count++;
   3.108 -        }
   3.109 -
   3.110 -        op->u.getdomaininfo.cpu_time = cpu_time;
   3.111 -        op->u.getdomaininfo.n_vcpu = vcpu_count;
   3.112 -
   3.113 -        op->u.getdomaininfo.flags = flags |
   3.114 -            ((d->domain_flags & DOMF_dying)    ? DOMFLAGS_DYING    : 0) |
   3.115 -            ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
   3.116 -            d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
   3.117 -
   3.118 -        if (d->ssid != NULL)
   3.119 -            op->u.getdomaininfo.ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
   3.120 -        else    
   3.121 -            op->u.getdomaininfo.ssidref = ACM_DEFAULT_SSID;
   3.122 -
   3.123 -        op->u.getdomaininfo.tot_pages   = d->tot_pages;
   3.124 -        op->u.getdomaininfo.max_pages   = d->max_pages;
   3.125 -        op->u.getdomaininfo.shared_info_frame = 
   3.126 -            __pa(d->shared_info) >> PAGE_SHIFT;
   3.127 +        getdomaininfo(d, &op->u.getdomaininfo);
   3.128  
   3.129          if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )     
   3.130              ret = -EINVAL;
   3.131 @@ -384,6 +387,53 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   3.132      }
   3.133      break;
   3.134  
   3.135 +    case DOM0_GETDOMAININFOLIST:
   3.136 +    { 
   3.137 +        struct domain *d;
   3.138 +        dom0_getdomaininfo_t info;
   3.139 +        dom0_getdomaininfo_t *buffer = op->u.getdomaininfolist.buffer;
   3.140 +        u32 num_domains = 0;
   3.141 +
   3.142 +        read_lock(&domlist_lock);
   3.143 +
   3.144 +        for_each_domain ( d )
   3.145 +        {
   3.146 +            if ( d->domain_id < op->u.getdomaininfolist.first_domain )
   3.147 +                continue;
   3.148 +            if ( num_domains == op->u.getdomaininfolist.max_domains )
   3.149 +                break;
   3.150 +            if ( (d == NULL) || !get_domain(d) )
   3.151 +            {
   3.152 +                ret = -ESRCH;
   3.153 +                break;
   3.154 +            }
   3.155 +
   3.156 +            getdomaininfo(d, &info);
   3.157 +
   3.158 +            put_domain(d);
   3.159 +
   3.160 +            if ( copy_to_user(buffer, &info, sizeof(dom0_getdomaininfo_t)) )
   3.161 +            {
   3.162 +                ret = -EINVAL;
   3.163 +                break;
   3.164 +            }
   3.165 +            
   3.166 +            buffer++;
   3.167 +            num_domains++;
   3.168 +        }
   3.169 +        
   3.170 +        read_unlock(&domlist_lock);
   3.171 +        
   3.172 +        if ( ret != 0 )
   3.173 +            break;
   3.174 +        
   3.175 +        op->u.getdomaininfolist.num_domains = num_domains;
   3.176 +
   3.177 +        if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
   3.178 +            ret = -EINVAL;
   3.179 +    }
   3.180 +    break;
   3.181 +
   3.182      case DOM0_GETVCPUCONTEXT:
   3.183      { 
   3.184          struct vcpu_guest_context *c;
     4.1 --- a/xen/include/public/dom0_ops.h	Fri Jul 08 08:48:46 2005 +0000
     4.2 +++ b/xen/include/public/dom0_ops.h	Fri Jul 08 09:06:04 2005 +0000
     4.3 @@ -19,7 +19,7 @@
     4.4   * This makes sure that old versions of dom0 tools will stop working in a
     4.5   * well-defined way (rather than crashing the machine, for instance).
     4.6   */
     4.7 -#define DOM0_INTERFACE_VERSION   0xAAAA100C
     4.8 +#define DOM0_INTERFACE_VERSION   0xAAAA100D
     4.9  
    4.10  /************************************************************************/
    4.11  
    4.12 @@ -357,6 +357,16 @@ typedef struct {
    4.13      u64     cpu_time;                 
    4.14  } dom0_getvcpucontext_t;
    4.15  
    4.16 +#define DOM0_GETDOMAININFOLIST    38
    4.17 +typedef struct {
    4.18 +    /* IN variables. */
    4.19 +    domid_t               first_domain;
    4.20 +    memory_t              max_domains;
    4.21 +    dom0_getdomaininfo_t *buffer;
    4.22 +    /* OUT variables. */
    4.23 +    memory_t              num_domains;
    4.24 +} dom0_getdomaininfolist_t;
    4.25 +
    4.26  typedef struct {
    4.27      u32 cmd;
    4.28      u32 interface_version; /* DOM0_INTERFACE_VERSION */
    4.29 @@ -389,6 +399,7 @@ typedef struct {
    4.30          dom0_microcode_t         microcode;
    4.31          dom0_ioport_permission_t ioport_permission;
    4.32          dom0_getvcpucontext_t    getvcpucontext;
    4.33 +        dom0_getdomaininfolist_t getdomaininfolist;
    4.34      } u;
    4.35  } dom0_op_t;
    4.36