#include <asm/p2m.h>
-#include <xen/vm_event.h>
+#include <xen/guest_access.h>
+#include <xsm/xsm.h>
-
-int mem_paging_memop(struct domain *d, xen_mem_paging_op_t *mpo)
+int mem_paging_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_paging_op_t) arg)
{
- int rc = -ENODEV;
- if ( unlikely(!d->vm_event->paging.ring_page) )
+ int rc;
+ xen_mem_paging_op_t mpo;
+ struct domain *d;
+ bool_t copyback = 0;
+
+ if ( copy_from_guest(&mpo, arg, 1) )
+ return -EFAULT;
+
+ rc = rcu_lock_live_remote_domain_by_id(mpo.domain, &d);
+ if ( rc )
return rc;
- switch( mpo->op )
+ rc = xsm_vm_event_op(XSM_DM_PRIV, d, XENMEM_paging_op);
+ if ( rc )
+ goto out;
+
+ rc = -ENODEV;
+ if ( unlikely(!d->vm_event->paging.ring_page) )
+ goto out;
+
+ switch( mpo.op )
{
case XENMEM_paging_op_nominate:
- rc = p2m_mem_paging_nominate(d, mpo->gfn);
+ rc = p2m_mem_paging_nominate(d, mpo.gfn);
break;
case XENMEM_paging_op_evict:
- rc = p2m_mem_paging_evict(d, mpo->gfn);
+ rc = p2m_mem_paging_evict(d, mpo.gfn);
break;
case XENMEM_paging_op_prep:
- rc = p2m_mem_paging_prep(d, mpo->gfn, mpo->buffer);
+ rc = p2m_mem_paging_prep(d, mpo.gfn, mpo.buffer);
+ if ( !rc )
+ copyback = 1;
break;
default:
break;
}
+ if ( copyback && __copy_to_guest(arg, &mpo, 1) )
+ rc = -EFAULT;
+
+out:
+ rcu_unlock_domain(d);
return rc;
}
#include <xen/grant_table.h>
#include <xen/sched.h>
#include <xen/rcupdate.h>
+#include <xen/guest_access.h>
#include <xen/vm_event.h>
#include <asm/page.h>
#include <asm/string.h>
return rc;
}
-int mem_sharing_memop(struct domain *d, xen_mem_sharing_op_t *mec)
+int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
{
- int rc = 0;
+ int rc;
+ xen_mem_sharing_op_t mso;
+ struct domain *d;
+
+ rc = -EFAULT;
+ if ( copy_from_guest(&mso, arg, 1) )
+ return rc;
+
+ if ( mso.op == XENMEM_sharing_op_audit )
+ return mem_sharing_audit();
+
+ rc = rcu_lock_live_remote_domain_by_id(mso.domain, &d);
+ if ( rc )
+ return rc;
+
+ rc = xsm_vm_event_op(XSM_DM_PRIV, d, XENMEM_sharing_op);
+ if ( rc )
+ goto out;
/* Only HAP is supported */
+ rc = -ENODEV;
if ( !hap_enabled(d) || !d->arch.hvm_domain.mem_sharing_enabled )
- return -ENODEV;
+ goto out;
- switch(mec->op)
+ rc = -ENODEV;
+ if ( unlikely(!d->vm_event->share.ring_page) )
+ goto out;
+
+ switch ( mso.op )
{
case XENMEM_sharing_op_nominate_gfn:
{
- unsigned long gfn = mec->u.nominate.u.gfn;
+ unsigned long gfn = mso.u.nominate.u.gfn;
shr_handle_t handle;
+
+ rc = -EINVAL;
if ( !mem_sharing_enabled(d) )
- return -EINVAL;
+ goto out;
+
rc = mem_sharing_nominate_page(d, gfn, 0, &handle);
- mec->u.nominate.handle = handle;
+ mso.u.nominate.handle = handle;
}
break;
case XENMEM_sharing_op_nominate_gref:
{
- grant_ref_t gref = mec->u.nominate.u.grant_ref;
+ grant_ref_t gref = mso.u.nominate.u.grant_ref;
unsigned long gfn;
shr_handle_t handle;
+ rc = -EINVAL;
if ( !mem_sharing_enabled(d) )
- return -EINVAL;
+ goto out;
if ( mem_sharing_gref_to_gfn(d, gref, &gfn) < 0 )
- return -EINVAL;
+ goto out;
+
rc = mem_sharing_nominate_page(d, gfn, 3, &handle);
- mec->u.nominate.handle = handle;
+ mso.u.nominate.handle = handle;
}
break;
struct domain *cd;
shr_handle_t sh, ch;
+ rc = -EINVAL;
if ( !mem_sharing_enabled(d) )
- return -EINVAL;
+ goto out;
- rc = rcu_lock_live_remote_domain_by_id(mec->u.share.client_domain,
+ rc = rcu_lock_live_remote_domain_by_id(mso.u.share.client_domain,
&cd);
if ( rc )
- return rc;
+ goto out;
- rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mec->op);
+ rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mso.op);
if ( rc )
{
rcu_unlock_domain(cd);
- return rc;
+ goto out;
}
if ( !mem_sharing_enabled(cd) )
{
rcu_unlock_domain(cd);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
- if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mec->u.share.source_gfn) )
+ if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mso.u.share.source_gfn) )
{
grant_ref_t gref = (grant_ref_t)
(XENMEM_SHARING_OP_FIELD_GET_GREF(
- mec->u.share.source_gfn));
+ mso.u.share.source_gfn));
if ( mem_sharing_gref_to_gfn(d, gref, &sgfn) < 0 )
{
rcu_unlock_domain(cd);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
} else {
- sgfn = mec->u.share.source_gfn;
+ sgfn = mso.u.share.source_gfn;
}
- if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mec->u.share.client_gfn) )
+ if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mso.u.share.client_gfn) )
{
grant_ref_t gref = (grant_ref_t)
(XENMEM_SHARING_OP_FIELD_GET_GREF(
- mec->u.share.client_gfn));
+ mso.u.share.client_gfn));
if ( mem_sharing_gref_to_gfn(cd, gref, &cgfn) < 0 )
{
rcu_unlock_domain(cd);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
} else {
- cgfn = mec->u.share.client_gfn;
+ cgfn = mso.u.share.client_gfn;
}
- sh = mec->u.share.source_handle;
- ch = mec->u.share.client_handle;
+ sh = mso.u.share.source_handle;
+ ch = mso.u.share.client_handle;
rc = mem_sharing_share_pages(d, sgfn, sh, cd, cgfn, ch);
struct domain *cd;
shr_handle_t sh;
+ rc = -EINVAL;
if ( !mem_sharing_enabled(d) )
- return -EINVAL;
+ goto out;
- rc = rcu_lock_live_remote_domain_by_id(mec->u.share.client_domain,
+ rc = rcu_lock_live_remote_domain_by_id(mso.u.share.client_domain,
&cd);
if ( rc )
- return rc;
+ goto out;
- rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mec->op);
+ rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mso.op);
if ( rc )
{
rcu_unlock_domain(cd);
- return rc;
+ goto out;
}
if ( !mem_sharing_enabled(cd) )
{
rcu_unlock_domain(cd);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
- if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mec->u.share.source_gfn) )
+ if ( XENMEM_SHARING_OP_FIELD_IS_GREF(mso.u.share.source_gfn) )
{
/* Cannot add a gref to the physmap */
rcu_unlock_domain(cd);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
- sgfn = mec->u.share.source_gfn;
- sh = mec->u.share.source_handle;
- cgfn = mec->u.share.client_gfn;
+ sgfn = mso.u.share.source_gfn;
+ sh = mso.u.share.source_handle;
+ cgfn = mso.u.share.client_gfn;
rc = mem_sharing_add_to_physmap(d, sgfn, sh, cd, cgfn);
case XENMEM_sharing_op_resume:
{
if ( !mem_sharing_enabled(d) )
- return -EINVAL;
+ {
+ rc = -EINVAL;
+ goto out;
+ }
vm_event_resume(d, &d->vm_event->share);
}
case XENMEM_sharing_op_debug_gfn:
{
- unsigned long gfn = mec->u.debug.u.gfn;
+ unsigned long gfn = mso.u.debug.u.gfn;
rc = mem_sharing_debug_gfn(d, gfn);
}
break;
case XENMEM_sharing_op_debug_gref:
{
- grant_ref_t gref = mec->u.debug.u.gref;
+ grant_ref_t gref = mso.u.debug.u.gref;
rc = mem_sharing_debug_gref(d, gref);
}
break;
break;
}
+ if ( !rc && __copy_to_guest(arg, &mso, 1) )
+ rc = -EFAULT;
+
+out:
+ rcu_unlock_domain(d);
return rc;
}
#include <xen/event.h>
-#include <xen/vm_event.h>
#include <xen/mem_access.h>
#include <xen/multicall.h>
#include <compat/memory.h>
#include <compat/xen.h>
+#include <asm/mem_paging.h>
#include <asm/mem_sharing.h>
int compat_set_gdt(XEN_GUEST_HANDLE_PARAM(uint) frame_list, unsigned int entries)
return mem_sharing_get_nr_shared_mfns();
case XENMEM_paging_op:
- {
- xen_mem_paging_op_t mpo;
-
- if ( copy_from_guest(&mpo, arg, 1) )
- return -EFAULT;
- rc = do_vm_event_op(cmd, mpo.domain, &mpo);
- if ( !rc && __copy_to_guest(arg, &mpo, 1) )
- return -EFAULT;
- break;
- }
+ return mem_paging_memop(guest_handle_cast(arg, xen_mem_paging_op_t));
case XENMEM_sharing_op:
- {
- xen_mem_sharing_op_t mso;
-
- if ( copy_from_guest(&mso, arg, 1) )
- return -EFAULT;
- if ( mso.op == XENMEM_sharing_op_audit )
- return mem_sharing_audit();
- rc = do_vm_event_op(cmd, mso.domain, &mso);
- if ( !rc && __copy_to_guest(arg, &mso, 1) )
- return -EFAULT;
- break;
- }
+ return mem_sharing_memop(guest_handle_cast(arg, xen_mem_sharing_op_t));
default:
rc = -ENOSYS;
#include <xen/nodemask.h>
#include <xen/guest_access.h>
#include <xen/hypercall.h>
-#include <xen/vm_event.h>
#include <xen/mem_access.h>
#include <asm/current.h>
#include <asm/asm_defns.h>
#include <asm/msr.h>
#include <asm/setup.h>
#include <asm/numa.h>
+#include <asm/mem_paging.h>
#include <asm/mem_sharing.h>
#include <public/memory.h>
return mem_sharing_get_nr_shared_mfns();
case XENMEM_paging_op:
- {
- xen_mem_paging_op_t mpo;
- if ( copy_from_guest(&mpo, arg, 1) )
- return -EFAULT;
- rc = do_vm_event_op(cmd, mpo.domain, &mpo);
- if ( !rc && __copy_to_guest(arg, &mpo, 1) )
- return -EFAULT;
- break;
- }
+ return mem_paging_memop(guest_handle_cast(arg, xen_mem_paging_op_t));
case XENMEM_sharing_op:
- {
- xen_mem_sharing_op_t mso;
- if ( copy_from_guest(&mso, arg, 1) )
- return -EFAULT;
- if ( mso.op == XENMEM_sharing_op_audit )
- return mem_sharing_audit();
- rc = do_vm_event_op(cmd, mso.domain, &mso);
- if ( !rc && __copy_to_guest(arg, &mso, 1) )
- return -EFAULT;
- break;
- }
+ return mem_sharing_memop(guest_handle_cast(arg, xen_mem_sharing_op_t));
default:
rc = -ENOSYS;
#include <xen/vm_event.h>
#include <xen/mem_access.h>
#include <asm/p2m.h>
-
-#ifdef HAS_MEM_PAGING
-#include <asm/mem_paging.h>
-#endif
-
-#ifdef HAS_MEM_SHARING
-#include <asm/mem_sharing.h>
-#endif
-
#include <xsm/xsm.h>
/* for public/io/ring.h macros */
}
#endif
-int do_vm_event_op(int op, uint32_t domain, void *arg)
-{
- int ret;
- struct domain *d;
-
- ret = rcu_lock_live_remote_domain_by_id(domain, &d);
- if ( ret )
- return ret;
-
- ret = xsm_vm_event_op(XSM_DM_PRIV, d, op);
- if ( ret )
- goto out;
-
- switch (op)
- {
-#ifdef HAS_MEM_PAGING
- case XENMEM_paging_op:
- ret = mem_paging_memop(d, arg);
- break;
-#endif
-#ifdef HAS_MEM_SHARING
- case XENMEM_sharing_op:
- ret = mem_sharing_memop(d, arg);
- break;
-#endif
- default:
- ret = -ENOSYS;
- }
-
- out:
- rcu_unlock_domain(d);
- return ret;
-}
-
/* Clean up on domain destruction */
void vm_event_cleanup(struct domain *d)
{
#ifndef __ASM_X86_MEM_PAGING_H__
#define __ASM_X86_MEM_PAGING_H__
-int mem_paging_memop(struct domain *d, xen_mem_paging_op_t *mpo);
+int mem_paging_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_paging_op_t) arg);
#endif /*__ASM_X86_MEM_PAGING_H__ */
*/
int mem_sharing_notify_enomem(struct domain *d, unsigned long gfn,
bool_t allow_sleep);
-int mem_sharing_memop(struct domain *d,
- xen_mem_sharing_op_t *mec);
+int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg);
int mem_sharing_domctl(struct domain *d,
xen_domctl_mem_sharing_op_t *mec);
int mem_sharing_audit(void);
void vm_event_resume(struct domain *d, struct vm_event_domain *ved);
-int do_vm_event_op(int op, uint32_t domain, void *arg);
int vm_event_domctl(struct domain *d, xen_domctl_vm_event_op_t *vec,
XEN_GUEST_HANDLE_PARAM(void) u_domctl);