return xc_mem_event_control(xch, domain_id,
XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE,
XEN_DOMCTL_MEM_EVENT_OP_ACCESS,
- shared_page, ring_page, INVALID_MFN);
+ shared_page, ring_page);
}
int xc_mem_access_disable(xc_interface *xch, domid_t domain_id)
return xc_mem_event_control(xch, domain_id,
XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE,
XEN_DOMCTL_MEM_EVENT_OP_ACCESS,
- NULL, NULL, INVALID_MFN);
+ NULL, NULL);
}
int xc_mem_access_resume(xc_interface *xch, domid_t domain_id, unsigned long gfn)
{
- return xc_mem_event_control(xch, domain_id,
- XEN_DOMCTL_MEM_EVENT_OP_ACCESS_RESUME,
- XEN_DOMCTL_MEM_EVENT_OP_ACCESS,
- NULL, NULL, gfn);
+ return xc_mem_event_memop(xch, domain_id,
+ XENMEM_access_op_resume,
+ XENMEM_access_op,
+ gfn, NULL);
}
/*
#include "xc_private.h"
int xc_mem_event_control(xc_interface *xch, domid_t domain_id, unsigned int op,
- unsigned int mode, void *page,
- void *ring_page, unsigned long gfn)
+ unsigned int mode, void *page, void *ring_page)
{
DECLARE_DOMCTL;
domctl.u.mem_event_op.op = op;
domctl.u.mem_event_op.mode = mode;
- domctl.u.mem_event_op.u.shared_addr = (unsigned long)page;
+ domctl.u.mem_event_op.shared_addr = (unsigned long)page;
domctl.u.mem_event_op.ring_addr = (unsigned long)ring_page;
-
- domctl.u.mem_event_op.gfn = gfn;
return do_domctl(xch, &domctl);
}
+int xc_mem_event_memop(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int mode,
+ uint64_t gfn, void *buffer)
+{
+ xen_mem_event_op_t meo;
+
+ memset(&meo, 0, sizeof(meo));
+
+ meo.op = op;
+ meo.domain = domain_id;
+ meo.gfn = gfn;
+ meo.buffer = (unsigned long) buffer;
+
+ return do_memory_op(xch, mode, &meo, sizeof(meo));
+}
+
return xc_mem_event_control(xch, domain_id,
XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE,
XEN_DOMCTL_MEM_EVENT_OP_PAGING,
- shared_page, ring_page, INVALID_MFN);
+ shared_page, ring_page);
}
int xc_mem_paging_disable(xc_interface *xch, domid_t domain_id)
return xc_mem_event_control(xch, domain_id,
XEN_DOMCTL_MEM_EVENT_OP_PAGING_DISABLE,
XEN_DOMCTL_MEM_EVENT_OP_PAGING,
- NULL, NULL, INVALID_MFN);
+ NULL, NULL);
}
int xc_mem_paging_nominate(xc_interface *xch, domid_t domain_id, unsigned long gfn)
{
- return xc_mem_event_control(xch, domain_id,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING,
- NULL, NULL, gfn);
+ return xc_mem_event_memop(xch, domain_id,
+ XENMEM_paging_op_nominate,
+ XENMEM_paging_op,
+ gfn, NULL);
}
int xc_mem_paging_evict(xc_interface *xch, domid_t domain_id, unsigned long gfn)
{
- return xc_mem_event_control(xch, domain_id,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING,
- NULL, NULL, gfn);
+ return xc_mem_event_memop(xch, domain_id,
+ XENMEM_paging_op_evict,
+ XENMEM_paging_op,
+ gfn, NULL);
}
int xc_mem_paging_prep(xc_interface *xch, domid_t domain_id, unsigned long gfn)
{
- return xc_mem_event_control(xch, domain_id,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING,
- NULL, NULL, gfn);
+ return xc_mem_event_memop(xch, domain_id,
+ XENMEM_paging_op_prep,
+ XENMEM_paging_op,
+ gfn, NULL);
}
int xc_mem_paging_load(xc_interface *xch, domid_t domain_id,
if ( mlock(buffer, XC_PAGE_SIZE) )
return -1;
- rc = xc_mem_event_control(xch, domain_id,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING,
- buffer, NULL, gfn);
+ rc = xc_mem_event_memop(xch, domain_id,
+ XENMEM_paging_op_prep,
+ XENMEM_paging_op,
+ gfn, buffer);
old_errno = errno;
munlock(buffer, XC_PAGE_SIZE);
int xc_mem_paging_resume(xc_interface *xch, domid_t domain_id, unsigned long gfn)
{
- return xc_mem_event_control(xch, domain_id,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME,
- XEN_DOMCTL_MEM_EVENT_OP_PAGING,
- NULL, NULL, gfn);
+ return xc_mem_event_memop(xch, domain_id,
+ XENMEM_paging_op_resume,
+ XENMEM_paging_op,
+ gfn, NULL);
}
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,
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,
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,
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,
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)
* mem_event operations
*/
int xc_mem_event_control(xc_interface *xch, domid_t domain_id, unsigned int op,
- unsigned int mode, void *shared_page,
- void *ring_page, unsigned long gfn);
+ unsigned int mode, void *shared_page, void *ring_page);
+int xc_mem_event_memop(xc_interface *xch, domid_t domain_id,
+ unsigned int op, unsigned int mode,
+ uint64_t gfn, void *buffer);
int xc_mem_paging_enable(xc_interface *xch, domid_t domain_id,
void *shared_page, void *ring_page);
remove the relevant ones from the map */
switch(ret)
{
- case XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID:
+ case XENMEM_SHARING_OP_S_HANDLE_INVALID:
ret = blockshr_shrhnd_remove(memshr.blks, source_st, NULL);
if(ret) DPRINTF("Could not rm invl s_hnd: %u %"PRId64" %"PRId64"\n",
source_st.domain, source_st.frame, source_st.handle);
break;
- case XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID:
+ case XENMEM_SHARING_OP_C_HANDLE_INVALID:
ret = blockshr_shrhnd_remove(memshr.blks, client_st, NULL);
if(ret) DPRINTF("Could not rm invl c_hnd: %u %"PRId64" %"PRId64"\n",
client_st.domain, client_st.frame, client_st.handle);
int rc = f; \
if ( rc < 0 ) { \
printf("error executing %s: %s\n", #f, \
- ((errno * -1) == XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID) ? \
+ ((errno * -1) == XENMEM_SHARING_OP_S_HANDLE_INVALID) ? \
"problem with client handle" :\
- ((errno * -1) == XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID) ? \
+ ((errno * -1) == XENMEM_SHARING_OP_C_HANDLE_INVALID) ? \
"problem with source handle" : strerror(errno)); \
return rc; \
} \
if ( !ret )
ret = mem_sharing_domctl(d, &domctl->u.mem_sharing_op);
rcu_unlock_domain(d);
- copy_to_guest(u_domctl, domctl, 1);
}
}
break;
#include <asm/mem_event.h>
-int mem_access_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
- XEN_GUEST_HANDLE(void) u_domctl)
+int mem_access_memop(struct domain *d, xen_mem_event_op_t *meo)
{
int rc;
- switch( mec->op )
+ switch( meo->op )
{
- case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_RESUME:
+ case XENMEM_access_op_resume:
{
p2m_mem_access_resume(d);
rc = 0;
#include <asm/mem_event.h>
#include <asm/mem_paging.h>
#include <asm/mem_access.h>
+#include <asm/mem_sharing.h>
/* for public/io/ring.h macros */
#define xen_mb() mb()
struct domain *dom_mem_event = current->domain;
struct vcpu *v = current;
unsigned long ring_addr = mec->ring_addr;
- unsigned long shared_addr = mec->u.shared_addr;
+ unsigned long shared_addr = mec->shared_addr;
l1_pgentry_t l1e;
unsigned long shared_gfn = 0, ring_gfn = 0; /* gcc ... */
p2m_type_t p2mt;
p2m_mem_access_resume(v->domain);
}
+struct domain *get_mem_event_op_target(uint32_t domain, int *rc)
+{
+ struct domain *d;
+
+ /* Get the target domain */
+ *rc = rcu_lock_remote_target_domain_by_id(domain, &d);
+ if ( *rc != 0 )
+ return NULL;
+
+ /* Not dying? */
+ if ( d->is_dying )
+ {
+ rcu_unlock_domain(d);
+ *rc = -EINVAL;
+ return NULL;
+ }
+
+ return d;
+}
+
+int do_mem_event_op(int op, uint32_t domain, void *arg)
+{
+ int ret;
+ struct domain *d;
+
+ d = get_mem_event_op_target(domain, &ret);
+ if ( !d )
+ return ret;
+
+ switch (op)
+ {
+ case XENMEM_paging_op:
+ ret = mem_paging_memop(d, (xen_mem_event_op_t *) arg);
+ break;
+ case XENMEM_access_op:
+ ret = mem_access_memop(d, (xen_mem_event_op_t *) arg);
+ break;
+ case XENMEM_sharing_op:
+ ret = mem_sharing_memop(d, (xen_mem_sharing_op_t *) arg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ rcu_unlock_domain(d);
+ return ret;
+}
+
int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
XEN_GUEST_HANDLE(void) u_domctl)
{
break;
default:
- {
- if ( med->ring_page )
- rc = mem_paging_domctl(d, mec, u_domctl);
- }
- break;
+ rc = -ENOSYS;
+ break;
}
}
break;
break;
default:
- {
- if ( med->ring_page )
- rc = mem_access_domctl(d, mec, u_domctl);
- }
- break;
+ rc = -ENOSYS;
+ break;
}
}
break;
+
+ default:
+ rc = -ENOSYS;
}
return rc;
#include <asm/mem_event.h>
-int mem_paging_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
- XEN_GUEST_HANDLE(void) u_domctl)
+int mem_paging_memop(struct domain *d, xen_mem_event_op_t *mec)
{
switch( mec->op )
{
- case XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE:
+ case XENMEM_paging_op_nominate:
{
unsigned long gfn = mec->gfn;
return p2m_mem_paging_nominate(d, gfn);
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT:
+ case XENMEM_paging_op_evict:
{
unsigned long gfn = mec->gfn;
return p2m_mem_paging_evict(d, gfn);
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP:
+ case XENMEM_paging_op_prep:
{
unsigned long gfn = mec->gfn;
- return p2m_mem_paging_prep(d, gfn, mec->u.buffer);
+ return p2m_mem_paging_prep(d, gfn, mec->buffer);
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME:
+ case XENMEM_paging_op_resume:
{
p2m_mem_paging_resume(d);
return 0;
}
else if ( mfn_x(smfn) < mfn_x(cmfn) )
{
- ret = XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID;
+ ret = XENMEM_SHARING_OP_S_HANDLE_INVALID;
spage = firstpg = __grab_shared_page(smfn);
if ( spage == NULL )
goto err_out;
- ret = XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID;
+ ret = XENMEM_SHARING_OP_C_HANDLE_INVALID;
cpage = secondpg = __grab_shared_page(cmfn);
if ( cpage == NULL )
{
goto err_out;
}
} else {
- ret = XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID;
+ ret = XENMEM_SHARING_OP_C_HANDLE_INVALID;
cpage = firstpg = __grab_shared_page(cmfn);
if ( cpage == NULL )
goto err_out;
- ret = XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID;
+ ret = XENMEM_SHARING_OP_S_HANDLE_INVALID;
spage = secondpg = __grab_shared_page(smfn);
if ( spage == NULL )
{
/* Check that the handles match */
if ( spage->sharing->handle != sh )
{
- ret = XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID;
+ ret = XENMEM_SHARING_OP_S_HANDLE_INVALID;
mem_sharing_page_unlock(secondpg);
mem_sharing_page_unlock(firstpg);
goto err_out;
}
if ( cpage->sharing->handle != ch )
{
- ret = XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID;
+ ret = XENMEM_SHARING_OP_C_HANDLE_INVALID;
mem_sharing_page_unlock(secondpg);
mem_sharing_page_unlock(firstpg);
goto err_out;
p2m_query, &tg);
/* Get the source shared page, check and lock */
- ret = XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID;
+ ret = XENMEM_SHARING_OP_S_HANDLE_INVALID;
spage = __grab_shared_page(smfn);
if ( spage == NULL )
goto err_out;
if ( mfn_valid(cmfn) ||
(!(p2m_is_ram(cmfn_type))) )
{
- ret = XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID;
+ ret = XENMEM_SHARING_OP_C_HANDLE_INVALID;
goto err_unlock;
}
return 0;
}
-int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec)
+int mem_sharing_memop(struct domain *d, xen_mem_sharing_op_t *mec)
{
- int rc;
+ int rc = 0;
/* Only HAP is supported */
if ( !hap_enabled(d) )
switch(mec->op)
{
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_CONTROL:
- {
- d->arch.hvm_domain.mem_sharing_enabled = mec->u.enable;
- rc = 0;
- }
- break;
-
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_NOMINATE_GFN:
+ case XENMEM_sharing_op_nominate_gfn:
{
unsigned long gfn = mec->u.nominate.u.gfn;
shr_handle_t handle;
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_NOMINATE_GREF:
+ case XENMEM_sharing_op_nominate_gref:
{
grant_ref_t gref = mec->u.nominate.u.grant_ref;
unsigned long gfn;
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_SHARE:
+ case XENMEM_sharing_op_share:
{
unsigned long sgfn, cgfn;
struct domain *cd;
if ( !mem_sharing_enabled(d) )
return -EINVAL;
- cd = get_domain_by_id(mec->u.share.client_domain);
+ cd = get_mem_event_op_target(mec->u.share.client_domain, &rc);
if ( !cd )
- return -ESRCH;
+ return rc;
if ( !mem_sharing_enabled(cd) )
{
- put_domain(cd);
+ rcu_unlock_domain(cd);
return -EINVAL;
}
- if ( XEN_DOMCTL_MEM_SHARING_FIELD_IS_GREF(mec->u.share.source_gfn) )
+ if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mec->u.share.source_gfn) )
{
grant_ref_t gref = (grant_ref_t)
- (XEN_DOMCTL_MEM_SHARING_FIELD_GET_GREF(
+ (XENMEM_SHARING_OP_FIELD_GET_GREF(
mec->u.share.source_gfn));
if ( mem_sharing_gref_to_gfn(d, gref, &sgfn) < 0 )
{
- put_domain(cd);
+ rcu_unlock_domain(cd);
return -EINVAL;
}
} else {
sgfn = mec->u.share.source_gfn;
}
- if ( XEN_DOMCTL_MEM_SHARING_FIELD_IS_GREF(mec->u.share.client_gfn) )
+ if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mec->u.share.client_gfn) )
{
grant_ref_t gref = (grant_ref_t)
- (XEN_DOMCTL_MEM_SHARING_FIELD_GET_GREF(
+ (XENMEM_SHARING_OP_FIELD_GET_GREF(
mec->u.share.client_gfn));
if ( mem_sharing_gref_to_gfn(cd, gref, &cgfn) < 0 )
{
- put_domain(cd);
+ rcu_unlock_domain(cd);
return -EINVAL;
}
} else {
rc = mem_sharing_share_pages(d, sgfn, sh, cd, cgfn, ch);
- put_domain(cd);
+ rcu_unlock_domain(cd);
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_ADD_PHYSMAP:
+ case XENMEM_sharing_op_add_physmap:
{
unsigned long sgfn, cgfn;
struct domain *cd;
if ( !mem_sharing_enabled(d) )
return -EINVAL;
- cd = get_domain_by_id(mec->u.share.client_domain);
+ cd = get_mem_event_op_target(mec->u.share.client_domain, &rc);
if ( !cd )
- return -ESRCH;
+ return rc;
if ( !mem_sharing_enabled(cd) )
{
- put_domain(cd);
+ rcu_unlock_domain(cd);
return -EINVAL;
}
- if ( XEN_DOMCTL_MEM_SHARING_FIELD_IS_GREF(mec->u.share.source_gfn) )
+ if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mec->u.share.source_gfn) )
{
/* Cannot add a gref to the physmap */
- put_domain(cd);
+ rcu_unlock_domain(cd);
return -EINVAL;
}
rc = mem_sharing_add_to_physmap(d, sgfn, sh, cd, cgfn);
- put_domain(cd);
+ rcu_unlock_domain(cd);
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_RESUME:
+ case XENMEM_sharing_op_resume:
{
if ( !mem_sharing_enabled(d) )
return -EINVAL;
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_GFN:
+ case XENMEM_sharing_op_debug_gfn:
{
unsigned long gfn = mec->u.debug.u.gfn;
rc = mem_sharing_debug_gfn(d, gfn);
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_MFN:
+ case XENMEM_sharing_op_debug_mfn:
{
unsigned long mfn = mec->u.debug.u.mfn;
rc = mem_sharing_debug_mfn(_mfn(mfn));
}
break;
- case XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_GREF:
+ case XENMEM_sharing_op_debug_gref:
{
grant_ref_t gref = mec->u.debug.u.gref;
rc = mem_sharing_debug_gref(d, gref);
return rc;
}
+int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec)
+{
+ int rc;
+
+ /* Only HAP is supported */
+ if ( !hap_enabled(d) )
+ return -ENODEV;
+
+ switch(mec->op)
+ {
+ case XEN_DOMCTL_MEM_SHARING_CONTROL:
+ {
+ d->arch.hvm_domain.mem_sharing_enabled = mec->u.enable;
+ rc = 0;
+ }
+ break;
+
+ default:
+ rc = -ENOSYS;
+ }
+
+ return rc;
+}
+
void __init mem_sharing_init(void)
{
printk("Initing memory sharing.\n");
#include <xen/multicall.h>
#include <compat/memory.h>
#include <compat/xen.h>
+#include <asm/mem_event.h>
int compat_set_gdt(XEN_GUEST_HANDLE(uint) frame_list, unsigned int entries)
{
case XENMEM_get_sharing_shared_pages:
return mem_sharing_get_nr_shared_mfns();
+ case XENMEM_paging_op:
+ case XENMEM_access_op:
+ {
+ xen_mem_event_op_t meo;
+ if ( copy_from_guest(&meo, arg, 1) )
+ return -EFAULT;
+ rc = do_mem_event_op(op, meo.domain, (void *) &meo);
+ if ( !rc && copy_to_guest(arg, &meo, 1) )
+ return -EFAULT;
+ break;
+ }
+ case XENMEM_sharing_op:
+ {
+ xen_mem_sharing_op_t mso;
+ if ( copy_from_guest(&mso, arg, 1) )
+ return -EFAULT;
+ rc = do_mem_event_op(op, mso.domain, (void *) &mso);
+ if ( !rc && copy_to_guest(arg, &mso, 1) )
+ return -EFAULT;
+ break;
+ }
+
default:
rc = -ENOSYS;
break;
#include <asm/msr.h>
#include <asm/setup.h>
#include <asm/numa.h>
+#include <asm/mem_event.h>
#include <asm/mem_sharing.h>
#include <public/memory.h>
case XENMEM_get_sharing_shared_pages:
return mem_sharing_get_nr_shared_mfns();
+ case XENMEM_paging_op:
+ case XENMEM_access_op:
+ {
+ xen_mem_event_op_t meo;
+ if ( copy_from_guest(&meo, arg, 1) )
+ return -EFAULT;
+ rc = do_mem_event_op(op, meo.domain, (void *) &meo);
+ if ( !rc && copy_to_guest(arg, &meo, 1) )
+ return -EFAULT;
+ break;
+ }
+ case XENMEM_sharing_op:
+ {
+ xen_mem_sharing_op_t mso;
+ if ( copy_from_guest(&mso, arg, 1) )
+ return -EFAULT;
+ rc = do_mem_event_op(op, mso.domain, (void *) &mso);
+ if ( !rc && copy_to_guest(arg, &mso, 1) )
+ return -EFAULT;
+ break;
+ }
+
default:
rc = -ENOSYS;
break;
*/
-int mem_access_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
- XEN_GUEST_HANDLE(void) u_domctl);
+int mem_access_memop(struct domain *d, xen_mem_event_op_t *meo);
int mem_access_send_req(struct domain *d, mem_event_request_t *req);
int mem_event_get_response(struct domain *d, struct mem_event_domain *med,
mem_event_response_t *rsp);
+struct domain *get_mem_event_op_target(uint32_t domain, int *rc);
+int do_mem_event_op(int op, uint32_t domain, void *arg);
int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
XEN_GUEST_HANDLE(void) u_domctl);
*/
-int mem_paging_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
- XEN_GUEST_HANDLE(void) u_domctl);
+int mem_paging_memop(struct domain *d, xen_mem_event_op_t *meo);
/*
#define __MEM_SHARING_H__
#include <public/domctl.h>
+#include <public/memory.h>
/* Auditing of memory sharing code? */
#define MEM_SHARING_AUDIT 0
unsigned long gfn,
uint16_t flags);
int mem_sharing_sharing_resume(struct domain *d);
+int mem_sharing_memop(struct domain *d,
+ xen_mem_sharing_op_t *mec);
int mem_sharing_domctl(struct domain *d,
xen_domctl_mem_sharing_op_t *mec);
void mem_sharing_init(void);
/*
* Domain memory paging
- * Page memory in and out.
+ * Page memory in and out.
+ * Domctl interface to set up and tear down the
+ * pager<->hypervisor interface. Use XENMEM_paging_op*
+ * to perform per-page operations.
*/
#define XEN_DOMCTL_MEM_EVENT_OP_PAGING 1
#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_ENABLE 0
#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_DISABLE 1
-#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE 2
-#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT 3
-#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP 4
-#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME 5
/*
* Access permissions.
*
+ * As with paging, use the domctl for teardown/setup of the
+ * helper<->hypervisor interface.
+ *
* There are HVM hypercalls to set the per-page access permissions of every
* page in a domain. When one of these permissions--independent, read,
* write, and execute--is violated, the VCPU is paused and a memory event
- * is sent with what happened. (See public/mem_event.h) The memory event
- * handler can then resume the VCPU and redo the access with an
- * ACCESS_RESUME mode for the following domctl.
+ * is sent with what happened. (See public/mem_event.h) .
+ *
+ * The memory event handler can then resume the VCPU and redo the access
+ * with a XENMEM_access_op_resume hypercall.
*/
#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS 2
#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE 0
#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE 1
-#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_RESUME 2
+/* Use for teardown/setup of helper<->hypervisor interface for paging,
+ * access and sharing.*/
struct xen_domctl_mem_event_op {
uint32_t op; /* XEN_DOMCTL_MEM_EVENT_OP_*_* */
uint32_t mode; /* XEN_DOMCTL_MEM_EVENT_OP_* */
- union {
- /* OP_ENABLE IN: Virtual address of shared page */
- uint64_aligned_t shared_addr;
- /* PAGING_PREP IN: buffer to immediately fill page in */
- uint64_aligned_t buffer;
- } u;
+ uint64_aligned_t shared_addr; /* IN: Virtual address of shared page */
uint64_aligned_t ring_addr; /* IN: Virtual address of ring page */
-
- /* Other OPs */
- uint64_aligned_t gfn; /* IN: gfn of page being operated on */
};
typedef struct xen_domctl_mem_event_op xen_domctl_mem_event_op_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_event_op_t);
/*
* Memory sharing operations
*/
-/* XEN_DOMCTL_mem_sharing_op */
-
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING 3
-
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_CONTROL 0
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_NOMINATE_GFN 1
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_NOMINATE_GREF 2
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_SHARE 3
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_RESUME 4
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_GFN 5
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_MFN 6
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_DEBUG_GREF 7
-#define XEN_DOMCTL_MEM_EVENT_OP_SHARING_ADD_PHYSMAP 8
-
-#define XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID (-10)
-#define XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID (-9)
-
-/* The following allows sharing of grant refs. This is useful
- * for sharing utilities sitting as "filters" in IO backends
- * (e.g. memshr + blktap(2)). The IO backend is only exposed
- * to grant references, and this allows sharing of the grefs */
-#define XEN_DOMCTL_MEM_SHARING_FIELD_IS_GREF_FLAG (1ULL << 62)
-
-#define XEN_DOMCTL_MEM_SHARING_FIELD_MAKE_GREF(field, val) \
- (field) = (XEN_DOMCTL_MEM_SHARING_FIELD_IS_GREF_FLAG | val)
-#define XEN_DOMCTL_MEM_SHARING_FIELD_IS_GREF(field) \
- ((field) & XEN_DOMCTL_MEM_SHARING_FIELD_IS_GREF_FLAG)
-#define XEN_DOMCTL_MEM_SHARING_FIELD_GET_GREF(field) \
- ((field) & (~XEN_DOMCTL_MEM_SHARING_FIELD_IS_GREF_FLAG))
+/* XEN_DOMCTL_mem_sharing_op.
+ * The CONTROL sub-domctl is used for bringup/teardown. */
+#define XEN_DOMCTL_MEM_SHARING_CONTROL 0
struct xen_domctl_mem_sharing_op {
- uint8_t op; /* XEN_DOMCTL_MEM_EVENT_OP_* */
+ uint8_t op; /* XEN_DOMCTL_MEM_SHARING_* */
union {
- uint8_t enable; /* OP_CONTROL */
-
- struct mem_sharing_op_nominate { /* OP_NOMINATE_xxx */
- union {
- uint64_aligned_t gfn; /* IN: gfn to nominate */
- uint32_t grant_ref; /* IN: grant ref to nominate */
- } u;
- uint64_aligned_t handle; /* OUT: the handle */
- } nominate;
- struct mem_sharing_op_share { /* OP_SHARE/ADD_PHYSMAP */
- uint64_aligned_t source_gfn; /* IN: the gfn of the source page */
- uint64_aligned_t source_handle; /* IN: handle to the source page */
- domid_t client_domain; /* IN: the client domain id */
- uint64_aligned_t client_gfn; /* IN: the client gfn */
- uint64_aligned_t client_handle; /* IN: handle to the client page */
- } share;
- struct mem_sharing_op_debug { /* OP_DEBUG_xxx */
- union {
- uint64_aligned_t gfn; /* IN: gfn to debug */
- uint64_aligned_t mfn; /* IN: mfn to debug */
- grant_ref_t gref; /* IN: gref to debug */
- } u;
- } debug;
+ uint8_t enable; /* CONTROL */
} u;
};
typedef struct xen_domctl_mem_sharing_op xen_domctl_mem_sharing_op_t;
};
typedef struct xen_pod_target xen_pod_target_t;
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+#ifndef uint64_aligned_t
+#define uint64_aligned_t uint64_t
+#endif
+
/*
* Get the number of MFNs saved through memory sharing.
* The call never fails.
#define XENMEM_get_sharing_freed_pages 18
#define XENMEM_get_sharing_shared_pages 19
+#define XENMEM_paging_op 20
+#define XENMEM_paging_op_nominate 0
+#define XENMEM_paging_op_evict 1
+#define XENMEM_paging_op_prep 2
+#define XENMEM_paging_op_resume 3
+
+#define XENMEM_access_op 21
+#define XENMEM_access_op_resume 0
+
+struct xen_mem_event_op {
+ uint8_t op; /* XENMEM_*_op_* */
+ domid_t domain;
+
+
+ /* PAGING_PREP IN: buffer to immediately fill page in */
+ uint64_aligned_t buffer;
+ /* Other OPs */
+ uint64_aligned_t gfn; /* IN: gfn of page being operated on */
+};
+typedef struct xen_mem_event_op xen_mem_event_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_event_op_t);
+
+#define XENMEM_sharing_op 22
+#define XENMEM_sharing_op_nominate_gfn 0
+#define XENMEM_sharing_op_nominate_gref 1
+#define XENMEM_sharing_op_share 2
+#define XENMEM_sharing_op_resume 3
+#define XENMEM_sharing_op_debug_gfn 4
+#define XENMEM_sharing_op_debug_mfn 5
+#define XENMEM_sharing_op_debug_gref 6
+#define XENMEM_sharing_op_add_physmap 7
+
+#define XENMEM_SHARING_OP_S_HANDLE_INVALID (-10)
+#define XENMEM_SHARING_OP_C_HANDLE_INVALID (-9)
+
+/* The following allows sharing of grant refs. This is useful
+ * for sharing utilities sitting as "filters" in IO backends
+ * (e.g. memshr + blktap(2)). The IO backend is only exposed
+ * to grant references, and this allows sharing of the grefs */
+#define XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG (1ULL << 62)
+
+#define XENMEM_SHARING_OP_FIELD_MAKE_GREF(field, val) \
+ (field) = (XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG | val)
+#define XENMEM_SHARING_OP_FIELD_IS_GREF(field) \
+ ((field) & XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG)
+#define XENMEM_SHARING_OP_FIELD_GET_GREF(field) \
+ ((field) & (~XENMEM_SHARING_OP_FIELD_IS_GREF_FLAG))
+
+struct xen_mem_sharing_op {
+ uint8_t op; /* XENMEM_sharing_op_* */
+ domid_t domain;
+
+ union {
+ struct mem_sharing_op_nominate { /* OP_NOMINATE_xxx */
+ union {
+ uint64_aligned_t gfn; /* IN: gfn to nominate */
+ uint32_t grant_ref; /* IN: grant ref to nominate */
+ } u;
+ uint64_aligned_t handle; /* OUT: the handle */
+ } nominate;
+ struct mem_sharing_op_share { /* OP_SHARE/ADD_PHYSMAP */
+ uint64_aligned_t source_gfn; /* IN: the gfn of the source page */
+ uint64_aligned_t source_handle; /* IN: handle to the source page */
+ uint64_aligned_t client_gfn; /* IN: the client gfn */
+ uint64_aligned_t client_handle; /* IN: handle to the client page */
+ domid_t client_domain; /* IN: the client domain id */
+ } share;
+ struct mem_sharing_op_debug { /* OP_DEBUG_xxx */
+ union {
+ uint64_aligned_t gfn; /* IN: gfn to debug */
+ uint64_aligned_t mfn; /* IN: mfn to debug */
+ uint32_t gref; /* IN: gref to debug */
+ } u;
+ } debug;
+ } u;
+};
+typedef struct xen_mem_sharing_op xen_mem_sharing_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_sharing_op_t);
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
#endif /* __XEN_PUBLIC_MEMORY_H__ */
/*