From patchwork Tue Aug 22 14:50:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 9915461 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 9202E603FF for ; Tue, 22 Aug 2017 14:54:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 610BF28617 for ; Tue, 22 Aug 2017 14:54:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 55CF428847; Tue, 22 Aug 2017 14:54:19 +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 BA5F528889 for ; Tue, 22 Aug 2017 14:54:15 +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 1dkAX2-0002R9-K0; Tue, 22 Aug 2017 14:51:52 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dkAX1-0002OA-Qf for xen-devel@lists.xenproject.org; Tue, 22 Aug 2017 14:51:51 +0000 Received: from [193.109.254.147] by server-7.bemta-6.messagelabs.com id F4/7A-03557-7054C995; Tue, 22 Aug 2017 14:51:51 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupjkeJIrShJLcpLzFFi42JxWrohUpfNdU6 kQftDE4vvWyYzOTB6HP5whSWAMYo1My8pvyKBNePSsiMsBXPcK85t6GBuYOy07mLk5JAQ8JdY 1fmMHcRmE9CRmPr0EmsXIweHiICKxO29BiBhZoFiib//u5lBwsICMRK3z/iAhFkEVCU2HDrGC GLzClhLHGw5wAIxUV5iV9tFVhCbU8BG4uGhCSwgrUJANbeuB4KEhYCGr586iw2iVVDi5MwnLB CbJCQOvnjBPIGRdxaS1CwkqQWMTKsYNYpTi8pSi3SNLPWSijLTM0pyEzNzdA0NzPRyU4uLE9N TcxKTivWS83M3MQLDhgEIdjAeWBR4iFGSg0lJlHfy99mRQnxJ+SmVGYnFGfFFpTmpxYcYZTg4 lCR4pZ3nRAoJFqWmp1akZeYAAxgmLcHBoyTCGwqS5i0uSMwtzkyHSJ1i1OXYsHr9FyYhlrz8v FQpcd43IEUCIEUZpXlwI2DRdIlRVkqYlxHoKCGegtSi3MwSVPlXjOIcjErCvAUgU3gy80rgNr 0COoIJ6AjD1mkgR5QkIqSkGhi5yz9vmSZewuzTfPR4a6uIxQNe74sXeycc6esJXP2b/2LcJD2 nCSc39gtsZ90/TVSb+8bFz3t/fcoRO7zM0/hs6cnUL4t+NUzQ9HXsW6/74+unaVcKtDcYrW3Y 9+otv2OkwaEDB8/4rv+jZfR11SOP2/lr2QSmcdlM3DBPbHPMBMUObzGl03MjlFiKMxINtZiLi hMBxffSzqECAAA= X-Env-Sender: prvs=40066d99f=Paul.Durrant@citrix.com X-Msg-Ref: server-10.tower-27.messagelabs.com!1503413508!89722321!2 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 14983 invoked from network); 22 Aug 2017 14:51:50 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-10.tower-27.messagelabs.com with RC4-SHA encrypted SMTP; 22 Aug 2017 14:51:50 -0000 X-IronPort-AV: E=Sophos;i="5.41,412,1498521600"; d="scan'208";a="436412965" From: Paul Durrant To: Date: Tue, 22 Aug 2017 15:50:58 +0100 Message-ID: <20170822145107.6877-5-paul.durrant@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170822145107.6877-1-paul.durrant@citrix.com> References: <20170822145107.6877-1-paul.durrant@citrix.com> MIME-Version: 1.0 Cc: Wei Liu , Paul Durrant , Ian Jackson Subject: [Xen-devel] [PATCH v2 REPOST 04/12] 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 --- Cc: Ian Jackson Cc: Wei Liu 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 | 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 +++++++++++++++ 7 files changed, 173 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 b110076621..7eb59c78cb 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 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)