[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6 5/5] xen: introduce XENMEM_pin
Introduce a new hypercall to allow a guest to pin one or more pages whose machine addresses respect the number of bits addressable by the caller as expressed by the address_bits field. Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> --- xen/common/memory.c | 93 +++++++++++++++++++++++++++++++++++++++++++ xen/include/public/memory.h | 33 +++++++++++++++ 2 files changed, 126 insertions(+), 0 deletions(-) diff --git a/xen/common/memory.c b/xen/common/memory.c index 31a85be..93171d0 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -743,6 +743,95 @@ static int unpin(XEN_GUEST_HANDLE_PARAM(xen_unpin_t) arg) return rc; } +static long pin(XEN_GUEST_HANDLE_PARAM(xen_pin_t) arg) +{ + int rc; + unsigned long i = 0, j; + struct xen_pin pin; + xen_pfn_t gpfn, mfn; + struct domain *d = NULL; + unsigned int memflags = 0; + + if ( copy_from_guest(&pin, arg, 1) ) + return -EFAULT; + + /* Various sanity checks. */ + if ( /* Extent orders are sensible? */ + (pin.in.extent_order > MAX_ORDER) || + /* Sizes of input list do not overflow a long? */ + ((~0UL >> pin.in.extent_order) < pin.in.nr_extents) ) + { + rc = -EFAULT; + goto fail; + } + + if ( !guest_handle_okay(pin.in.extent_start, pin.in.nr_extents) ) + { + rc = -EFAULT; + goto fail; + } + + d = rcu_lock_domain_by_any_id(pin.in.domid); + if ( d == NULL ) + { + rc = -ESRCH; + goto fail; + } + + if ( !is_hardware_domain(d) ) + { + rc = -EPERM; + goto fail; + } + + memflags |= MEMF_bits(domain_clamp_alloc_bitsize( + d, + XENMEMF_get_address_bits(pin.in.mem_flags) ? : + (BITS_PER_LONG+PAGE_SHIFT))); + + for ( ; i < pin.in.nr_extents; i++ ) + { + if ( unlikely(__copy_from_guest_offset( + &gpfn, pin.in.extent_start, i, 1)) ) + { + rc = -EFAULT; + goto fail; + } + + if ( generic_fls64(gpfn << PAGE_SHIFT) > memflags ) + { + rc = -EINVAL; + goto fail; + } + + rc = guest_physmap_pin_range(d, gpfn, pin.in.extent_order); + if ( rc ) + goto fail; + + for ( j = 0; j < (1UL << pin.in.extent_order); j++ ) + { + mfn = gmfn_to_mfn(d, gpfn); + if ( __copy_to_guest_offset(pin.in.extent_start, + (i << pin.in.extent_order) + j, + &mfn, 1) ) + { + rc = -EFAULT; + goto fail; + } + } + } + + rc = 0; + + fail: + pin.nr_pinned = i; + if ( __copy_field_to_guest(arg, &pin, nr_pinned) ) + rc = -EFAULT; + + rcu_unlock_domain(d); + return rc; +} + long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg) { struct domain *d; @@ -840,6 +929,10 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg) rc = unpin(guest_handle_cast(arg, xen_unpin_t)); break; + case XENMEM_pin: + rc = pin(guest_handle_cast(arg, xen_pin_t)); + break; + case XENMEM_maximum_ram_page: rc = max_page; break; diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 4accbd4..cbc0b9a 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -511,6 +511,39 @@ struct xen_unpin { typedef struct xen_unpin xen_unpin_t; DEFINE_XEN_GUEST_HANDLE(xen_unpin_t); +/* + * XENMEM_pin pins a set of pages to make sure that the hypervisor does + * not change the p2m mappings for them. + * + */ +#define XENMEM_pin 28 +struct xen_pin { + /* + * [IN/OUT] Details of memory extents to be pinned (GMFN bases). + * Xen copies back the MFNs corresponding to the GMFNs passed in as + * argument. + * @in.address_bits contains the maximum number of bits addressable + * by the caller. If the machine addresses of the pages to be pinned + * are not addressable according to @in.address_bits, the hypercall + * fails and returns an errors. The pages are not pinned. Otherwise + * the hypercall succeeds. + */ + struct xen_memory_reservation in; + + /* + * [OUT] Number of input extents that were successfully pinned. + * 1. The first @nr_pinned input extents were successfully + * pinned. + * 2. All other input extents are untouched. + * 3. If not all input extents are pinned then the return code of this + * command will be non-zero. + */ + xen_ulong_t nr_pinned; +}; +typedef struct xen_pin xen_pin_t; +DEFINE_XEN_GUEST_HANDLE(xen_pin_t); + + #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ #endif /* __XEN_PUBLIC_MEMORY_H__ */ -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |