From patchwork Mon Mar 6 11:34:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 9606091 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 7C7C56046A for ; Mon, 6 Mar 2017 13:45:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6B6E02723E for ; Mon, 6 Mar 2017 13:45:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5FB172841D; Mon, 6 Mar 2017 13:45:47 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0B7392723E for ; Mon, 6 Mar 2017 13:45:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=eSsFPdQp2Os/woHLbJA9oQiikquefHli9cx+DAl6ONA=; b=ChxcHOCax6uJVrskQKPa91POM9 Xjg3tbHiHHIicp9Ptbfb3kr1jDXQ8+DtdsG7XyhxdPDE4j3dNKzRVpTn9ZX5LhuU3A1AcQPHqYoA0 2+hTVaNYphIGj5eFhL0CH5iMbi5ve56/QgbH8N9zl90EqTfwdZ6Xwi4UP6Eop5Mv5dtxnt9dh2cmI EqW+tmTHQWE05wTN1OSvMwiWN2oo38/6S75z7US2uxGwWoML6Dlff3dPN+vpQf7NM6uMgxI5mWy7P 07Aw3QuRt25W2MOvrG+yw0xre/KQ1yA9GfPSPd+9SElWiuNDDwWYmyjMfAKvXYAlYHU6O+TH6QIbv ZmuAUKbw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cksxK-0008Rx-V9; Mon, 06 Mar 2017 13:45:43 +0000 Received: from merlin.infradead.org ([2001:4978:20e::2]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cksvl-0006Ab-Nz for linux-arm-kernel@bombadil.infradead.org; Mon, 06 Mar 2017 13:44:05 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=nV9yPsSKYkmXtZPJH6BSsapAhM+PGjVhcmnGx7kkPFA=; b=dbMwvA5BLCHXEOIhi1qwA1Vcv fbQUv6HBZao2uh2M+EAhYLRXMKCn29+WYbcHhi9VhKUwX/ZF0EYDLV+5sLFkZUnnTV9kAuPEactFF WbigtV0kxb/+iE7Q0HFEqsoJXlSMiU0fyqo1gh86OUivQ0hj5/jt2EP40l28aT5cg/6b+i4YASMbG 2dOd8Q7ZsDAs0FCJ5M+KQIt/Xy4zRDoHsL3GNPrlFu+HDJ1AVUrtcTYQJxDl0x7n62iQcbH01yCq8 bgQkFkoPCetYynp7Je8NwjEGvD96ZuuGpaW3EHmNnwxJ/DOLMdbpkMGQF1MFu3PSlfB9sqnjFzo65 LOHNQxRMQ==; Received: from mx1.redhat.com ([209.132.183.28]) by merlin.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1ckqw3-0005F5-VR for linux-arm-kernel@lists.infradead.org; Mon, 06 Mar 2017 11:36:16 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B930F83F47; Mon, 6 Mar 2017 11:35:39 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-100.ams2.redhat.com [10.36.116.100]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v26BYbnd002618; Mon, 6 Mar 2017 06:35:36 -0500 From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, marc.zyngier@arm.com, christoffer.dall@linaro.org, vijayak@caviumnetworks.com, Vijaya.Kumar@cavium.com, peter.maydell@linaro.org, linux-arm-kernel@lists.infradead.org, drjones@redhat.com, kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Subject: [PATCH v3 14/19] KVM: arm64: ITS: Add infrastructure for table lookup Date: Mon, 6 Mar 2017 12:34:29 +0100 Message-Id: <1488800074-21991-15-git-send-email-eric.auger@redhat.com> In-Reply-To: <1488800074-21991-1-git-send-email-eric.auger@redhat.com> References: <1488800074-21991-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 06 Mar 2017 11:35:39 +0000 (UTC) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170306_063616_186599_E367BC34 X-CRM114-Status: GOOD ( 20.74 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andre.przywara@arm.com, pbonzini@redhat.com, dgilbert@redhat.com, quintela@redhat.com, Prasun.Kapoor@cavium.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Add a generic lookup_table() helper whose role consists in scanning a contiguous table located in guest RAM and applying a callback on each entry. Entries can be handled as linked lists since the callback may return an offset to the next entry and also tell that an entry is the last one. Helper functions also are added to compute the device/event ID offset to the next DTE/ITE. Signed-off-by: Eric Auger --- virt/kvm/arm/vgic/vgic-its.c | 119 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 1cd6ae6..cf04776 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -181,6 +181,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id, #define VITS_ESZ 8 #define VITS_TYPER_IDBITS 0xF #define VITS_TYPER_DEVBITS 0xF +#define VITS_DTE_MAX_DEVID_OFFSET GENMASK(19, 0) +#define VITS_ITE_MAX_EVENTID_OFFSET GENMASK(16, 0) /* * Finds and returns a collection in the ITS collection table. @@ -1607,6 +1609,123 @@ int vgic_its_attr_regs_access(struct kvm_device *dev, return 0; } +static u32 compute_next_devid_offset(struct list_head *h, + struct its_device *dev) +{ + struct list_head *e = &dev->dev_list; + struct its_device *next; + u32 next_offset; + + if (e->next == h) + return 0; + next = list_entry(e->next, struct its_device, dev_list); + next_offset = next->device_id - dev->device_id; + + return next_offset < VITS_DTE_MAX_DEVID_OFFSET ? + next_offset : VITS_DTE_MAX_DEVID_OFFSET; +} + +static u32 compute_next_eventid_offset(struct list_head *h, + struct its_ite *ite) +{ + struct list_head *e = &ite->ite_list; + struct its_ite *next; + u32 next_offset; + + if (e->next == h) + return 0; + next = list_entry(e->next, struct its_ite, ite_list); + next_offset = next->event_id - ite->event_id; + + return next_offset < VITS_ITE_MAX_EVENTID_OFFSET ? + next_offset : VITS_ITE_MAX_EVENTID_OFFSET; +} + +static int next_segment(unsigned long len, int offset) +{ + if (len > PAGE_SIZE - offset) + return PAGE_SIZE - offset; + else + return len; +} + +/** + * entry_fn_t - Callback called on a table entry restore path + * @its: its handle + * @id: id of the entry + * @addr: kernel VA of the entry + * @opaque: pointer to an opaque data + * @next_offset: minimal ID offset to the next entry. 0 if this + * entry is the last one, 1 if the entry is invalid, >= 1 if an + * entry's next_offset field was truly decoded + * + * Return: < 0 on error, 0 otherwise + */ +typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr, + void *opaque, u32 *next_offset); + +/** + * lookup_table - scans a contiguous table in guest RAM and applies a function + * to each entry + * + * @its: its handle + * @base: base gpa of the table + * @size: size of the table in bytes + * @esz: entry size in bytes + * @start_id: first entry's ID + * @fn: function to apply on each entry + * + * Return: < 0 on error, 1 if last element identified, 0 otherwise + */ +static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz, + int start_id, entry_fn_t fn, void *opaque) +{ + gpa_t gpa = base, top = base + size - 1; + unsigned long len = top - gpa; + int ret, seg, offset = offset_in_page(gpa); + gfn_t gfn = gpa >> PAGE_SHIFT; + u32 id = start_id + (gpa - base)/esz; + struct kvm *kvm = its->dev->kvm; + kvm_pfn_t pfn; + + while ((seg = next_segment(len, offset)) != 0) { + u32 next_offset; + bool writeable; + void *addr; + + pfn = gfn_to_pfn_prot(kvm, gfn, true, &writeable); + if (is_error_noslot_pfn(pfn)) + return -EINVAL; + addr = phys_to_virt((u64)pfn << PAGE_SHIFT); + addr += offset; + + while (seg > 0) { + size_t byte_offset; + + ret = fn(its, id, addr, opaque, &next_offset); + if (ret < 0 || (!ret && !next_offset)) + goto out; + + byte_offset = next_offset * esz; + + id += next_offset; + gpa += byte_offset; + addr += byte_offset; + seg -= byte_offset; + } + kvm_release_pfn_clean(pfn); + + len = top - gpa; + offset = offset_in_page(gpa); + gfn = gpa >> PAGE_SHIFT; + id = start_id + (gpa - base)/esz; + } + return 0; +out: + kvm_release_pfn_clean(pfn); + return (ret < 0 ? ret : 1); +} + /** * vgic_its_flush_pending_tables - Flush the pending tables into guest RAM */