[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 01/21] xen: arm: implement XENMEM_add_to_physmap_range



I should have CC'd Keir, Jan and Mukesh on this one and forgot. Done
now.

On Fri, 2012-10-05 at 11:38 +0100, Ian Campbell wrote:
> This allows for foreign mappings as well as batching, fitting all that
> into XENMEM_add_to_physmap wasn't possible.
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> ---
>  xen/arch/arm/mm.c           |  120 
> ++++++++++++++++++++++++++++++++++++++-----
>  xen/include/public/memory.h |   40 +++++++++++---
>  xen/include/public/xen.h    |    1 +
>  3 files changed, 139 insertions(+), 22 deletions(-)
> 
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index 40ac176..dde304b 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -25,6 +25,8 @@
>  #include <xen/mm.h>
>  #include <xen/preempt.h>
>  #include <xen/errno.h>
> +#include <xen/softirq.h>
> +#include <xen/event.h>
>  #include <xen/guest_access.h>
>  #include <xen/domain_page.h>
>  #include <asm/page.h>
> @@ -461,37 +463,96 @@ void share_xen_page_with_guest(struct page_info *page,
>      spin_unlock(&d->page_alloc_lock);
>  }
>  
> -static int xenmem_add_to_physmap_once(
> +static int xenmem_add_to_physmap_one(
>      struct domain *d,
> -    const struct xen_add_to_physmap *xatp)
> +    uint16_t space,
> +    domid_t foreign_domid,
> +    unsigned long idx,
> +    xen_pfn_t gpfn)
>  {
>      unsigned long mfn = 0;
>      int rc;
>  
> -    switch ( xatp->space )
> +    switch ( space )
>      {
> -        case XENMAPSPACE_shared_info:
> -            if ( xatp->idx == 0 )
> -                mfn = virt_to_mfn(d->shared_info);
> -            break;
> -        default:
> -            return -ENOSYS;
> +    case XENMAPSPACE_shared_info:
> +        if ( idx == 0 )
> +            mfn = virt_to_mfn(d->shared_info);
> +        break;
> +    case XENMAPSPACE_gmfn_foreign:
> +    {
> +        paddr_t maddr;
> +        struct domain *od;
> +        rc = rcu_lock_target_domain_by_id(foreign_domid, &od);
> +        if ( rc < 0 )
> +            return rc;
> +
> +        maddr = p2m_lookup(od, idx << PAGE_SHIFT);
> +        if ( maddr == INVALID_PADDR )
> +        {
> +            dump_p2m_lookup(od, idx << PAGE_SHIFT);
> +            rcu_unlock_domain(od);
> +            return -EINVAL;
> +        }
> +
> +        mfn = maddr >> PAGE_SHIFT;
> +
> +        rcu_unlock_domain(od);
> +        break;
> +    }
> +
> +    default:
> +        return -ENOSYS;
>      }
>  
>      domain_lock(d);
>  
>      /* Map at new location. */
> -    rc = guest_physmap_add_page(d, xatp->gpfn, mfn, 0);
> +    rc = guest_physmap_add_page(d, gpfn, mfn, 0);
>  
>      domain_unlock(d);
>  
>      return rc;
>  }
>  
> -static int xenmem_add_to_physmap(struct domain *d,
> -                                 struct xen_add_to_physmap *xatp)
> +static int xenmem_add_to_physmap_range(struct domain *d,
> +                                       struct xen_add_to_physmap_range 
> *xatpr)
>  {
> -    return xenmem_add_to_physmap_once(d, xatp);
> +    int rc;
> +
> +    /* Process entries in reverse order to allow continuations */
> +    while ( xatpr->size > 0 )
> +    {
> +        xen_ulong_t idx;
> +        xen_pfn_t gpfn;
> +
> +        rc = copy_from_guest_offset(&idx, xatpr->idxs, xatpr->size-1, 1);
> +        if ( rc < 0 )
> +            goto out;
> +
> +        rc = copy_from_guest_offset(&gpfn, xatpr->gpfns, xatpr->size-1, 1);
> +        if ( rc < 0 )
> +            goto out;
> +
> +        rc = xenmem_add_to_physmap_one(d, xatpr->space,
> +                                       xatpr->foreign_domid,
> +                                       idx, gpfn);
> +
> +        xatpr->size--;
> +
> +        /* Check for continuation if it's not the last interation */
> +        if ( xatpr->size > 0 && hypercall_preempt_check() )
> +        {
> +            rc = -EAGAIN;
> +            goto out;
> +        }
> +    }
> +
> +    rc = 0;
> +
> +out:
> +    return rc;
> +
>  }
>  
>  long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
> @@ -508,14 +569,45 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
>          if ( copy_from_guest(&xatp, arg, 1) )
>              return -EFAULT;
>  
> +        /* This one is only supported by add_to_physmap_range */
> +        if ( xatp.space == XENMAPSPACE_gmfn_foreign )
> +            return -EINVAL;
> +
>          rc = rcu_lock_target_domain_by_id(xatp.domid, &d);
>          if ( rc != 0 )
>              return rc;
>  
> -        rc = xenmem_add_to_physmap(d, &xatp);
> +        rc = xenmem_add_to_physmap_one(d, xatp.space, DOMID_INVALID,
> +                                       xatp.idx, xatp.gpfn);
> +
> +        rcu_unlock_domain(d);
> +
> +        return rc;
> +    }
> +
> +    case XENMEM_add_to_physmap_range:
> +    {
> +        struct xen_add_to_physmap_range xatpr;
> +        struct domain *d;
> +
> +        if ( copy_from_guest(&xatpr, arg, 1) )
> +            return -EFAULT;
> +
> +        rc = rcu_lock_target_domain_by_id(xatpr.domid, &d);
> +        if ( rc != 0 )
> +            return rc;
> +
> +        rc = xenmem_add_to_physmap_range(d, &xatpr);
>  
>          rcu_unlock_domain(d);
>  
> +        if ( rc && copy_to_guest(arg, &xatpr, 1) )
> +            rc = -EFAULT;
> +
> +        if ( rc == -EAGAIN )
> +            rc = hypercall_create_continuation(
> +                __HYPERVISOR_memory_op, "ih", op, arg);
> +
>          return rc;
>      }
>  
> diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
> index 86d02c8..f1ddbc0 100644
> --- a/xen/include/public/memory.h
> +++ b/xen/include/public/memory.h
> @@ -198,6 +198,15 @@ struct xen_machphys_mapping {
>  typedef struct xen_machphys_mapping xen_machphys_mapping_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
>  
> +/* Source mapping space. */
> +/* ` enum phys_map_space { */
> +#define XENMAPSPACE_shared_info  0 /* shared info page */
> +#define XENMAPSPACE_grant_table  1 /* grant table page */
> +#define XENMAPSPACE_gmfn         2 /* GMFN */
> +#define XENMAPSPACE_gmfn_range   3 /* GMFN range */
> +#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom */
> +/* ` } */
> +
>  /*
>   * Sets the GPFN at which a particular page appears in the specified guest's
>   * pseudophysical address space.
> @@ -211,24 +220,39 @@ struct xen_add_to_physmap {
>      /* Number of pages to go through for gmfn_range */
>      uint16_t    size;
>  
> -    /* Source mapping space. */
> -#define XENMAPSPACE_shared_info 0 /* shared info page */
> -#define XENMAPSPACE_grant_table 1 /* grant table page */
> -#define XENMAPSPACE_gmfn        2 /* GMFN */
> -#define XENMAPSPACE_gmfn_range  3 /* GMFN range */
> -    unsigned int space;
> +    unsigned int space; /* => enum phys_map_space */
>  
>  #define XENMAPIDX_grant_table_status 0x80000000
>  
> -    /* Index into source mapping space. */
> +    /* Index into space being mapped. */
>      xen_ulong_t idx;
>  
> -    /* GPFN where the source mapping page should appear. */
> +    /* GPFN in domid where the source mapping page should appear. */
>      xen_pfn_t     gpfn;
>  };
>  typedef struct xen_add_to_physmap xen_add_to_physmap_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
>  
> +/* A batched version of add_to_physmap. */
> +#define XENMEM_add_to_physmap_range 23
> +struct xen_add_to_physmap_range {
> +    /* Which domain to change the mapping for. */
> +    domid_t domid;
> +    uint16_t space; /* => enum phys_map_space */
> +
> +    /* Number of pages to go through */
> +    uint16_t size;
> +    domid_t foreign_domid; /* IFF gmfn_foreign */
> +
> +    /* Indexes into space being mapped. */
> +    XEN_GUEST_HANDLE(xen_ulong_t) idxs;
> +
> +    /* GPFN in domdwhere the source mapping page should appear. */
> +    XEN_GUEST_HANDLE(xen_pfn_t) gpfns;
> +};
> +typedef struct xen_add_to_physmap_range xen_add_to_physmap_range_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_range_t);
> +
>  /*
>   * Unmaps the page appearing at a particular GPFN from the specified guest's
>   * pseudophysical address space.
> diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
> index 361398b..e42d01f 100644
> --- a/xen/include/public/xen.h
> +++ b/xen/include/public/xen.h
> @@ -49,6 +49,7 @@ DEFINE_XEN_GUEST_HANDLE(void);
>  
>  DEFINE_XEN_GUEST_HANDLE(uint64_t);
>  DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
> +DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
>  #endif
>  
>  /*



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.