From patchwork Fri Apr 29 12:11:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dong Jia Shi X-Patchwork-Id: 616780 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3qxFKk0CLLz9t3k for ; Fri, 29 Apr 2016 23:44:10 +1000 (AEST) Received: from localhost ([::1]:54547 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aw8iD-000760-0L for incoming@patchwork.ozlabs.org; Fri, 29 Apr 2016 09:44:05 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40041) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aw7IT-0001y7-1f for qemu-devel@nongnu.org; Fri, 29 Apr 2016 08:13:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aw7IG-00039U-OL for qemu-devel@nongnu.org; Fri, 29 Apr 2016 08:13:19 -0400 Received: from e38.co.us.ibm.com ([32.97.110.159]:40026) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aw7IG-0002zj-HU for qemu-devel@nongnu.org; Fri, 29 Apr 2016 08:13:12 -0400 Received: from localhost by e38.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 29 Apr 2016 06:12:35 -0600 Received: from d03dlp03.boulder.ibm.com (9.17.202.179) by e38.co.us.ibm.com (192.168.1.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 29 Apr 2016 06:12:21 -0600 X-IBM-Helo: d03dlp03.boulder.ibm.com X-IBM-MailFrom: bjsdjshi@linux.vnet.ibm.com X-IBM-RcptTo: qemu-devel@nongnu.org; alex.williamson@redhat.com; agraf@suse.com; kvm@vger.kernel.org; linux-s390@vger.kernel.org Received: from b01cxnp23032.gho.pok.ibm.com (b01cxnp23032.gho.pok.ibm.com [9.57.198.27]) by d03dlp03.boulder.ibm.com (Postfix) with ESMTP id 05C6D19D804A; Fri, 29 Apr 2016 06:12:04 -0600 (MDT) Received: from b01ledav001.gho.pok.ibm.com (b01ledav001.gho.pok.ibm.com [9.57.199.106]) by b01cxnp23032.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u3TCC6MJ32309290; Fri, 29 Apr 2016 12:12:19 GMT Received: from b01ledav001.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 75A502803A; Fri, 29 Apr 2016 08:12:17 -0400 (EDT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by b01ledav001.gho.pok.ibm.com (Postfix) with ESMTP id 6511B2803D; Fri, 29 Apr 2016 08:12:16 -0400 (EDT) From: Dong Jia Shi To: kvm@vger.kernel.org, linux-s390@vger.kernel.org, qemu-devel@nongnu.org Date: Fri, 29 Apr 2016 14:11:53 +0200 Message-Id: <1461931915-22397-7-git-send-email-bjsdjshi@linux.vnet.ibm.com> X-Mailer: git-send-email 2.6.6 In-Reply-To: <1461931915-22397-1-git-send-email-bjsdjshi@linux.vnet.ibm.com> References: <1461931915-22397-1-git-send-email-bjsdjshi@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16042912-0029-0000-0000-0000271F1E60 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 32.97.110.159 X-Mailman-Approved-At: Fri, 29 Apr 2016 09:31:35 -0400 Subject: [Qemu-devel] [PATCH RFC 6/8] vfio: ccw: introduce page array interfaces X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: borntraeger@de.ibm.com, alex.williamson@redhat.com, renxiaof@linux.vnet.ibm.com, cornelia.huck@de.ibm.com, bjsdjshi@linux.vnet.ibm.com, agraf@suse.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" CCW translation requires to pin/unpin sets of mem pages frequently. Currently we have a lack of support to do this in an efficient way. So we introduce page_array data structure and helper functions to handle pin/unpin operations here. Signed-off-by: Dong Jia Shi --- drivers/vfio/ccw/Makefile | 2 +- drivers/vfio/ccw/ccwchain.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 drivers/vfio/ccw/ccwchain.c diff --git a/drivers/vfio/ccw/Makefile b/drivers/vfio/ccw/Makefile index ea14ca9..ac62330 100644 --- a/drivers/vfio/ccw/Makefile +++ b/drivers/vfio/ccw/Makefile @@ -1,2 +1,2 @@ -vfio-ccw-y := vfio_ccw.o +vfio-ccw-y := vfio_ccw.o ccwchain.o obj-$(CONFIG_VFIO_CCW) += vfio-ccw.o diff --git a/drivers/vfio/ccw/ccwchain.c b/drivers/vfio/ccw/ccwchain.c new file mode 100644 index 0000000..03b4e82 --- /dev/null +++ b/drivers/vfio/ccw/ccwchain.c @@ -0,0 +1,128 @@ +/* + * ccwchain interfaces + * + * Copyright IBM Corp. 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + * Author(s): Dong Jia Shi + * Xiao Feng Ren + */ + +#include +#include + +struct page_array { + u64 hva; + int nr; + struct page **items; +}; + +struct page_arrays { + struct page_array *parray; + int nr; +}; + +/* + * Helpers to operate page_array. + */ +/* + * page_array_pin() - pin user pages in memory + * @p: page_array on which to perform the operation + * + * Attempt to pin user pages in memory. + * + * Usage of page_array: + * @p->hva starting user address. Assigned by caller. + * @p->nr number of pages from @p->hva to pin. Assigned by caller. + * number of pages pinned. Assigned by callee. + * @p->items array that receives pointers to the pages pinned. Allocated by + * caller. + * + * Returns: + * Number of pages pinned on success. If @p->nr is 0 or negative, returns 0. + * If no pages were pinned, returns -errno. + */ +static int page_array_pin(struct page_array *p) +{ + int i, nr; + + nr = get_user_pages_fast(p->hva, p->nr, 1, p->items); + if (nr <= 0) { + p->nr = 0; + return nr; + } else if (nr != p->nr) { + for (i = 0; i < nr; i++) + put_page(p->items[i]); + p->nr = 0; + return -ENOMEM; + } + + return nr; +} + +/* Unpin the items before releasing the memory. */ +static void page_array_items_unpin_free(struct page_array *p) +{ + int i; + + for (i = 0; i < p->nr; i++) + put_page(p->items[i]); + + p->nr = 0; + kfree(p->items); +} + +/* Alloc memory for items, then pin pages with them. */ +static int page_array_items_alloc_pin(u64 hva, + unsigned int len, + struct page_array *p) +{ + int ret; + + if (!len || p->nr) + return -EINVAL; + + p->hva = hva; + + p->nr = ((hva & ~PAGE_MASK) + len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if (!p->nr) + return -EINVAL; + + p->items = kcalloc(p->nr, sizeof(*p->items), GFP_KERNEL); + if (!p->items) + return -ENOMEM; + + ret = page_array_pin(p); + if (ret <= 0) + kfree(p->items); + + return ret; +} + +static int page_arrays_init(struct page_arrays *ps, int nr) +{ + ps->parray = kcalloc(nr, sizeof(*ps->parray), GFP_KERNEL); + if (!ps->parray) { + ps->nr = 0; + return -ENOMEM; + } + + ps->nr = nr; + return 0; +} + +static void page_arrays_unpin_free(struct page_arrays *ps) +{ + int i; + + for (i = 0; i < ps->nr; i++) + page_array_items_unpin_free(ps->parray + i); + + kfree(ps->parray); + + ps->parray = NULL; + ps->nr = 0; +}