|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |