aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_memshr.c
diff options
context:
space:
mode:
authorAndres Lagar-Cavilla <andres@lagarcavilla.org>2012-02-10 16:07:07 +0000
committerAndres Lagar-Cavilla <andres@lagarcavilla.org>2012-02-10 16:07:07 +0000
commit59a36d66a5d50a66f8a629b334a0cbd7af360f80 (patch)
treeeb7a565b5e32cc6542dbf49205e26d9772dc46b9 /tools/libxc/xc_memshr.c
parent2da4c17b3b76d190da3dda35aa24910ff69984e5 (diff)
downloadxen-59a36d66a5d50a66f8a629b334a0cbd7af360f80.tar.gz
xen-59a36d66a5d50a66f8a629b334a0cbd7af360f80.tar.bz2
xen-59a36d66a5d50a66f8a629b334a0cbd7af360f80.zip
Use memops for mem paging, sharing, and access, instead of domctls
Per page operations in the paging, sharing, and access tracking subsystems are all implemented with domctls (e.g. a domctl to evict one page, or to share one page). Under heavy load, the domctl path reveals a lack of scalability. The domctl lock serializes dom0's vcpus in the hypervisor. When performing thousands of per-page operations on dozens of domains, these vcpus will spin in the hypervisor. Beyond the aggressive locking, an added inefficiency of blocking vcpus in the domctl lock is that dom0 is prevented from re-scheduling any of its other work-starved processes. We retain the domctl interface for setting up and tearing down paging/sharing/mem access for a domain. But we migrate all the per page operations to use the memory_op hypercalls (e.g XENMEM_*). Signed-off-by: Andres Lagar-Cavilla <andres@lagarcavilla> Signed-off-by: Adin Scannell <adin@scannell.ca> Acked-by: Tim Deegan <tim@xen.org> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> Committed-by: Tim Deegan <tim@xen.org>
Diffstat (limited to 'tools/libxc/xc_memshr.c')
-rw-r--r--tools/libxc/xc_memshr.c182
1 files changed, 84 insertions, 98 deletions
diff --git a/tools/libxc/xc_memshr.c b/tools/libxc/xc_memshr.c
index 810200c5e4..5866960f38 100644
--- a/tools/libxc/xc_memshr.c
+++ b/tools/libxc/xc_memshr.c
@@ -36,32 +36,38 @@ int xc_memshr_control(xc_interface *xch,
domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
domctl.domain = domid;
op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_CONTROL;
+ op->op = XEN_DOMCTL_MEM_SHARING_CONTROL;
op->u.enable = enable;
return do_domctl(xch, &domctl);
}
+static int xc_memshr_memop(xc_interface *xch, domid_t domid,
+ xen_mem_sharing_op_t *mso)
+{
+ mso->domain = domid;
+
+ return do_memory_op(xch, XENMEM_sharing_op, mso, sizeof(*mso));
+}
+
int xc_memshr_nominate_gfn(xc_interface *xch,
domid_t domid,
unsigned long gfn,
uint64_t *handle)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
- int ret;
+ int rc;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = domid;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_NOMINATE_GFN;
- op->u.nominate.u.gfn = gfn;
+ memset(&mso, 0, sizeof(mso));
- ret = do_domctl(xch, &domctl);
- if(!ret) *handle = op->u.nominate.handle;
+ mso.op = XENMEM_sharing_op_nominate_gfn;
+ mso.u.nominate.u.gfn = gfn;
- return ret;
+ rc = xc_memshr_memop(xch, domid, &mso);
+
+ if (!rc) *handle = mso.u.nominate.handle;
+
+ return rc;
}
int xc_memshr_nominate_gref(xc_interface *xch,
@@ -69,21 +75,19 @@ int xc_memshr_nominate_gref(xc_interface *xch,
grant_ref_t gref,
uint64_t *handle)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
- int ret;
+ int rc;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = domid;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_NOMINATE_GREF;
- op->u.nominate.u.grant_ref = gref;
+ memset(&mso, 0, sizeof(mso));
+
+ mso.op = XENMEM_sharing_op_nominate_gref;
+ mso.u.nominate.u.grant_ref = gref;
- ret = do_domctl(xch, &domctl);
- if(!ret) *handle = op->u.nominate.handle;
+ rc = xc_memshr_memop(xch, domid, &mso);
- return ret;
+ if (!rc) *handle = mso.u.nominate.handle;
+
+ return rc;
}
int xc_memshr_share_gfns(xc_interface *xch,
@@ -94,21 +98,19 @@ int xc_memshr_share_gfns(xc_interface *xch,
unsigned long client_gfn,
uint64_t client_handle)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = source_domain;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_SHARE;
- op->u.share.source_handle = source_handle;
- op->u.share.source_gfn = source_gfn;
- op->u.share.client_domain = client_domain;
- op->u.share.client_gfn = client_gfn;
- op->u.share.client_handle = client_handle;
+ memset(&mso, 0, sizeof(mso));
- return do_domctl(xch, &domctl);
+ mso.op = XENMEM_sharing_op_share;
+
+ mso.u.share.source_handle = source_handle;
+ mso.u.share.source_gfn = source_gfn;
+ mso.u.share.client_domain = client_domain;
+ mso.u.share.client_gfn = client_gfn;
+ mso.u.share.client_handle = client_handle;
+
+ return xc_memshr_memop(xch, source_domain, &mso);
}
int xc_memshr_share_grefs(xc_interface *xch,
@@ -119,21 +121,19 @@ int xc_memshr_share_grefs(xc_interface *xch,
grant_ref_t client_gref,
uint64_t client_handle)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = source_domain;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_SHARE;
- op->u.share.source_handle = source_handle;
- XEN_DOMCTL_MEM_SHARING_FIELD_MAKE_GREF(op->u.share.source_gfn, source_gref);
- op->u.share.client_domain = client_domain;
- XEN_DOMCTL_MEM_SHARING_FIELD_MAKE_GREF(op->u.share.client_gfn, client_gref);
- op->u.share.client_handle = client_handle;
+ memset(&mso, 0, sizeof(mso));
- return do_domctl(xch, &domctl);
+ mso.op = XENMEM_sharing_op_share;
+
+ mso.u.share.source_handle = source_handle;
+ XENMEM_SHARING_OP_FIELD_MAKE_GREF(mso.u.share.source_gfn, source_gref);
+ mso.u.share.client_domain = client_domain;
+ XENMEM_SHARING_OP_FIELD_MAKE_GREF(mso.u.share.client_gfn, client_gref);
+ mso.u.share.client_handle = client_handle;
+
+ return xc_memshr_memop(xch, source_domain, &mso);
}
int xc_memshr_add_to_physmap(xc_interface *xch,
@@ -143,86 +143,72 @@ int xc_memshr_add_to_physmap(xc_interface *xch,
domid_t client_domain,
unsigned long client_gfn)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = source_domain;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_ADD_PHYSMAP;
- op->u.share.source_gfn = source_gfn;
- op->u.share.source_handle = source_handle;
- op->u.share.client_gfn = client_gfn;
- op->u.share.client_domain = client_domain;
+ memset(&mso, 0, sizeof(mso));
- return do_domctl(xch, &domctl);
+ mso.op = XENMEM_sharing_op_add_physmap;
+
+ mso.u.share.source_handle = source_handle;
+ mso.u.share.source_gfn = source_gfn;
+ mso.u.share.client_domain = client_domain;
+ mso.u.share.client_gfn = client_gfn;
+
+ return xc_memshr_memop(xch, source_domain, &mso);
}
int xc_memshr_domain_resume(xc_interface *xch,
domid_t domid)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = domid;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_RESUME;
+ memset(&mso, 0, sizeof(mso));
- return do_domctl(xch, &domctl);
+ mso.op = XENMEM_sharing_op_resume;
+
+ return xc_memshr_memop(xch, domid, &mso);
}
int xc_memshr_debug_gfn(xc_interface *xch,
domid_t domid,
unsigned long gfn)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = domid;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_GFN;
- op->u.debug.u.gfn = gfn;
+ memset(&mso, 0, sizeof(mso));
- return do_domctl(xch, &domctl);
+ mso.op = XENMEM_sharing_op_debug_gfn;
+ mso.u.debug.u.gfn = gfn;
+
+ return xc_memshr_memop(xch, domid, &mso);
}
int xc_memshr_debug_mfn(xc_interface *xch,
domid_t domid,
unsigned long mfn)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = domid;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_MFN;
- op->u.debug.u.mfn = mfn;
+ memset(&mso, 0, sizeof(mso));
- return do_domctl(xch, &domctl);
+ mso.op = XENMEM_sharing_op_debug_mfn;
+ mso.u.debug.u.mfn = mfn;
+
+ return xc_memshr_memop(xch, domid, &mso);
}
int xc_memshr_debug_gref(xc_interface *xch,
domid_t domid,
grant_ref_t gref)
{
- DECLARE_DOMCTL;
- struct xen_domctl_mem_sharing_op *op;
+ xen_mem_sharing_op_t mso;
- domctl.cmd = XEN_DOMCTL_mem_sharing_op;
- domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
- domctl.domain = domid;
- op = &(domctl.u.mem_sharing_op);
- op->op = XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_GREF;
- op->u.debug.u.gref = gref;
+ memset(&mso, 0, sizeof(mso));
- return do_domctl(xch, &domctl);
+ mso.op = XENMEM_sharing_op_debug_gref;
+ mso.u.debug.u.gref = gref;
+
+ return xc_memshr_memop(xch, domid, &mso);
}
long xc_sharing_freed_pages(xc_interface *xch)