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: 8980541 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id F4169BF29F for ; Fri, 29 Apr 2016 12:12:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0E4CB201ED for ; Fri, 29 Apr 2016 12:12:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CFD3C20212 for ; Fri, 29 Apr 2016 12:12:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753472AbcD2MMh (ORCPT ); Fri, 29 Apr 2016 08:12:37 -0400 Received: from e38.co.us.ibm.com ([32.97.110.159]:50172 "EHLO e38.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753465AbcD2MMg (ORCPT ); Fri, 29 Apr 2016 08:12:36 -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 Cc: bjsdjshi@linux.vnet.ibm.com, renxiaof@linux.vnet.ibm.com, cornelia.huck@de.ibm.com, borntraeger@de.ibm.com, agraf@suse.com, alex.williamson@redhat.com Subject: [PATCH RFC 6/8] vfio: ccw: introduce page array interfaces 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 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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; +}