From patchwork Mon Oct 30 17:48:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10032985 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1754E603B4 for ; Mon, 30 Oct 2017 17:51:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0BF102892C for ; Mon, 30 Oct 2017 17:51:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 00FF828926; Mon, 30 Oct 2017 17:51:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1CDEF2892C for ; Mon, 30 Oct 2017 17:51:04 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1e9EAy-0006od-HC; Mon, 30 Oct 2017 17:48:40 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1e9EAw-0006mr-Ks for xen-devel@lists.xenproject.org; Mon, 30 Oct 2017 17:48:38 +0000 Received: from [85.158.139.211] by server-15.bemta-5.messagelabs.com id 98/9D-23912-5F567F95; Mon, 30 Oct 2017 17:48:37 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrJIsWRWlGSWpSXmKPExsXitHRDpO7X1O+ RBk0vxCy+b5nM5MDocfjDFZYAxijWzLyk/IoE1ozlfSfYC275VMz9cY+5gfGvXRcjJ4eEgL/E nmMnmUBsNgEdialPL7F2MXJwiAioSNzeawASZhYIkZh4cgIriC0sECbRtnI6M0gJi4CqxJ/Pz iBhXgFriZlPmhkhJspL7Gq7CFbOKWAjsa7jHzOILQRUc/JmNyNEvaDEyZlPWCDGa0q0bv/NDm HLSzRvnQ1VryKxfuostgmMfLOQtMxC0jILScsCRuZVjBrFqUVlqUW6RqZ6SUWZ6RkluYmZObq GBqZ6uanFxYnpqTmJScV6yfm5mxiBgVbPwMC4g3FXu98hRkkOJiVR3p2O3yOF+JLyUyozEosz 4otKc1KLDzHKcHAoSfC6AgNXSLAoNT21Ii0zBxjyMGkJDh4lEd6yFKA0b3FBYm5xZjpE6hSjP ce6W5f+MHEc23QZSHbcvAskn8183cAsxJKXn5cqJc6rBjJVAKQtozQPbigsRi8xykoJ8zIyMD AI8RSkFuVmlqDKv2IU52BUEuYNAZnCk5lXArf7FdBZTEBnaUh+ATmrJBEhJdXA6P89PvNjjNS BbenHXe7z21/jXSvbbfr40LYJcht7Ug68CRBbfb7ESzyE/dWLU3rLM3fKn0s4Y5H9tf29JVeJ meS0jVUH1i/ccyVhHpPj//fSu+x0z5eWhG5+5mHHXPGa/cVkWc3tfL+1sjusVMTM2bxfxC1x2 fM6iOFNbSKbydtkUeEnV878U2Ipzkg01GIuKk4EAKjuR8vMAgAA X-Env-Sender: prvs=469f563c5=Paul.Durrant@citrix.com X-Msg-Ref: server-9.tower-206.messagelabs.com!1509385712!109444241!4 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 5712 invoked from network); 30 Oct 2017 17:48:37 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-9.tower-206.messagelabs.com with RC4-SHA encrypted SMTP; 30 Oct 2017 17:48:37 -0000 X-IronPort-AV: E=Sophos;i="5.44,320,1505779200"; d="scan'208";a="449051816" From: Paul Durrant To: Date: Mon, 30 Oct 2017 17:48:26 +0000 Message-ID: <20171030174829.4518-9-paul.durrant@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171030174829.4518-1-paul.durrant@citrix.com> References: <20171030174829.4518-1-paul.durrant@citrix.com> MIME-Version: 1.0 Cc: Paul Durrant , Ian Jackson Subject: [Xen-devel] [PATCH v13 08/11] tools/libxenforeignmemory: add support for resource mapping X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Roger Pau Monné Reviewed-by: Wei Liu --- Cc: Ian Jackson 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 79b24d273b..efa915015c 100644 --- a/tools/libs/foreignmemory/core.c +++ b/tools/libs/foreignmemory/core.c @@ -17,6 +17,8 @@ #include #include +#include + #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)