From patchwork Tue Sep 5 11:37:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 9938487 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 3676D6038C for ; Tue, 5 Sep 2017 11:40:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 270E128938 for ; Tue, 5 Sep 2017 11:40:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1AE4E28948; Tue, 5 Sep 2017 11:40: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 6871328938 for ; Tue, 5 Sep 2017 11:40:03 +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 1dpCAW-0007OB-Lr; Tue, 05 Sep 2017 11:37:24 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dpCAV-0007NE-2X for xen-devel@lists.xenproject.org; Tue, 05 Sep 2017 11:37:23 +0000 Received: from [193.109.254.147] by server-11.bemta-6.messagelabs.com id A6/0C-03616-27C8EA95; Tue, 05 Sep 2017 11:37:22 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrHIsWRWlGSWpSXmKPExsXitHRDpG5hz7p Ig637TSy+b5nM5MDocfjDFZYAxijWzLyk/IoE1oz5f8+xF5z3qdi9bh9TA+M3uy5GTg4JAX+J p4+nsILYbAI6ElOfXgKyOThEBFQkbu81AAkzCxRL/P3fzQxiCwuESqzfvhPMZgEqeddwlR3E5 hWwljh/5xoLxEh5iV1tF8FGcgrYSDy/ewisRgio5s+ht0wQ9YISJ2c+YYGYrynRuv03O4QtL9 G8dTYzRL2KxPqps9gmMPLNQtIyC0nLLCQtCxiZVzFqFKcWlaUW6Rpa6CUVZaZnlOQmZuboGhq Y6eWmFhcnpqfmJCYV6yXn525iBIYaAxDsYLy5MeAQoyQHk5Iob2jiukghvqT8lMqMxOKM+KLS nNTiQ4wyHBxKEryzuoBygkWp6akVaZk5wKCHSUtw8CiJ8LqCpHmLCxJzizPTIVKnGI051l1a9 4WJY8Pq9V+YhFjy8vNSpcR5t4GUCoCUZpTmwQ2CReMlRlkpYV5GoNOEeApSi3IzS1DlXzGKcz AqCfNKdwNN4cnMK4Hb9wroFCagU6pergE5pSQRISXVwGja3/vsL4O8/3UZWwbGkL+KC9t+TFP KPCx2yT5Q5OtN2diZwmnzen9lZ09gfLp40ZXtTIr2vbMMdotef6Pu7N50z4FVZOlJsfnvSnas E+BTjtnnx21/bvuCr+nmx+PZPIq/Nl4X2xOT9LV+wfeQ/qsNq33U3/yt+dR14uMTz49rZ1648 kO/i1+JpTgj0VCLuag4EQAcvvX+wQIAAA== X-Env-Sender: prvs=414c423db=Paul.Durrant@citrix.com X-Msg-Ref: server-5.tower-27.messagelabs.com!1504611439!109691739!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 31149 invoked from network); 5 Sep 2017 11:37:21 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-5.tower-27.messagelabs.com with RC4-SHA encrypted SMTP; 5 Sep 2017 11:37:21 -0000 X-IronPort-AV: E=Sophos;i="5.41,480,1498521600"; d="scan'208";a="438388726" From: Paul Durrant To: Date: Tue, 5 Sep 2017 12:37:07 +0100 Message-ID: <20170905113716.3960-4-paul.durrant@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170905113716.3960-1-paul.durrant@citrix.com> References: <20170905113716.3960-1-paul.durrant@citrix.com> MIME-Version: 1.0 Cc: Wei Liu , Paul Durrant , Ian Jackson Subject: [Xen-devel] [PATCH v4 03/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 Reviewed-by: Roger Pau Monné Reviewed-by: Wei Liu --- Cc: Ian Jackson Cc: Wei Liu 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 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..8d3f9f178f 100644 --- a/tools/libs/foreignmemory/core.c +++ b/tools/libs/foreignmemory/core.c @@ -17,6 +17,8 @@ #include #include +#include + #include "private.h" xenforeignmemory_handle *xenforeignmemory_open(xentoollog_logger *logger, @@ -120,6 +122,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 c5c07cc4c4..80b22bdbfc 100644 --- a/tools/libs/foreignmemory/private.h +++ b/tools/libs/foreignmemory/private.h @@ -42,6 +42,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)