@@ -1400,6 +1400,24 @@ static int range_share(struct domain *d, struct domain *cd,
return rc;
}
+static inline int mem_sharing_control(struct domain *d, bool enable)
+{
+ if ( enable )
+ {
+ if ( unlikely(!is_hvm_domain(d)) )
+ return -EOPNOTSUPP;
+
+ if ( unlikely(!hap_enabled(d)) )
+ return -ENODEV;
+
+ if ( unlikely(is_iommu_enabled(d)) )
+ return -EXDEV;
+ }
+
+ d->arch.hvm.mem_sharing.enabled = enable;
+ return 0;
+}
+
int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
{
int rc;
@@ -1421,10 +1439,8 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
if ( rc )
goto out;
- /* Only HAP is supported */
- rc = -ENODEV;
- if ( !mem_sharing_enabled(d) )
- goto out;
+ if ( !mem_sharing_enabled(d) && (rc = mem_sharing_control(d, true)) )
+ return rc;
switch ( mso.op )
{
@@ -1432,10 +1448,6 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
{
shr_handle_t handle;
- rc = -EINVAL;
- if ( !mem_sharing_enabled(d) )
- goto out;
-
rc = nominate_page(d, _gfn(mso.u.nominate.u.gfn), 0, &handle);
mso.u.nominate.handle = handle;
}
@@ -1447,9 +1459,6 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
gfn_t gfn;
shr_handle_t handle;
- rc = -EINVAL;
- if ( !mem_sharing_enabled(d) )
- goto out;
rc = mem_sharing_gref_to_gfn(d->grant_table, gref, &gfn, NULL);
if ( rc < 0 )
goto out;
@@ -1465,10 +1474,6 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
struct domain *cd;
shr_handle_t sh, ch;
- rc = -EINVAL;
- if ( !mem_sharing_enabled(d) )
- goto out;
-
rc = rcu_lock_live_remote_domain_by_id(mso.u.share.client_domain,
&cd);
if ( rc )
@@ -1535,10 +1540,6 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
struct domain *cd;
shr_handle_t sh;
- rc = -EINVAL;
- if ( !mem_sharing_enabled(d) )
- goto out;
-
rc = rcu_lock_live_remote_domain_by_id(mso.u.share.client_domain,
&cd);
if ( rc )
@@ -1597,9 +1598,6 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
mso.u.range.opaque > mso.u.range.last_gfn) )
goto out;
- if ( !mem_sharing_enabled(d) )
- goto out;
-
rc = rcu_lock_live_remote_domain_by_id(mso.u.range.client_domain,
&cd);
if ( rc )
@@ -1691,18 +1689,10 @@ int mem_sharing_domctl(struct domain *d, struct xen_domctl_mem_sharing_op *mec)
{
int rc;
- /* Only HAP is supported */
- if ( !hap_enabled(d) )
- return -ENODEV;
-
switch ( mec->op )
{
case XEN_DOMCTL_MEM_SHARING_CONTROL:
- rc = 0;
- if ( unlikely(is_iommu_enabled(d) && mec->u.enable) )
- rc = -EXDEV;
- else
- d->arch.hvm.mem_sharing_enabled = mec->u.enable;
+ rc = mem_sharing_control(d, mec->u.enable);
break;
default:
It is wasteful to require separate hypercalls to enable sharing on both the parent and the client domain during VM forking. To speed things up we enable sharing on the first memop in case it wasn't already enabled. Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com> --- xen/arch/x86/mm/mem_sharing.c | 52 ++++++++++++++--------------------- 1 file changed, 21 insertions(+), 31 deletions(-)