[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v15 08/11] tools/libxenforeignmemory: add support for resource mapping
A previous patch introduced a new HYPERVISOR_memory_op to acquire guest resources for direct priv-mapping. This patch adds new functionality into libxenforeignmemory to make use of a new privcmd ioctl [1] that uses the new memory op to make such resources available via mmap(2). [1] http://xenbits.xen.org/gitweb/?p=people/pauldu/linux.git;a=commit;h=ce59a05e6712 Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> Reviewed-by: Wei Liu <wei.liu2@xxxxxxxxxx> --- Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> v4: - Fixed errno and removed single-use label - The unmap call now returns a status - Use C99 initialization for ioctl struct v2: - Bump minor version up to 3. --- tools/include/xen-sys/Linux/privcmd.h | 11 +++++ tools/libs/foreignmemory/Makefile | 2 +- tools/libs/foreignmemory/core.c | 53 ++++++++++++++++++++++ .../libs/foreignmemory/include/xenforeignmemory.h | 41 +++++++++++++++++ tools/libs/foreignmemory/libxenforeignmemory.map | 5 ++ tools/libs/foreignmemory/linux.c | 45 ++++++++++++++++++ tools/libs/foreignmemory/private.h | 31 +++++++++++++ 7 files changed, 187 insertions(+), 1 deletion(-) diff --git a/tools/include/xen-sys/Linux/privcmd.h b/tools/include/xen-sys/Linux/privcmd.h index 732ff7c15a..9531b728f9 100644 --- a/tools/include/xen-sys/Linux/privcmd.h +++ b/tools/include/xen-sys/Linux/privcmd.h @@ -86,6 +86,15 @@ typedef struct privcmd_dm_op { const privcmd_dm_op_buf_t __user *ubufs; } privcmd_dm_op_t; +typedef struct privcmd_mmap_resource { + domid_t dom; + __u32 type; + __u32 id; + __u32 idx; + __u64 num; + __u64 addr; +} privcmd_mmap_resource_t; + /* * @cmd: IOCTL_PRIVCMD_HYPERCALL * @arg: &privcmd_hypercall_t @@ -103,5 +112,7 @@ typedef struct privcmd_dm_op { _IOC(_IOC_NONE, 'P', 5, sizeof(privcmd_dm_op_t)) #define IOCTL_PRIVCMD_RESTRICT \ _IOC(_IOC_NONE, 'P', 6, sizeof(domid_t)) +#define IOCTL_PRIVCMD_MMAP_RESOURCE \ + _IOC(_IOC_NONE, 'P', 7, sizeof(privcmd_mmap_resource_t)) #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ diff --git a/tools/libs/foreignmemory/Makefile b/tools/libs/foreignmemory/Makefile index cbe815fce8..ee5c3fd67e 100644 --- a/tools/libs/foreignmemory/Makefile +++ b/tools/libs/foreignmemory/Makefile @@ -2,7 +2,7 @@ XEN_ROOT = $(CURDIR)/../../.. include $(XEN_ROOT)/tools/Rules.mk MAJOR = 1 -MINOR = 2 +MINOR = 3 SHLIB_LDFLAGS += -Wl,--version-script=libxenforeignmemory.map CFLAGS += -Werror -Wmissing-prototypes diff --git a/tools/libs/foreignmemory/core.c b/tools/libs/foreignmemory/core.c index 7c8562ae74..63f12e2450 100644 --- a/tools/libs/foreignmemory/core.c +++ b/tools/libs/foreignmemory/core.c @@ -17,6 +17,8 @@ #include <assert.h> #include <errno.h> +#include <sys/mman.h> + #include "private.h" static int all_restrict_cb(Xentoolcore__Active_Handle *ah, domid_t domid) { @@ -135,6 +137,57 @@ int xenforeignmemory_restrict(xenforeignmemory_handle *fmem, return osdep_xenforeignmemory_restrict(fmem, domid); } +xenforeignmemory_resource_handle *xenforeignmemory_map_resource( + xenforeignmemory_handle *fmem, domid_t domid, unsigned int type, + unsigned int id, unsigned long frame, unsigned long nr_frames, + void **paddr, int prot, int flags) +{ + xenforeignmemory_resource_handle *fres; + int rc; + + /* Check flags only contains POSIX defined values */ + if ( flags & ~(MAP_SHARED | MAP_PRIVATE) ) + { + errno = EINVAL; + return NULL; + } + + fres = calloc(1, sizeof(*fres)); + if ( !fres ) + { + errno = ENOMEM; + return NULL; + } + + fres->domid = domid; + fres->type = type; + fres->id = id; + fres->frame = frame; + fres->nr_frames = nr_frames; + fres->addr = *paddr; + fres->prot = prot; + fres->flags = flags; + + rc = osdep_xenforeignmemory_map_resource(fmem, fres); + if ( rc ) + { + free(fres); + fres = NULL; + } else + *paddr = fres->addr; + + return fres; +} + +int xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ + int rc = osdep_xenforeignmemory_unmap_resource(fmem, fres); + + free(fres); + return rc; +} + /* * Local variables: * mode: C diff --git a/tools/libs/foreignmemory/include/xenforeignmemory.h b/tools/libs/foreignmemory/include/xenforeignmemory.h index f4814c390f..d594be8df0 100644 --- a/tools/libs/foreignmemory/include/xenforeignmemory.h +++ b/tools/libs/foreignmemory/include/xenforeignmemory.h @@ -138,6 +138,47 @@ int xenforeignmemory_unmap(xenforeignmemory_handle *fmem, int xenforeignmemory_restrict(xenforeignmemory_handle *fmem, domid_t domid); +typedef struct xenforeignmemory_resource_handle xenforeignmemory_resource_handle; + +/** + * This function maps a guest resource. + * + * @parm fmem handle to the open foreignmemory interface + * @parm domid the domain id + * @parm type the resource type + * @parm id the type-specific resource identifier + * @parm frame base frame index within the resource + * @parm nr_frames number of frames to map + * @parm paddr pointer to an address passed through to mmap(2) + * @parm prot passed through to mmap(2) + * @parm POSIX-only flags passed through to mmap(2) + * @return pointer to foreignmemory resource handle on success, NULL on + * failure + * + * *paddr is used, on entry, as a hint address for foreign map placement + * (see mmap(2)) so should be set to NULL if no specific placement is + * required. On return *paddr contains the address where the resource is + * mapped. + * As for xenforeignmemory_map2() flags is a set of additional flags + * for mmap(2). Not all of the flag combinations are possible due to + * implementation details on different platforms. + */ +xenforeignmemory_resource_handle *xenforeignmemory_map_resource( + xenforeignmemory_handle *fmem, domid_t domid, unsigned int type, + unsigned int id, unsigned long frame, unsigned long nr_frames, + void **paddr, int prot, int flags); + +/** + * This function releases a previously acquired resource. + * + * @parm fmem handle to the open foreignmemory interface + * @parm fres handle to the acquired resource + * + * Returns 0 on success on failure sets errno and returns -1. + */ +int xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres); + #endif /* diff --git a/tools/libs/foreignmemory/libxenforeignmemory.map b/tools/libs/foreignmemory/libxenforeignmemory.map index 716ecaf15c..d5323c87d9 100644 --- a/tools/libs/foreignmemory/libxenforeignmemory.map +++ b/tools/libs/foreignmemory/libxenforeignmemory.map @@ -14,3 +14,8 @@ VERS_1.2 { global: xenforeignmemory_map2; } VERS_1.1; +VERS_1.3 { + global: + xenforeignmemory_map_resource; + xenforeignmemory_unmap_resource; +} VERS_1.2; diff --git a/tools/libs/foreignmemory/linux.c b/tools/libs/foreignmemory/linux.c index 374e45aed5..a6b41b0b7f 100644 --- a/tools/libs/foreignmemory/linux.c +++ b/tools/libs/foreignmemory/linux.c @@ -277,6 +277,51 @@ int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem, return ioctl(fmem->fd, IOCTL_PRIVCMD_RESTRICT, &domid); } +int osdep_xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ + return munmap(fres->addr, fres->nr_frames << PAGE_SHIFT); +} + +int osdep_xenforeignmemory_map_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ + privcmd_mmap_resource_t mr = { + .dom = fres->domid, + .type = fres->type, + .id = fres->id, + .idx = fres->frame, + .num = fres->nr_frames, + }; + int rc; + + fres->addr = mmap(fres->addr, fres->nr_frames << PAGE_SHIFT, + fres->prot, fres->flags | MAP_SHARED, fmem->fd, 0); + if ( fres->addr == MAP_FAILED ) + return -1; + + mr.addr = (uintptr_t)fres->addr; + + rc = ioctl(fmem->fd, IOCTL_PRIVCMD_MMAP_RESOURCE, &mr); + if ( rc ) + { + int saved_errno; + + if ( errno != ENOTTY ) + PERROR("ioctl failed"); + else + errno = EOPNOTSUPP; + + saved_errno = errno; + (void)osdep_xenforeignmemory_unmap_resource(fmem, fres); + errno = saved_errno; + + return -1; + } + + return 0; +} + /* * Local variables: * mode: C diff --git a/tools/libs/foreignmemory/private.h b/tools/libs/foreignmemory/private.h index 2470f3c46c..b191000b49 100644 --- a/tools/libs/foreignmemory/private.h +++ b/tools/libs/foreignmemory/private.h @@ -45,6 +45,37 @@ void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom, xen_pfn_t *arr, int num); #endif +struct xenforeignmemory_resource_handle { + domid_t domid; + unsigned int type; + unsigned int id; + unsigned long frame; + unsigned long nr_frames; + void *addr; + int prot; + int flags; +}; + +#ifndef __linux__ +static inline int osdep_xenforeignmemory_map_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ + errno = EOPNOTSUPP; + return -1; +} + +static inline int osdep_xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ + return 0; +} +#else +int osdep_xenforeignmemory_map_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres); +int osdep_xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres); +#endif + #define PERROR(_f...) \ xtl_log(fmem->logger, XTL_ERROR, errno, "xenforeignmemory", _f) -- 2.11.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |