# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID eef23f57f20e931a75481c2e2bce05cf2e9a19c6
# Parent 20ff6c7413d8dfb59d5c87d83887a3aaa2b86785
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@xxxxxxxxxx>
diff -r 20ff6c7413d8 -r eef23f57f20e tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Fri Jul 8 08:48:46 2005
+++ b/tools/libxc/xc_domain.c Fri Jul 8 09:06:04 2005
@@ -123,6 +123,33 @@
if( !nr_doms ) return rc;
return nr_doms;
+}
+
+int xc_domain_getinfolist(int xc_handle,
+ u32 first_domain,
+ unsigned int max_domains,
+ xc_domaininfo_t *info)
+{
+ int ret = 0;
+ dom0_op_t op;
+
+ if(mlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0)
+ return -1;
+
+ op.cmd = DOM0_GETDOMAININFOLIST;
+ op.u.getdomaininfolist.first_domain = first_domain;
+ op.u.getdomaininfolist.max_domains = max_domains;
+ op.u.getdomaininfolist.buffer = info;
+
+ if(xc_dom0_op(xc_handle, &op) < 0)
+ ret = -1;
+ else
+ ret = op.u.getdomaininfolist.num_domains;
+
+ if(munlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0)
+ ret = -1;
+
+ return ret;
}
int xc_domain_get_vcpu_context(int xc_handle,
diff -r 20ff6c7413d8 -r eef23f57f20e tools/libxc/xc.h
--- a/tools/libxc/xc.h Fri Jul 8 08:48:46 2005
+++ b/tools/libxc/xc.h Fri Jul 8 09:06:04 2005
@@ -192,6 +192,24 @@
xc_dominfo_t *info);
/**
+ * This function will return information about one or more domains, using a
+ * single hypercall. The domain information will be stored into the supplied
+ * array of xc_domaininfo_t structures.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm first_domain the first domain to enumerate information from.
+ * Domains are currently enumerate in order of creation.
+ * @parm max_domains the number of elements in info
+ * @parm info an array of max_doms size that will contain the information for
+ * the enumerated domains.
+ * @return the number of domains enumerated or -1 on error
+ */
+int xc_domain_getinfolist(int xc_handle,
+ u32 first_domain,
+ unsigned int max_domains,
+ xc_domaininfo_t *info);
+
+/**
* This function returns information about one domain. This information is
* more detailed than the information from xc_domain_getinfo().
*
diff -r 20ff6c7413d8 -r eef23f57f20e xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h Fri Jul 8 08:48:46 2005
+++ b/xen/include/public/dom0_ops.h Fri Jul 8 09:06:04 2005
@@ -19,7 +19,7 @@
* This makes sure that old versions of dom0 tools will stop working in a
* well-defined way (rather than crashing the machine, for instance).
*/
-#define DOM0_INTERFACE_VERSION 0xAAAA100C
+#define DOM0_INTERFACE_VERSION 0xAAAA100D
/************************************************************************/
@@ -356,6 +356,16 @@
vcpu_guest_context_t *ctxt; /* NB. IN/OUT variable. */
u64 cpu_time;
} dom0_getvcpucontext_t;
+
+#define DOM0_GETDOMAININFOLIST 38
+typedef struct {
+ /* IN variables. */
+ domid_t first_domain;
+ memory_t max_domains;
+ dom0_getdomaininfo_t *buffer;
+ /* OUT variables. */
+ memory_t num_domains;
+} dom0_getdomaininfolist_t;
typedef struct {
u32 cmd;
@@ -389,6 +399,7 @@
dom0_microcode_t microcode;
dom0_ioport_permission_t ioport_permission;
dom0_getvcpucontext_t getvcpucontext;
+ dom0_getdomaininfolist_t getdomaininfolist;
} u;
} dom0_op_t;
diff -r 20ff6c7413d8 -r eef23f57f20e xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c Fri Jul 8 08:48:46 2005
+++ b/xen/common/dom0_ops.c Fri Jul 8 09:06:04 2005
@@ -88,6 +88,60 @@
return err;
}
+static void getdomaininfo(struct domain *d, dom0_getdomaininfo_t *info)
+{
+ struct vcpu *v;
+ u64 cpu_time = 0;
+ int vcpu_count = 0;
+ int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
+
+ info->domain = d->domain_id;
+
+ memset(&info->vcpu_to_cpu, -1, sizeof(info->vcpu_to_cpu));
+ memset(&info->cpumap, 0, sizeof(info->cpumap));
+
+ /*
+ * - domain is marked as paused or blocked only if all its vcpus
+ * are paused or blocked
+ * - domain is marked as running if any of its vcpus is running
+ * - only map vcpus that aren't down. Note, at some point we may
+ * wish to demux the -1 value to indicate down vs. not-ever-booted
+ *
+ */
+ for_each_vcpu ( d, v ) {
+ /* only map vcpus that are up */
+ if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
+ info->vcpu_to_cpu[v->vcpu_id] = v->processor;
+ info->cpumap[v->vcpu_id] = v->cpumap;
+ if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
+ flags &= ~DOMFLAGS_PAUSED;
+ if ( !(v->vcpu_flags & VCPUF_blocked) )
+ flags &= ~DOMFLAGS_BLOCKED;
+ if ( v->vcpu_flags & VCPUF_running )
+ flags |= DOMFLAGS_RUNNING;
+ if ( v->cpu_time > cpu_time )
+ cpu_time += v->cpu_time;
+ vcpu_count++;
+ }
+
+ info->cpu_time = cpu_time;
+ info->n_vcpu = vcpu_count;
+
+ info->flags = flags |
+ ((d->domain_flags & DOMF_dying) ? DOMFLAGS_DYING : 0) |
+ ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
+ d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
+
+ if (d->ssid != NULL)
+ info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
+ else
+ info->ssidref = ACM_DEFAULT_SSID;
+
+ info->tot_pages = d->tot_pages;
+ info->max_pages = d->max_pages;
+ info->shared_info_frame = __pa(d->shared_info) >> PAGE_SHIFT;
+}
+
long do_dom0_op(dom0_op_t *u_dom0_op)
{
long ret = 0;
@@ -306,10 +360,6 @@
case DOM0_GETDOMAININFO:
{
struct domain *d;
- struct vcpu *v;
- u64 cpu_time = 0;
- int vcpu_count = 0;
- int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
read_lock(&domlist_lock);
@@ -328,59 +378,59 @@
read_unlock(&domlist_lock);
- op->u.getdomaininfo.domain = d->domain_id;
-
- memset(&op->u.getdomaininfo.vcpu_to_cpu, -1,
- sizeof(op->u.getdomaininfo.vcpu_to_cpu));
- memset(&op->u.getdomaininfo.cpumap, 0,
- sizeof(op->u.getdomaininfo.cpumap));
-
- /*
- * - domain is marked as paused or blocked only if all its vcpus
- * are paused or blocked
- * - domain is marked as running if any of its vcpus is running
- * - only map vcpus that aren't down. Note, at some point we may
- * wish to demux the -1 value to indicate down vs. not-ever-booted
- *
- */
- for_each_vcpu ( d, v ) {
- /* only map vcpus that are up */
- if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
- op->u.getdomaininfo.vcpu_to_cpu[v->vcpu_id] = v->processor;
- op->u.getdomaininfo.cpumap[v->vcpu_id] = v->cpumap;
- if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
- flags &= ~DOMFLAGS_PAUSED;
- if ( !(v->vcpu_flags & VCPUF_blocked) )
- flags &= ~DOMFLAGS_BLOCKED;
- if ( v->vcpu_flags & VCPUF_running )
- flags |= DOMFLAGS_RUNNING;
- if ( v->cpu_time > cpu_time )
- cpu_time += v->cpu_time;
- vcpu_count++;
- }
-
- op->u.getdomaininfo.cpu_time = cpu_time;
- op->u.getdomaininfo.n_vcpu = vcpu_count;
-
- op->u.getdomaininfo.flags = flags |
- ((d->domain_flags & DOMF_dying) ? DOMFLAGS_DYING : 0) |
- ((d->domain_flags & DOMF_shutdown) ? DOMFLAGS_SHUTDOWN : 0) |
- d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
-
- if (d->ssid != NULL)
- op->u.getdomaininfo.ssidref = ((struct acm_ssid_domain
*)d->ssid)->ssidref;
- else
- op->u.getdomaininfo.ssidref = ACM_DEFAULT_SSID;
-
- op->u.getdomaininfo.tot_pages = d->tot_pages;
- op->u.getdomaininfo.max_pages = d->max_pages;
- op->u.getdomaininfo.shared_info_frame =
- __pa(d->shared_info) >> PAGE_SHIFT;
+ getdomaininfo(d, &op->u.getdomaininfo);
if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
ret = -EINVAL;
put_domain(d);
+ }
+ break;
+
+ case DOM0_GETDOMAININFOLIST:
+ {
+ struct domain *d;
+ dom0_getdomaininfo_t info;
+ dom0_getdomaininfo_t *buffer = op->u.getdomaininfolist.buffer;
+ u32 num_domains = 0;
+
+ read_lock(&domlist_lock);
+
+ for_each_domain ( d )
+ {
+ if ( d->domain_id < op->u.getdomaininfolist.first_domain )
+ continue;
+ if ( num_domains == op->u.getdomaininfolist.max_domains )
+ break;
+ if ( (d == NULL) || !get_domain(d) )
+ {
+ ret = -ESRCH;
+ break;
+ }
+
+ getdomaininfo(d, &info);
+
+ put_domain(d);
+
+ if ( copy_to_user(buffer, &info, sizeof(dom0_getdomaininfo_t)) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ buffer++;
+ num_domains++;
+ }
+
+ read_unlock(&domlist_lock);
+
+ if ( ret != 0 )
+ break;
+
+ op->u.getdomaininfolist.num_domains = num_domains;
+
+ if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
+ ret = -EINVAL;
}
break;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|