From patchwork Wed Aug 2 09:59:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 9876527 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 C235F6037D for ; Wed, 2 Aug 2017 10:02:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9E13C287A2 for ; Wed, 2 Aug 2017 10:02:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 92E56287A5; Wed, 2 Aug 2017 10:02:38 +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 EF985287A2 for ; Wed, 2 Aug 2017 10:02:37 +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 1dcqRh-0006zS-St; Wed, 02 Aug 2017 10:00:05 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dcqRg-0006yk-Is for xen-devel@lists.xenproject.org; Wed, 02 Aug 2017 10:00:04 +0000 Received: from [85.158.139.211] by server-15.bemta-5.messagelabs.com id 9C/80-01736-3A2A1895; Wed, 02 Aug 2017 10:00:03 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprMIsWRWlGSWpSXmKPExsXitHSDve7iRY2 RBg9PiVh83zKZyYHR4/CHKywBjFGsmXlJ+RUJrBmbmxawF8xyrug+38LUwPjQvIuRk0NCwF9i 6YVl7CA2m4COxNSnl1i7GDk4RARUJG7vNQAJMwsUS/z9380MYgsLBEjc6r/OBFLCAlSyfnMpS JhXwEZi1fdvrBAT5SV2tV0EszkFbCWmnWlhBikXAqp580EdJCwE0jl1FhtEq6DEyZlPWCA2SU gcfPGCeQIj7ywkqVlIUgsYmVYxqhenFpWlFula6CUVZaZnlOQmZuboGhqY6uWmFhcnpqfmJCY V6yXn525iBAYNAxDsYDzY7HyIUZKDSUmUV7GnPlKILyk/pTIjsTgjvqg0J7X4EKMMB4eSBC/z wsZIIcGi1PTUirTMHGD4wqQlOHiURHh1QdK8xQWJucWZ6RCpU4zGHBtWr//CxPFqwv9vTEIse fl5qVLivG4gpQIgpRmleXCDYHF1iVFWSpiXEeg0IZ6C1KLczBJU+VeM4hyMSsK81SBTeDLzSu D2vQI6hQnolD91YKeUJCKkpBoY5bWNdItYT6/irZG4eKX24sFFlQ/2Ttv1/cvBb4FLmnxKYtQ m3fs4Za8Qc8fj6Tofl0abtijtebtLgPPrSpPdyS1yLpPd+wpnd3CxvujKWvZo3f+IWxenxYr8 dmALmhIqEbf0SqnuuZcvOsqSxd3W8UybM2ndt90lWTpTVDYUzfx6inG/lv9KJyWW4oxEQy3mo uJEAI9x3RSmAgAA X-Env-Sender: prvs=380900d51=Paul.Durrant@citrix.com X-Msg-Ref: server-14.tower-206.messagelabs.com!1501668000!66681652!2 X-Originating-IP: [66.165.176.63] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.25; banners=-,-,- X-VirusChecked: Checked Received: (qmail 2132 invoked from network); 2 Aug 2017 10:00:03 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP; 2 Aug 2017 10:00:03 -0000 X-IronPort-AV: E=Sophos;i="5.41,310,1498521600"; d="scan'208";a="442331783" From: Paul Durrant To: Date: Wed, 2 Aug 2017 10:59:48 +0100 Message-ID: <20170802095949.40677-5-paul.durrant@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170802095949.40677-1-paul.durrant@citrix.com> References: <20170802095949.40677-1-paul.durrant@citrix.com> MIME-Version: 1.0 Cc: Wei Liu , Paul Durrant , Ian Jackson Subject: [Xen-devel] [PATCH 4/5] 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=c5cf2b15f7a448277716a7e96fea1c93df6c17a5 Signed-off-by: Paul Durrant --- Cc: Ian Jackson Cc: Wei Liu --- tools/include/xen-sys/Linux/privcmd.h | 11 ++++++ tools/libs/foreignmemory/core.c | 42 ++++++++++++++++++++ .../libs/foreignmemory/include/xenforeignmemory.h | 39 +++++++++++++++++++ tools/libs/foreignmemory/libxenforeignmemory.map | 5 +++ tools/libs/foreignmemory/linux.c | 45 ++++++++++++++++++++++ tools/libs/foreignmemory/private.h | 30 +++++++++++++++ 6 files changed, 172 insertions(+) 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/core.c b/tools/libs/foreignmemory/core.c index a6897dc561..291ee44516 100644 --- a/tools/libs/foreignmemory/core.c +++ b/tools/libs/foreignmemory/core.c @@ -120,6 +120,48 @@ 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; + + fres = calloc(1, sizeof(*fres)); + if ( !fres ) + 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 ) + goto fail; + + *paddr = fres->addr; + return fres; + +fail: + free(fres); + + return NULL; +} + +void xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ + osdep_xenforeignmemory_unmap_resource(fmem, fres); + + free(fres); +} + /* * Local variables: * mode: C diff --git a/tools/libs/foreignmemory/include/xenforeignmemory.h b/tools/libs/foreignmemory/include/xenforeignmemory.h index f4814c390f..e56eb3c4d4 100644 --- a/tools/libs/foreignmemory/include/xenforeignmemory.h +++ b/tools/libs/foreignmemory/include/xenforeignmemory.h @@ -138,6 +138,45 @@ 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 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 + */ +void 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..4447723cb1 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); } +void osdep_xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ + (void) 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; + 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; + + memset(&mr, 0, sizeof(mr)); + mr.dom = fres->domid; + mr.type = fres->type; + mr.id = fres->id; + mr.idx = fres->frame; + mr.num = fres->nr_frames; + 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; + 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 c5c07cc4c4..2ae9382669 100644 --- a/tools/libs/foreignmemory/private.h +++ b/tools/libs/foreignmemory/private.h @@ -42,6 +42,36 @@ 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; +} + +void osdep_xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres) +{ +} +#else +int osdep_xenforeignmemory_map_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres); +void osdep_xenforeignmemory_unmap_resource( + xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres); +#endif + #define PERROR(_f...) \ xtl_log(fmem->logger, XTL_ERROR, errno, "xenforeignmemory", _f)