diff options
-rw-r--r-- | tools/libxc/xc_mem_access.c | 12 | ||||
-rw-r--r-- | tools/libxc/xc_mem_event.c | 23 | ||||
-rw-r--r-- | tools/libxc/xc_mem_paging.c | 44 | ||||
-rw-r--r-- | tools/libxc/xc_memshr.c | 182 | ||||
-rw-r--r-- | tools/libxc/xenctrl.h | 6 | ||||
-rw-r--r-- | tools/memshr/interface.c | 4 | ||||
-rw-r--r-- | tools/tests/mem-sharing/memshrtool.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/domctl.c | 1 | ||||
-rw-r--r-- | xen/arch/x86/mm/mem_access.c | 7 | ||||
-rw-r--r-- | xen/arch/x86/mm/mem_event.c | 68 | ||||
-rw-r--r-- | xen/arch/x86/mm/mem_paging.c | 13 | ||||
-rw-r--r-- | xen/arch/x86/mm/mem_sharing.c | 99 | ||||
-rw-r--r-- | xen/arch/x86/x86_64/compat/mm.c | 23 | ||||
-rw-r--r-- | xen/arch/x86/x86_64/mm.c | 23 | ||||
-rw-r--r-- | xen/include/asm-x86/mem_access.h | 3 | ||||
-rw-r--r-- | xen/include/asm-x86/mem_event.h | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/mem_paging.h | 3 | ||||
-rw-r--r-- | xen/include/asm-x86/mem_sharing.h | 3 | ||||
-rw-r--r-- | xen/include/public/domctl.h | 90 | ||||
-rw-r--r-- | xen/include/public/memory.h | 87 |
20 files changed, 421 insertions, 276 deletions
diff --git a/tools/libxc/xc_mem_access.c b/tools/libxc/xc_mem_access.c index 6606878567..3dca355dc1 100644 --- a/tools/libxc/xc_mem_access.c +++ b/tools/libxc/xc_mem_access.c @@ -30,7 +30,7 @@ int xc_mem_access_enable(xc_interface *xch, domid_t domain_id, 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) @@ -38,15 +38,15 @@ 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); } /* diff --git a/tools/libxc/xc_mem_event.c b/tools/libxc/xc_mem_event.c index 80259071b1..a568a52e77 100644 --- a/tools/libxc/xc_mem_event.c +++ b/tools/libxc/xc_mem_event.c @@ -24,8 +24,7 @@ #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; @@ -34,11 +33,25 @@ int xc_mem_event_control(xc_interface *xch, domid_t domain_id, unsigned int op, 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)); +} + diff --git a/tools/libxc/xc_mem_paging.c b/tools/libxc/xc_mem_paging.c index a108a5c4cf..eaf713388f 100644 --- a/tools/libxc/xc_mem_paging.c +++ b/tools/libxc/xc_mem_paging.c @@ -30,7 +30,7 @@ int xc_mem_paging_enable(xc_interface *xch, domid_t domain_id, 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) @@ -38,31 +38,31 @@ 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, @@ -81,10 +81,10 @@ 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); @@ -95,10 +95,10 @@ int xc_mem_paging_load(xc_interface *xch, domid_t domain_id, 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); } 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) diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index e6fd488af8..371a97f5e8 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -1883,8 +1883,10 @@ int xc_tmem_restore_extra(xc_interface *xch, int dom, int fd); * 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); diff --git a/tools/memshr/interface.c b/tools/memshr/interface.c index b4d6d4e190..1c39dfa77d 100644 --- a/tools/memshr/interface.c +++ b/tools/memshr/interface.c @@ -186,12 +186,12 @@ int memshr_vbd_issue_ro_request(char *buf, 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); diff --git a/tools/tests/mem-sharing/memshrtool.c b/tools/tests/mem-sharing/memshrtool.c index b876619ac9..a5dfc24f94 100644 --- a/tools/tests/mem-sharing/memshrtool.c +++ b/tools/tests/mem-sharing/memshrtool.c @@ -34,9 +34,9 @@ static int usage(const char* prog) 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; \ } \ diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 831cddaa15..931f9d39f5 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1463,7 +1463,6 @@ long arch_do_domctl( if ( !ret ) ret = mem_sharing_domctl(d, &domctl->u.mem_sharing_op); rcu_unlock_domain(d); - copy_to_guest(u_domctl, domctl, 1); } } break; diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c index f52d993840..94a4c30f04 100644 --- a/xen/arch/x86/mm/mem_access.c +++ b/xen/arch/x86/mm/mem_access.c @@ -25,14 +25,13 @@ #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; diff --git a/xen/arch/x86/mm/mem_event.c b/xen/arch/x86/mm/mem_event.c index b1333e1330..138fcdfdf6 100644 --- a/xen/arch/x86/mm/mem_event.c +++ b/xen/arch/x86/mm/mem_event.c @@ -28,6 +28,7 @@ #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() @@ -49,7 +50,7 @@ static int mem_event_enable( 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; @@ -460,6 +461,54 @@ static void mem_access_notification(struct vcpu *v, unsigned int port) 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) { @@ -533,11 +582,8 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, break; default: - { - if ( med->ring_page ) - rc = mem_paging_domctl(d, mec, u_domctl); - } - break; + rc = -ENOSYS; + break; } } break; @@ -572,14 +618,14 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, break; default: - { - if ( med->ring_page ) - rc = mem_access_domctl(d, mec, u_domctl); - } - break; + rc = -ENOSYS; + break; } } break; + + default: + rc = -ENOSYS; } return rc; diff --git a/xen/arch/x86/mm/mem_paging.c b/xen/arch/x86/mm/mem_paging.c index 14b3827664..4fdf3d74b8 100644 --- a/xen/arch/x86/mm/mem_paging.c +++ b/xen/arch/x86/mm/mem_paging.c @@ -25,33 +25,32 @@ #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; diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c index 062d53b849..7ac3e81899 100644 --- a/xen/arch/x86/mm/mem_sharing.c +++ b/xen/arch/x86/mm/mem_sharing.c @@ -747,12 +747,12 @@ int mem_sharing_share_pages(struct domain *sd, unsigned long sgfn, shr_handle_t } 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 ) { @@ -760,12 +760,12 @@ int mem_sharing_share_pages(struct domain *sd, unsigned long sgfn, shr_handle_t 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 ) { @@ -780,14 +780,14 @@ int mem_sharing_share_pages(struct domain *sd, unsigned long sgfn, shr_handle_t /* 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; @@ -849,7 +849,7 @@ int mem_sharing_add_to_physmap(struct domain *sd, unsigned long sgfn, shr_handle 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; @@ -863,7 +863,7 @@ int mem_sharing_add_to_physmap(struct domain *sd, unsigned long sgfn, shr_handle 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; } @@ -1014,9 +1014,9 @@ private_page_found: 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) ) @@ -1024,14 +1024,7 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) 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; @@ -1042,7 +1035,7 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) } 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; @@ -1057,7 +1050,7 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) } break; - case XEN_DOMCTL_MEM_EVENT_OP_SHARING_SHARE: + case XENMEM_sharing_op_share: { unsigned long sgfn, cgfn; struct domain *cd; @@ -1066,38 +1059,38 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) 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 { @@ -1109,11 +1102,11 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) 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; @@ -1122,20 +1115,20 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) 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; } @@ -1145,11 +1138,11 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) 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; @@ -1157,21 +1150,21 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) } 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); @@ -1188,6 +1181,30 @@ int mem_sharing_domctl(struct domain *d, xen_domctl_mem_sharing_op_t *mec) 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"); diff --git a/xen/arch/x86/x86_64/compat/mm.c b/xen/arch/x86/x86_64/compat/mm.c index 93325792f5..43d33cb8fb 100644 --- a/xen/arch/x86/x86_64/compat/mm.c +++ b/xen/arch/x86/x86_64/compat/mm.c @@ -2,6 +2,7 @@ #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) { @@ -211,6 +212,28 @@ int compat_arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) 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; diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index 25bbbd1c7a..6121701db1 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -34,6 +34,7 @@ #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> @@ -1100,6 +1101,28 @@ long subarch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) 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; diff --git a/xen/include/asm-x86/mem_access.h b/xen/include/asm-x86/mem_access.h index fe3c349aa7..30ab2190ea 100644 --- a/xen/include/asm-x86/mem_access.h +++ b/xen/include/asm-x86/mem_access.h @@ -21,8 +21,7 @@ */ -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); diff --git a/xen/include/asm-x86/mem_event.h b/xen/include/asm-x86/mem_event.h index 7b2d4d3a88..3111ce77d2 100644 --- a/xen/include/asm-x86/mem_event.h +++ b/xen/include/asm-x86/mem_event.h @@ -42,6 +42,8 @@ void mem_event_put_request(struct domain *d, struct mem_event_domain *med, 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); diff --git a/xen/include/asm-x86/mem_paging.h b/xen/include/asm-x86/mem_paging.h index a6cc1a09c2..51fe80e326 100644 --- a/xen/include/asm-x86/mem_paging.h +++ b/xen/include/asm-x86/mem_paging.h @@ -21,8 +21,7 @@ */ -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); /* diff --git a/xen/include/asm-x86/mem_sharing.h b/xen/include/asm-x86/mem_sharing.h index f95e3a25b0..34fc2fe106 100644 --- a/xen/include/asm-x86/mem_sharing.h +++ b/xen/include/asm-x86/mem_sharing.h @@ -23,6 +23,7 @@ #define __MEM_SHARING_H__ #include <public/domctl.h> +#include <public/memory.h> /* Auditing of memory sharing code? */ #define MEM_SHARING_AUDIT 0 @@ -56,6 +57,8 @@ int mem_sharing_unshare_page(struct domain *d, 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); diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 16f9fd2390..546b22fc45 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -711,47 +711,43 @@ struct xen_domctl_gdbsx_domstatus { /* * 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); @@ -759,63 +755,15 @@ 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; diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 9d9aabcfdb..be82ab1285 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -305,6 +305,12 @@ struct xen_pod_target { }; 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. @@ -312,6 +318,87 @@ typedef struct xen_pod_target xen_pod_target_t; #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__ */ /* |