From patchwork Fri Mar 12 17:31:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 12135547 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16B16C433E6 for ; Fri, 12 Mar 2021 17:33:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DECBA64FB3 for ; Fri, 12 Mar 2021 17:33:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231557AbhCLRch (ORCPT ); Fri, 12 Mar 2021 12:32:37 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:55266 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231928AbhCLRcU (ORCPT ); Fri, 12 Mar 2021 12:32:20 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1615570340; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=C7rQ5JvwHZU2XBncrE7tSoBDfZg7trh611M/+N48Z8Y=; b=jLN3GtK82Xx9Fcg8m9RpQVHYpdzMYmDdnInp97I7FAqkv1UJwwZLhMwuGc8Gk7xMrIpOJ6 ReMxA47oeW9tWJJ/ndzg88wyOnIunz1mWPV5i+3QyBmuOp6wV8Zz/NBm7gdCe9DZTSOg/y 6q5z9XnTEl0xo/CRrM2wHyQ4qw2bnm4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-506-SS01kqT_PZqmkhf2MiCfgA-1; Fri, 12 Mar 2021 12:32:18 -0500 X-MC-Unique: SS01kqT_PZqmkhf2MiCfgA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E8B1493920; Fri, 12 Mar 2021 17:32:16 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-254.ams2.redhat.com [10.36.112.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id BF2EF1002388; Fri, 12 Mar 2021 17:32:13 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com Cc: james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, shuah@kernel.org, pbonzini@redhat.com Subject: [PATCH v3 1/8] KVM: arm64: vgic-v3: Fix some error codes when setting RDIST base Date: Fri, 12 Mar 2021 18:31:55 +0100 Message-Id: <20210312173202.89576-2-eric.auger@redhat.com> In-Reply-To: <20210312173202.89576-1-eric.auger@redhat.com> References: <20210312173202.89576-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org KVM_DEV_ARM_VGIC_GRP_ADDR group doc says we should return -EEXIST in case the base address of the redist is already set. We currently return -EINVAL. However we need to return -EINVAL in case a legacy REDIST address is attempted to be set while REDIST_REGIONS were set. This case is discriminated by looking at the count field. Signed-off-by: Eric Auger --- v1 -> v2: - simplify the check sequence --- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index 15a6c98ee92f..013b737b658f 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -791,10 +791,6 @@ static int vgic_v3_insert_redist_region(struct kvm *kvm, uint32_t index, size_t size = count * KVM_VGIC_V3_REDIST_SIZE; int ret; - /* single rdist region already set ?*/ - if (!count && !list_empty(rd_regions)) - return -EINVAL; - /* cross the end of memory ? */ if (base + size < base) return -EINVAL; @@ -805,11 +801,14 @@ static int vgic_v3_insert_redist_region(struct kvm *kvm, uint32_t index, } else { rdreg = list_last_entry(rd_regions, struct vgic_redist_region, list); - if (index != rdreg->index + 1) - return -EINVAL; - /* Cannot add an explicitly sized regions after legacy region */ - if (!rdreg->count) + if ((!count) != (!rdreg->count)) + return -EINVAL; /* Mix REDIST and REDIST_REGION */ + + if (!count) + return -EEXIST; + + if (index != rdreg->index + 1) return -EINVAL; } From patchwork Fri Mar 12 17:31:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 12135553 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2FA53C433DB for ; Fri, 12 Mar 2021 17:33:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F19B264FC3 for ; Fri, 12 Mar 2021 17:33:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232550AbhCLRch (ORCPT ); Fri, 12 Mar 2021 12:32:37 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:60792 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232043AbhCLRcZ (ORCPT ); Fri, 12 Mar 2021 12:32:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1615570344; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mdDREx6XEJ8GpRKupc63kfJAVUqoQp9Cy3QT3dCgXGE=; b=e0Q3vz2XoqvmBPP0h3O/4b4xCi4fNm5fmpo21CJBk6566ytMuAZvjnrTvDcYIBhHnvgMZa VVRExvrvScZCuUqEa4PompPdYpJzEeOIvIuTYcFuDPR+VJf7TaMqA+pR3jdac4qbRSVCea 5STmHk01VrSi/iJQ9S6xYA8uwlcdhPQ= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-130-Hym53le9OI2ark4-F_kjvg-1; Fri, 12 Mar 2021 12:32:23 -0500 X-MC-Unique: Hym53le9OI2ark4-F_kjvg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 89277800D55; Fri, 12 Mar 2021 17:32:21 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-254.ams2.redhat.com [10.36.112.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 52A971002388; Fri, 12 Mar 2021 17:32:17 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com Cc: james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, shuah@kernel.org, pbonzini@redhat.com Subject: [PATCH v3 2/8] KVM: arm64: Fix KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION read Date: Fri, 12 Mar 2021 18:31:56 +0100 Message-Id: <20210312173202.89576-3-eric.auger@redhat.com> In-Reply-To: <20210312173202.89576-1-eric.auger@redhat.com> References: <20210312173202.89576-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The doc says: "The characteristics of a specific redistributor region can be read by presetting the index field in the attr data. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3" Unfortunately the existing code fails to read the input attr data. Fixes: 04c110932225 ("KVM: arm/arm64: Implement KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION") Cc: stable@vger.kernel.org#v4.17+ Signed-off-by: Eric Auger Reviewed-by: Alexandru Elisei --- v1 -> v2: - in the commit message, remove the statement that the index always is 0 - add Alexandru's R-b --- arch/arm64/kvm/vgic/vgic-kvm-device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/kvm/vgic/vgic-kvm-device.c b/arch/arm64/kvm/vgic/vgic-kvm-device.c index 44419679f91a..2f66cf247282 100644 --- a/arch/arm64/kvm/vgic/vgic-kvm-device.c +++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c @@ -226,6 +226,9 @@ static int vgic_get_common_attr(struct kvm_device *dev, u64 addr; unsigned long type = (unsigned long)attr->attr; + if (copy_from_user(&addr, uaddr, sizeof(addr))) + return -EFAULT; + r = kvm_vgic_addr(dev->kvm, type, &addr, false); if (r) return (r == -ENODEV) ? -ENXIO : r; From patchwork Fri Mar 12 17:31:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 12135551 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F889C43381 for ; Fri, 12 Mar 2021 17:33:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2C73464FD9 for ; Fri, 12 Mar 2021 17:33:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232666AbhCLRci (ORCPT ); Fri, 12 Mar 2021 12:32:38 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:37435 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232217AbhCLRc3 (ORCPT ); Fri, 12 Mar 2021 12:32:29 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1615570348; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mfjQAaDuP/mR3DD+OPNLQ/Xq5ck0L3n/VihUobqZSI8=; b=d5R6HAPL32+pTxTqaXHYJ6RL5SJYgxhs4KNasVh2X9fkhnhc5sRF8bsvTto9AoHrkxvJs1 KbtJailgGxdSkMUNQazo3Ky52wM5oXhfOAMm1717nlKudw/XMfUtgYvPnGaXvNyTplzsxS tyYxRRosiy6Uy/RhmxbkKHJc3cTev1c= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-543-0ug2o4rDM-GUI5JrHKAsvw-1; Fri, 12 Mar 2021 12:32:27 -0500 X-MC-Unique: 0ug2o4rDM-GUI5JrHKAsvw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 29D381015C85; Fri, 12 Mar 2021 17:32:25 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-254.ams2.redhat.com [10.36.112.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id EC73E1002EE6; Fri, 12 Mar 2021 17:32:21 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com Cc: james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, shuah@kernel.org, pbonzini@redhat.com Subject: [PATCH v3 3/8] KVM: arm64: vgic-v3: Fix error handling in vgic_v3_set_redist_base() Date: Fri, 12 Mar 2021 18:31:57 +0100 Message-Id: <20210312173202.89576-4-eric.auger@redhat.com> In-Reply-To: <20210312173202.89576-1-eric.auger@redhat.com> References: <20210312173202.89576-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org vgic_v3_insert_redist_region() may succeed while vgic_register_all_redist_iodevs fails. For example this happens while adding a redistributor region overlapping a dist region. The failure only is detected on vgic_register_all_redist_iodevs when vgic_v3_check_base() gets called in vgic_register_redist_iodev(). In such a case, remove the newly added redistributor region and free it. Signed-off-by: Eric Auger --- v1 -> v2: - fix the commit message and split declaration/assignment of rdreg --- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index 013b737b658f..987e366c8000 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -860,8 +860,14 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count) * afterwards will register the iodevs when needed. */ ret = vgic_register_all_redist_iodevs(kvm); - if (ret) + if (ret) { + struct vgic_redist_region *rdreg; + + rdreg = vgic_v3_rdist_region_from_index(kvm, index); + list_del(&rdreg->list); + kfree(rdreg); return ret; + } return 0; } From patchwork Fri Mar 12 17:31:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 12135555 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7D19C433DB for ; Fri, 12 Mar 2021 17:33:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A3F7B64F6D for ; Fri, 12 Mar 2021 17:33:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232999AbhCLRdJ (ORCPT ); Fri, 12 Mar 2021 12:33:09 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:60129 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232176AbhCLRcn (ORCPT ); Fri, 12 Mar 2021 12:32:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1615570362; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DByFG8WE9w4blwkYdOK3/Dq3mki0T+Put1GzIk14928=; b=eYwQQLc0Pyb4sJgCoXSjwqXyAJZ3mgEQlmdvthNe4zf8brLR/5O36G5VbEu6vbWm7gRfWs rHjXvlXR70aPlua9rIg523giZ8Bf5qKrMVw+RYwv4m6E3U0ADDFJ1awJL0MyOLRHCPZ9R4 UuUGq6Ruq5sPRHqpeDmqBhAzMGmoGdc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-75-vduMqSMCPhSY4Aut4ULgdQ-1; Fri, 12 Mar 2021 12:32:41 -0500 X-MC-Unique: vduMqSMCPhSY4Aut4ULgdQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1EEDB108BD07; Fri, 12 Mar 2021 17:32:39 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-254.ams2.redhat.com [10.36.112.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 89C481009962; Fri, 12 Mar 2021 17:32:25 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com Cc: james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, shuah@kernel.org, pbonzini@redhat.com Subject: [PATCH v3 4/8] KVM: arm/arm64: vgic: Reset base address on kvm_vgic_dist_destroy() Date: Fri, 12 Mar 2021 18:31:58 +0100 Message-Id: <20210312173202.89576-5-eric.auger@redhat.com> In-Reply-To: <20210312173202.89576-1-eric.auger@redhat.com> References: <20210312173202.89576-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org On vgic_dist_destroy(), the addresses are not reset. However for kvm selftest purpose this would allow to continue the test execution even after a failure when running KVM_RUN. So let's reset the base addresses. Signed-off-by: Eric Auger --- v1 -> v2: - use dist-> in the else and add braces --- arch/arm64/kvm/vgic/vgic-init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 052917deb149..cf6faa0aeddb 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -335,13 +335,16 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm) kfree(dist->spis); dist->spis = NULL; dist->nr_spis = 0; + dist->vgic_dist_base = VGIC_ADDR_UNDEF; - if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { + if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list) { list_del(&rdreg->list); kfree(rdreg); } INIT_LIST_HEAD(&dist->rd_regions); + } else { + dist->vgic_cpu_base = VGIC_ADDR_UNDEF; } if (vgic_has_its(kvm)) @@ -362,6 +365,7 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) vgic_flush_pending_lpis(vcpu); INIT_LIST_HEAD(&vgic_cpu->ap_list_head); + vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; } /* To be called with kvm->lock held */ From patchwork Fri Mar 12 17:31:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 12135557 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21C58C433E0 for ; Fri, 12 Mar 2021 17:33:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D66FE64F70 for ; Fri, 12 Mar 2021 17:33:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233046AbhCLRdL (ORCPT ); Fri, 12 Mar 2021 12:33:11 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:49304 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232975AbhCLRcu (ORCPT ); Fri, 12 Mar 2021 12:32:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1615570369; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0uKBYh1tSc08YlThe5x4w/3MJ8XTaEMc9L9bVozy6w0=; b=Lt30PN2jNDd0ECY6jYd3bRdc2tfD1VUwHO4BSdEAU8OSb3O4VhlUmMeWq6uvKJkBjVu20s jJvUoXWRAqfoVf8iAbKKXF+nnknhomuH5L8jNALo9g7bjHQ+AC5Fw1KHTerC6w9O1vu4gv 0rlk0+SLrVNXKiitreR8Q5xGwAx81Go= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-505-e4DdS6LpMvKnHEPfN2M5vA-1; Fri, 12 Mar 2021 12:32:45 -0500 X-MC-Unique: e4DdS6LpMvKnHEPfN2M5vA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A791893920; Fri, 12 Mar 2021 17:32:43 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-254.ams2.redhat.com [10.36.112.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7EF491002388; Fri, 12 Mar 2021 17:32:39 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com Cc: james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, shuah@kernel.org, pbonzini@redhat.com Subject: [PATCH v3 5/8] docs: kvm: devices/arm-vgic-v3: enhance KVM_DEV_ARM_VGIC_CTRL_INIT doc Date: Fri, 12 Mar 2021 18:31:59 +0100 Message-Id: <20210312173202.89576-6-eric.auger@redhat.com> In-Reply-To: <20210312173202.89576-1-eric.auger@redhat.com> References: <20210312173202.89576-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org kvm_arch_vcpu_precreate() returns -EBUSY if the vgic is already initialized. So let's document that KVM_DEV_ARM_VGIC_CTRL_INIT must be called after all vcpu creations. Signed-off-by: Eric Auger --- v1 -> v2: - Must be called after all vcpu creations -> Must be called after all VCPUs have been created as per Alexandru's suggestion --- Documentation/virt/kvm/devices/arm-vgic-v3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/virt/kvm/devices/arm-vgic-v3.rst b/Documentation/virt/kvm/devices/arm-vgic-v3.rst index 5dd3bff51978..51e5e5762571 100644 --- a/Documentation/virt/kvm/devices/arm-vgic-v3.rst +++ b/Documentation/virt/kvm/devices/arm-vgic-v3.rst @@ -228,7 +228,7 @@ Groups: KVM_DEV_ARM_VGIC_CTRL_INIT request the initialization of the VGIC, no additional parameter in - kvm_device_attr.addr. + kvm_device_attr.addr. Must be called after all VCPUs have been created. KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES save all LPI pending bits into guest RAM pending tables. From patchwork Fri Mar 12 17:32:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 12135561 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D6520C4332E for ; Fri, 12 Mar 2021 17:33:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B22C264F27 for ; Fri, 12 Mar 2021 17:33:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233072AbhCLRdM (ORCPT ); Fri, 12 Mar 2021 12:33:12 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:28052 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232985AbhCLRcx (ORCPT ); Fri, 12 Mar 2021 12:32:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1615570372; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TfSxCMSqz+hjS9nhZYK1vsZAwrwIVNpKaR9ZlqBQD3E=; b=S26uMpWyMRWXl0a7IIxyomQcg5z7MQMqfvb7lO2AzP1xlyW4uqFq4pQJRwiJ7hiEEdvTMO kYjMU40V5VP7rl3EFdr2BT9UYPJXigEj7xq3HMueyr0x/cUQFfe/U/ou5DJUHyXEcLg61G pBpzofmrdwqlYdwH2Ij1TZVKyMI72Lc= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-564-Zjafp0eiPTqpYmo4ITY7EQ-1; Fri, 12 Mar 2021 12:32:50 -0500 X-MC-Unique: Zjafp0eiPTqpYmo4ITY7EQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6138693929; Fri, 12 Mar 2021 17:32:48 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-254.ams2.redhat.com [10.36.112.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 12DD41002EE6; Fri, 12 Mar 2021 17:32:44 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com Cc: james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, shuah@kernel.org, pbonzini@redhat.com Subject: [PATCH v3 6/8] KVM: arm64: Simplify argument passing to vgic_uaccess_[read|write] Date: Fri, 12 Mar 2021 18:32:00 +0100 Message-Id: <20210312173202.89576-7-eric.auger@redhat.com> In-Reply-To: <20210312173202.89576-1-eric.auger@redhat.com> References: <20210312173202.89576-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org vgic_uaccess() takes a struct vgic_io_device argument, converts it to a struct kvm_io_device and passes it to the read/write accessor functions, which convert it back to a struct vgic_io_device. Avoid the indirection by passing the struct vgic_io_device argument directly to vgic_uaccess_{read,write}. Signed-off-by: Eric Auger --- v1 -> v2: - reworded the commit message as suggested by Alexandru --- arch/arm64/kvm/vgic/vgic-mmio.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c index b2d73fc0d1ef..48c6067fc5ec 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio.c +++ b/arch/arm64/kvm/vgic/vgic-mmio.c @@ -938,10 +938,9 @@ vgic_get_mmio_region(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev, return region; } -static int vgic_uaccess_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, +static int vgic_uaccess_read(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev, gpa_t addr, u32 *val) { - struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev); const struct vgic_register_region *region; struct kvm_vcpu *r_vcpu; @@ -960,10 +959,9 @@ static int vgic_uaccess_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, return 0; } -static int vgic_uaccess_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, +static int vgic_uaccess_write(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev, gpa_t addr, const u32 *val) { - struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev); const struct vgic_register_region *region; struct kvm_vcpu *r_vcpu; @@ -986,9 +984,9 @@ int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev, bool is_write, int offset, u32 *val) { if (is_write) - return vgic_uaccess_write(vcpu, &dev->dev, offset, val); + return vgic_uaccess_write(vcpu, dev, offset, val); else - return vgic_uaccess_read(vcpu, &dev->dev, offset, val); + return vgic_uaccess_read(vcpu, dev, offset, val); } static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, From patchwork Fri Mar 12 17:32:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 12135559 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B68B2C43381 for ; Fri, 12 Mar 2021 17:33:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8891F64FC3 for ; Fri, 12 Mar 2021 17:33:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233096AbhCLRdM (ORCPT ); Fri, 12 Mar 2021 12:33:12 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:50775 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232986AbhCLRdA (ORCPT ); Fri, 12 Mar 2021 12:33:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1615570380; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EnVR6qOVBRd8kOthgXzIWyIygHlg5l5jPzBh8/NMyWc=; b=hZFoeWs0byQYeSkFj6ngirQoGzycGWqOWN4aOwZkIboiRhrOQvrEVwk+yvdVEDNLLLhuPr 3FIyG+EvsV0I3D3exq9+Gkcju9VzE9hWnmq2ckcwLZAvZTY2m9Kbr6EsezN9BejdbVSX8F xu3/XKt+TaAanyjErb7jgv5q49fp1XM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-516-lI4USvLyPTajr92wadrJhQ-1; Fri, 12 Mar 2021 12:32:58 -0500 X-MC-Unique: lI4USvLyPTajr92wadrJhQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3EC0C8030A0; Fri, 12 Mar 2021 17:32:56 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-254.ams2.redhat.com [10.36.112.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id C1F951009962; Fri, 12 Mar 2021 17:32:48 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com Cc: james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, shuah@kernel.org, pbonzini@redhat.com Subject: [PATCH v3 7/8] KVM: arm64: vgic-v3: Expose GICR_TYPER.Last for userspace Date: Fri, 12 Mar 2021 18:32:01 +0100 Message-Id: <20210312173202.89576-8-eric.auger@redhat.com> In-Reply-To: <20210312173202.89576-1-eric.auger@redhat.com> References: <20210312173202.89576-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Commit 23bde34771f1 ("KVM: arm64: vgic-v3: Drop the reporting of GICR_TYPER.Last for userspace") temporarily fixed a bug identified when attempting to access the GICR_TYPER register before the redistributor region setting, but dropped the support of the LAST bit. Emulating the GICR_TYPER.Last bit still makes sense for architecture compliance though. This patch restores its support (if the redistributor region was set) while keeping the code safe. We introduce a new helper, vgic_mmio_vcpu_rdist_is_last() which computes whether a redistributor is the highest one of a series of redistributor contributor pages. The spec says "Indicates whether this Redistributor is the highest-numbered Redistributor in a series of contiguous Redistributor pages." The code is a bit convulated since there is no guarantee redistributors are added in a given reditributor region in ascending order. In that case the current implementation was wrong. Also redistributor regions can be contiguous and registered in non increasing base address order. So the index of redistributors are stored in an array within the redistributor region structure. With this new implementation we do not need to have a uaccess read accessor anymore. Signed-off-by: Eric Auger --- arch/arm64/kvm/vgic/vgic-init.c | 7 +-- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 97 ++++++++++++++++++++---------- arch/arm64/kvm/vgic/vgic.h | 1 + include/kvm/arm_vgic.h | 3 + 4 files changed, 73 insertions(+), 35 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index cf6faa0aeddb..61150c34c268 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -190,6 +190,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) int i; vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; + vgic_cpu->index = vcpu->vcpu_id; INIT_LIST_HEAD(&vgic_cpu->ap_list_head); raw_spin_lock_init(&vgic_cpu->ap_list_lock); @@ -338,10 +339,8 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm) dist->vgic_dist_base = VGIC_ADDR_UNDEF; if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { - list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list) { - list_del(&rdreg->list); - kfree(rdreg); - } + list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list) + vgic_v3_free_redist_region(rdreg); INIT_LIST_HEAD(&dist->rd_regions); } else { dist->vgic_cpu_base = VGIC_ADDR_UNDEF; diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index 987e366c8000..652998ed0b55 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -251,45 +251,57 @@ static void vgic_mmio_write_v3r_ctlr(struct kvm_vcpu *vcpu, vgic_enable_lpis(vcpu); } +static bool vgic_mmio_vcpu_rdist_is_last(struct kvm_vcpu *vcpu) +{ + struct vgic_dist *vgic = &vcpu->kvm->arch.vgic; + struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + struct vgic_redist_region *rdreg = vgic_cpu->rdreg; + + if (!rdreg) + return false; + + if (!rdreg->count && vgic_cpu->rdreg_index == (rdreg->count - 1)) { + /* check whether there is no other contiguous rdist region */ + struct list_head *rd_regions = &vgic->rd_regions; + struct vgic_redist_region *iter; + + list_for_each_entry(iter, rd_regions, list) { + if (iter->base == rdreg->base + rdreg->count * KVM_VGIC_V3_REDIST_SIZE && + iter->free_index > 0) { + /* check the first rdist index of this region, if any */ + if (vgic_cpu->index < iter->rdist_indices[0]) + return false; + } + } + } else if (vgic_cpu->rdreg_index < rdreg->free_index - 1) { + /* look at the index of next rdist */ + int next_rdist_index = rdreg->rdist_indices[vgic_cpu->rdreg_index + 1]; + + if (vgic_cpu->index < next_rdist_index) + return false; + } + return true; +} + static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len) { unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu); - struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; - struct vgic_redist_region *rdreg = vgic_cpu->rdreg; int target_vcpu_id = vcpu->vcpu_id; - gpa_t last_rdist_typer = rdreg->base + GICR_TYPER + - (rdreg->free_index - 1) * KVM_VGIC_V3_REDIST_SIZE; u64 value; value = (u64)(mpidr & GENMASK(23, 0)) << 32; value |= ((target_vcpu_id & 0xffff) << 8); - if (addr == last_rdist_typer) + if (vgic_has_its(vcpu->kvm)) + value |= GICR_TYPER_PLPIS; + + if (vgic_mmio_vcpu_rdist_is_last(vcpu)) value |= GICR_TYPER_LAST; - if (vgic_has_its(vcpu->kvm)) - value |= GICR_TYPER_PLPIS; return extract_bytes(value, addr & 7, len); } -static unsigned long vgic_uaccess_read_v3r_typer(struct kvm_vcpu *vcpu, - gpa_t addr, unsigned int len) -{ - unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu); - int target_vcpu_id = vcpu->vcpu_id; - u64 value; - - value = (u64)(mpidr & GENMASK(23, 0)) << 32; - value |= ((target_vcpu_id & 0xffff) << 8); - - if (vgic_has_its(vcpu->kvm)) - value |= GICR_TYPER_PLPIS; - - /* reporting of the Last bit is not supported for userspace */ - return extract_bytes(value, addr & 7, len); -} - static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len) { @@ -612,7 +624,7 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = { VGIC_ACCESS_32bit), REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_TYPER, vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, - vgic_uaccess_read_v3r_typer, vgic_mmio_uaccess_write_wi, 8, + NULL, vgic_mmio_uaccess_write_wi, 8, VGIC_ACCESS_64bit | VGIC_ACCESS_32bit), REGISTER_DESC_WITH_LENGTH(GICR_WAKER, vgic_mmio_read_raz, vgic_mmio_write_wi, 4, @@ -714,6 +726,16 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) return -EINVAL; vgic_cpu->rdreg = rdreg; + vgic_cpu->rdreg_index = rdreg->free_index; + if (!rdreg->count) { + void *p = krealloc(rdreg->rdist_indices, + (vgic_cpu->rdreg_index + 1) * sizeof(u32), + GFP_KERNEL); + if (!p) + return -ENOMEM; + rdreg->rdist_indices = p; + } + rdreg->rdist_indices[vgic_cpu->rdreg_index] = vgic_cpu->index; rd_base = rdreg->base + rdreg->free_index * KVM_VGIC_V3_REDIST_SIZE; @@ -768,7 +790,7 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm) } /** - * vgic_v3_insert_redist_region - Insert a new redistributor region + * vgic_v3_alloc_redist_region - Allocate a new redistributor region * * Performs various checks before inserting the rdist region in the list. * Those tests depend on whether the size of the rdist region is known @@ -782,8 +804,8 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm) * * Return 0 on success, < 0 otherwise */ -static int vgic_v3_insert_redist_region(struct kvm *kvm, uint32_t index, - gpa_t base, uint32_t count) +static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index, + gpa_t base, uint32_t count) { struct vgic_dist *d = &kvm->arch.vgic; struct vgic_redist_region *rdreg; @@ -839,6 +861,13 @@ static int vgic_v3_insert_redist_region(struct kvm *kvm, uint32_t index, rdreg->count = count; rdreg->free_index = 0; rdreg->index = index; + if (count) { + rdreg->rdist_indices = kcalloc(count, sizeof(u32), GFP_KERNEL); + if (!rdreg->rdist_indices) { + ret = -ENOMEM; + goto free; + } + } list_add_tail(&rdreg->list, rd_regions); return 0; @@ -847,11 +876,18 @@ static int vgic_v3_insert_redist_region(struct kvm *kvm, uint32_t index, return ret; } +void vgic_v3_free_redist_region(struct vgic_redist_region *rdreg) +{ + list_del(&rdreg->list); + kfree(rdreg->rdist_indices); + kfree(rdreg); +} + int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count) { int ret; - ret = vgic_v3_insert_redist_region(kvm, index, addr, count); + ret = vgic_v3_alloc_redist_region(kvm, index, addr, count); if (ret) return ret; @@ -864,8 +900,7 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count) struct vgic_redist_region *rdreg; rdreg = vgic_v3_rdist_region_from_index(kvm, index); - list_del(&rdreg->list); - kfree(rdreg); + vgic_v3_free_redist_region(rdreg); return ret; } diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h index 64fcd7511110..bc418c2c1214 100644 --- a/arch/arm64/kvm/vgic/vgic.h +++ b/arch/arm64/kvm/vgic/vgic.h @@ -293,6 +293,7 @@ vgic_v3_rd_region_size(struct kvm *kvm, struct vgic_redist_region *rdreg) struct vgic_redist_region *vgic_v3_rdist_region_from_index(struct kvm *kvm, u32 index); +void vgic_v3_free_redist_region(struct vgic_redist_region *rdreg); bool vgic_v3_rdist_overlap(struct kvm *kvm, gpa_t base, size_t size); diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 3d74f1060bd1..9a3f060ac354 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -197,6 +197,7 @@ struct vgic_redist_region { gpa_t base; u32 count; /* number of redistributors or 0 if single region */ u32 free_index; /* index of the next free redistributor */ + int *rdist_indices; /* indices of the redistributors */ struct list_head list; }; @@ -322,6 +323,8 @@ struct vgic_cpu { */ struct vgic_io_device rd_iodev; struct vgic_redist_region *rdreg; + u32 rdreg_index; + int index; /* vcpu index */ /* Contains the attributes and gpa of the LPI pending tables. */ u64 pendbaser; From patchwork Fri Mar 12 17:32:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 12135563 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C402CC4332D for ; Fri, 12 Mar 2021 17:33:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 981C064FF5 for ; Fri, 12 Mar 2021 17:33:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232955AbhCLRdN (ORCPT ); Fri, 12 Mar 2021 12:33:13 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:56949 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232930AbhCLRdG (ORCPT ); Fri, 12 Mar 2021 12:33:06 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1615570385; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UMKN5Jrsm5WOpImTpwlncJkY6fDPKzjjJOPSwpCoGnw=; b=fEcnADmSOcZxSK91gXQ6X87UIGq3UDq1uMzwwlem2I90wluwSd2JuHiiIP+bCdFOiMlP+g uu/iQ6XJ2viZVzYciWtA6UQ1/dsPH8OV2RdAxw4AsmAfNCP2y0tOxdAwzGfu46kxqbRpkV Eb+NBmMO8IodjyhKCC79kAcHB9BeboU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-523-Y8EiSVj0O2mQQVDVVfe-kg-1; Fri, 12 Mar 2021 12:33:03 -0500 X-MC-Unique: Y8EiSVj0O2mQQVDVVfe-kg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D8A3881746A; Fri, 12 Mar 2021 17:33:01 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-254.ams2.redhat.com [10.36.112.254]) by smtp.corp.redhat.com (Postfix) with ESMTP id 75EB51002388; Fri, 12 Mar 2021 17:32:56 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, maz@kernel.org, drjones@redhat.com, alexandru.elisei@arm.com Cc: james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, shuah@kernel.org, pbonzini@redhat.com Subject: [PATCH v3 8/8] KVM: selftests: aarch64/vgic-v3 init sequence tests Date: Fri, 12 Mar 2021 18:32:02 +0100 Message-Id: <20210312173202.89576-9-eric.auger@redhat.com> In-Reply-To: <20210312173202.89576-1-eric.auger@redhat.com> References: <20210312173202.89576-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The tests exercise the VGIC_V3 device creation including the associated KVM_DEV_ARM_VGIC_GRP_ADDR group attributes: - KVM_VGIC_V3_ADDR_TYPE_DIST/REDIST - KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION Some other tests dedicate to KVM_DEV_ARM_VGIC_GRP_REDIST_REGS group and especially the GICR_TYPER read. The goal was to test the case recently fixed by commit 23bde34771f1 ("KVM: arm64: vgic-v3: Drop the reporting of GICR_TYPER.Last for userspace"). The API under test can be found at Documentation/virt/kvm/devices/arm-vgic-v3.rst Signed-off-by: Eric Auger --- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +- tools/testing/selftests/kvm/Makefile | 1 + .../testing/selftests/kvm/aarch64/vgic_init.c | 672 ++++++++++++++++++ .../testing/selftests/kvm/include/kvm_util.h | 5 + tools/testing/selftests/kvm/lib/kvm_util.c | 51 ++ 5 files changed, 730 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/kvm/aarch64/vgic_init.c diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index 652998ed0b55..f6a7eed1d6ad 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -260,7 +260,7 @@ static bool vgic_mmio_vcpu_rdist_is_last(struct kvm_vcpu *vcpu) if (!rdreg) return false; - if (!rdreg->count && vgic_cpu->rdreg_index == (rdreg->count - 1)) { + if (rdreg->count && vgic_cpu->rdreg_index == (rdreg->count - 1)) { /* check whether there is no other contiguous rdist region */ struct list_head *rd_regions = &vgic->rd_regions; struct vgic_redist_region *iter; diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index a6d61f451f88..4e548d7ab0ab 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -75,6 +75,7 @@ TEST_GEN_PROGS_x86_64 += steal_time TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list-sve +TEST_GEN_PROGS_aarch64 += aarch64/vgic_init TEST_GEN_PROGS_aarch64 += demand_paging_test TEST_GEN_PROGS_aarch64 += dirty_log_test TEST_GEN_PROGS_aarch64 += dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/aarch64/vgic_init.c b/tools/testing/selftests/kvm/aarch64/vgic_init.c new file mode 100644 index 000000000000..12205ab9fb10 --- /dev/null +++ b/tools/testing/selftests/kvm/aarch64/vgic_init.c @@ -0,0 +1,672 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * vgic init sequence tests + * + * Copyright (C) 2020, Red Hat, Inc. + */ +#define _GNU_SOURCE +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +#define NR_VCPUS 4 + +#define REDIST_REGION_ATTR_ADDR(count, base, flags, index) (((uint64_t)(count) << 52) | \ + ((uint64_t)((base) >> 16) << 16) | ((uint64_t)(flags) << 12) | index) +#define REG_OFFSET(vcpu, offset) (((uint64_t)vcpu << 32) | offset) + +#define GICR_TYPER 0x8 + +/* helper to access a redistributor register */ +static int access_redist_reg(int gicv3_fd, int vcpu, int offset, + uint32_t *val, bool write) +{ + uint64_t attr = REG_OFFSET(vcpu, offset); + + return kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + attr, val, write); +} + +/* dummy guest code */ +static void guest_code(int cpu) +{ + GUEST_SYNC(0); + GUEST_SYNC(1); + GUEST_SYNC(2); + GUEST_DONE(); +} + +/* we don't want to assert on run execution, hence that helper */ +static int run_vcpu(struct kvm_vm *vm, uint32_t vcpuid) +{ + static int run; + struct ucall uc; + int ret; + + vcpu_args_set(vm, vcpuid, 1, vcpuid); + ret = _vcpu_ioctl(vm, vcpuid, KVM_RUN, NULL); + get_ucall(vm, vcpuid, &uc); + run++; + + if (ret) + return -errno; + return 0; +} + +/** + * Helper routine that performs KVM device tests in general and + * especially ARM_VGIC_V3 ones. Eventually the ARM_VGIC_V3 + * device gets created, a legacy RDIST region is set at @0x0 + * and a DIST region is set @0x60000 + */ +int fuzz_dist_rdist(struct kvm_vm *vm) +{ + int ret, gicv3_fd, max_ipa_bits; + uint64_t addr; + + max_ipa_bits = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE); + + /* check ARM_VGIC_V3 device exists */ + ret = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, true); + if (ret) { + print_skip("GICv3 not supported"); + exit(KSFT_SKIP); + } + + /* try to create a non existing KVM device */ + ret = kvm_create_device(vm, 0, true); + TEST_ASSERT(ret == -ENODEV, "unsupported device"); + + /* Create the ARM_VGIC_V3 device */ + gicv3_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, false); + TEST_ASSERT(gicv3_fd > 0, "GICv3 device created"); + + /* Check existing group/attributes */ + ret = kvm_device_check_attr(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_DIST); + TEST_ASSERT(!ret, "KVM_DEV_ARM_VGIC_GRP_ADDR/KVM_VGIC_V3_ADDR_TYPE_DIST supported"); + + ret = kvm_device_check_attr(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST); + TEST_ASSERT(!ret, "KVM_DEV_ARM_VGIC_GRP_ADDR/KVM_VGIC_V3_ADDR_TYPE_REDIST supported"); + + /* check non existing attribute */ + ret = kvm_device_check_attr(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, 0); + TEST_ASSERT(ret == -ENXIO, "attribute not supported"); + + /* misaligned DIST and REDIST address settings */ + addr = 0x1000; + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_DIST, &addr, true); + TEST_ASSERT(ret == -EINVAL, "GICv3 dist base not 64kB aligned"); + + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true); + TEST_ASSERT(ret == -EINVAL, "GICv3 redist base not 64kB aligned"); + + /* out of range address */ + if (max_ipa_bits) { + addr = 1ULL << max_ipa_bits; + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_DIST, &addr, true); + TEST_ASSERT(ret == -E2BIG, "dist address beyond IPA limit"); + + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true); + TEST_ASSERT(ret == -E2BIG, "redist address beyond IPA limit"); + } + + /* set REDIST base address @0x0*/ + addr = 0x00000; + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true); + TEST_ASSERT(!ret, "GICv3 redist base set"); + + /* Attempt to create a second legacy redistributor region */ + addr = 0xE0000; + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true); + TEST_ASSERT(ret == -EEXIST, "GICv3 redist base set again"); + + /* Attempt to mix legacy and new redistributor regions */ + addr = REDIST_REGION_ATTR_ADDR(NR_VCPUS, 0x100000, 0, 0); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "attempt to mix GICv3 REDIST and REDIST_REGION"); + + /* + * Set overlapping DIST / REDIST, cannot be detected here. Will be detected + * on first vcpu run instead. + */ + addr = 3 * 2 * 0x10000; + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V3_ADDR_TYPE_DIST, + &addr, true); + TEST_ASSERT(!ret, "dist overlapping rdist"); + + ret = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, false); + TEST_ASSERT(ret == -EEXIST, "create GICv3 device twice"); + + ret = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, true); + TEST_ASSERT(!ret, "create GICv3 in test mode while the same already is created"); + + if (!kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V2, true)) { + ret = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V2, true); + TEST_ASSERT(ret == -EINVAL, "create GICv2 while v3 exists"); + } + + return gicv3_fd; +} + +/* Test the new REDIST region API */ +static int fuzz_redist_regions(struct kvm_vm *vm) +{ + int ret, max_ipa_bits, gicv3_fd; + uint64_t addr, expected_addr; + + max_ipa_bits = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE); + + /* trial mode */ + ret = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, true); + if (ret) { + print_skip("GICv3 not supported"); + exit(KSFT_SKIP); + } + + /* Create the actual gicv3 device */ + gicv3_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, false); + TEST_ASSERT(gicv3_fd >= 0, "VGIC_V3 device created"); + + ret = kvm_device_check_attr(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST); + TEST_ASSERT(!ret, "Multiple redist regions advertised"); + + addr = REDIST_REGION_ATTR_ADDR(NR_VCPUS, 0x100000, 2, 0); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "redist region attr value with flags != 0"); + + addr = REDIST_REGION_ATTR_ADDR(0, 0x100000, 0, 0); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "redist region attr value with count== 0"); + + addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "attempt to register the first rdist region with index != 0"); + + addr = REDIST_REGION_ATTR_ADDR(2, 0x201000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "rdist region with misaligned address"); + + addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "First valid redist region with 2 rdist @ 0x200000, index 0"); + + addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "register an rdist region with already used index"); + + addr = REDIST_REGION_ATTR_ADDR(1, 0x210000, 0, 2); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "register an rdist region overlapping with another one"); + + addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 2); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "register redist region with index not +1"); + + addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "register valid redist region with 1 rdist @ 0x220000, index 1"); + + addr = REDIST_REGION_ATTR_ADDR(1, 1ULL << max_ipa_bits, 0, 2); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -E2BIG, "register redist region with base address beyond IPA range"); + + addr = 0x260000; + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true); + TEST_ASSERT(ret == -EINVAL, "Mix KVM_VGIC_V3_ADDR_TYPE_REDIST and REDIST_REGION"); + + /* + * Now there are 2 redist regions: + * region 0 @ 0x200000 2 redists + * region 1 @ 0x240000 1 redist + * now attempt to read their characteristics + */ + + addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 0); + expected_addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false); + TEST_ASSERT(!ret && addr == expected_addr, "read characteristics of region #0"); + + addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 1); + expected_addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false); + TEST_ASSERT(!ret && addr == expected_addr, "read characteristics of region #1"); + + addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 2); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false); + TEST_ASSERT(ret == -ENOENT, "read characteristics of non existing region"); + + addr = 0x260000; + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_DIST, &addr, true); + TEST_ASSERT(!ret, "set dist region"); + + addr = REDIST_REGION_ATTR_ADDR(1, 0x260000, 0, 2); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "register redist region colliding with dist"); + + return gicv3_fd; +} + +/* + * VGIC KVM device is created and initialized before the secondary CPUs + * get created + */ +static void test_vgic_then_vcpus(void) +{ + int ret, i, gicv3_fd; + struct kvm_vm *vm; + + vm = vm_create_default(0, 0, guest_code); + + gicv3_fd = fuzz_dist_rdist(vm); + + /* Add the rest of the VCPUs */ + for (i = 1; i < NR_VCPUS; ++i) + vm_vcpu_add_default(vm, i, guest_code); + + ret = run_vcpu(vm, 3); + TEST_ASSERT(ret == -EINVAL, "dist/rdist overlap detected on 1st vcpu run"); + + close(gicv3_fd); + kvm_vm_free(vm); +} + + +/* All the VCPUs are created before the VGIC KVM device gets initialized */ +static void test_vcpus_then_vgic(void) +{ + int ret, i, gicv3_fd; + struct kvm_vm *vm; + + vm = vm_create_default(0, 0, guest_code); + + /* Add the rest of the VCPUs */ + for (i = 1; i < NR_VCPUS; ++i) + vm_vcpu_add_default(vm, i, guest_code); + + gicv3_fd = fuzz_dist_rdist(vm); + + ret = run_vcpu(vm, 3); + TEST_ASSERT(ret == -EINVAL, "dist/rdist overlap detected on 1st vcpu run"); + + close(gicv3_fd); + kvm_vm_free(vm); +} + +static void redist_regions_setup(struct kvm_vm **vm, int *gicv3_fd) +{ + int i; + + *vm = vm_create_default(0, 0, guest_code); + ucall_init(*vm, NULL); + + /* Add the rest of the VCPUs */ + for (i = 1; i < NR_VCPUS; ++i) + vm_vcpu_add_default(*vm, i, guest_code); + + *gicv3_fd = fuzz_redist_regions(*vm); +} + +static void test_new_redist_regions(void) +{ + int ret, gicv3_fd; + struct kvm_vm *vm; + uint64_t addr; + void *dummy = NULL; + + redist_regions_setup(&vm, &gicv3_fd); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true); + TEST_ASSERT(!ret, "init the vgic"); + + ret = run_vcpu(vm, 3); + TEST_ASSERT(ret == -ENXIO, "running without sufficient number of rdists"); + + close(gicv3_fd); + kvm_vm_free(vm); + + /* step2 */ + + redist_regions_setup(&vm, &gicv3_fd); + + addr = REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "register a third region allowing to cover the 4 vcpus"); + + ret = run_vcpu(vm, 3); + TEST_ASSERT(ret == -EBUSY, "running without vgic explicit init"); + + close(gicv3_fd); + kvm_vm_free(vm); + + /* step 3 */ + + redist_regions_setup(&vm, &gicv3_fd); + + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, dummy, true); + TEST_ASSERT(ret == -EFAULT, "register a third region allowing to cover the 4 vcpus"); + + addr = REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "register a third region allowing to cover the 4 vcpus"); + + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true); + TEST_ASSERT(!ret, "init the vgic"); + + ret = run_vcpu(vm, 3); + TEST_ASSERT(!ret, "vcpu run"); + + close(gicv3_fd); + kvm_vm_free(vm); +} + +static void test_typer_accesses(void) +{ + int ret, i, gicv3_fd = -1; + uint64_t addr; + struct kvm_vm *vm; + uint32_t val; + + vm = vm_create_default(0, 0, guest_code); + ucall_init(vm, NULL); + + gicv3_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, false); + TEST_ASSERT(gicv3_fd >= 0, "VGIC_V3 device created"); + + vm_vcpu_add_default(vm, 3, guest_code); + + ret = access_redist_reg(gicv3_fd, 1, GICR_TYPER, &val, false); + TEST_ASSERT(ret == -EINVAL, "attempting to read GICR_TYPER of non created vcpu"); + + vm_vcpu_add_default(vm, 1, guest_code); + + ret = access_redist_reg(gicv3_fd, 1, GICR_TYPER, &val, false); + TEST_ASSERT(ret == -EBUSY, "read GICR_TYPER before GIC initialized"); + + vm_vcpu_add_default(vm, 2, guest_code); + + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true); + TEST_ASSERT(!ret, "init the vgic after the vcpu creations"); + + for (i = 0; i < NR_VCPUS ; i++) { + ret = access_redist_reg(gicv3_fd, 0, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && !val, "read GICR_TYPER before rdist region setting"); + } + + addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "first rdist region with a capacity of 2 rdists"); + + /* The 2 first rdists should be put there (vcpu 0 and 3) */ + ret = access_redist_reg(gicv3_fd, 0, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && !val, "read typer of rdist #0"); + + ret = access_redist_reg(gicv3_fd, 3, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x310, "read typer of rdist #1"); + + addr = REDIST_REGION_ATTR_ADDR(10, 0x100000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(ret == -EINVAL, "collision with previous rdist region"); + + ret = access_redist_reg(gicv3_fd, 1, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x100, + "no redist region attached to vcpu #1 yet, last cannot be returned"); + + ret = access_redist_reg(gicv3_fd, 2, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x200, + "no redist region attached to vcpu #2, last cannot be returned"); + + addr = REDIST_REGION_ATTR_ADDR(10, 0x20000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "second rdist region"); + + ret = access_redist_reg(gicv3_fd, 1, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #1"); + + ret = access_redist_reg(gicv3_fd, 2, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x210, + "read typer of rdist #1, last properly returned"); + + close(gicv3_fd); + kvm_vm_free(vm); +} + +/** + * Test GICR_TYPER last bit with new redist regions + * 2 rdist regions that are contiguous + * rdist region #0 @0x200000 3 rdist capacity + * rdists: 0, 2 (Last), 1 + * rdist region #1 @0x260000 10 rdist capacity + * rdists: 3, 5 (Last), 4 (Last) + */ +static void test_last_bit_1(void) +{ + int ret, gicv3_fd = -1; + uint64_t addr; + struct kvm_vm *vm; + uint32_t val; + + vm = vm_create_default(0, 0, guest_code); + ucall_init(vm, NULL); + + gicv3_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, false); + TEST_ASSERT(gicv3_fd >= 0, "VGIC_V3 device created"); + + vm_vcpu_add_default(vm, 2, guest_code); + vm_vcpu_add_default(vm, 1, guest_code); + vm_vcpu_add_default(vm, 3, guest_code); + vm_vcpu_add_default(vm, 5, guest_code); + vm_vcpu_add_default(vm, 4, guest_code); + + ret = access_redist_reg(gicv3_fd, 0, GICR_TYPER, &val, false); + TEST_ASSERT(ret, "read typer of rdist #0 before redist reg creation"); + + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true); + TEST_ASSERT(!ret, "init the vgic after the vcpu creations"); + + addr = REDIST_REGION_ATTR_ADDR(3, 0x200000, 0, 0); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "rdist region #0 with a capacity of 3 rdists"); + + addr = REDIST_REGION_ATTR_ADDR(10, 0x260000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "rdist region #1 (1 rdist) contiguous with the 1st one"); + + /* + * rdist_region #0 should contain rdists 0, 2, 1 + * rdist region #1 should contain rdists 3, 5, 4 + */ + ret = access_redist_reg(gicv3_fd, 0, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && !val, "read typer of rdist #0"); + + ret = access_redist_reg(gicv3_fd, 2, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x210, "read typer of rdist #2"); + + ret = access_redist_reg(gicv3_fd, 1, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #1"); + + ret = access_redist_reg(gicv3_fd, 3, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x300, "read typer of rdist #3"); + + ret = access_redist_reg(gicv3_fd, 5, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x510, "read typer of rdist #3"); + + ret = access_redist_reg(gicv3_fd, 4, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x410, "read typer of rdist #3"); + + close(gicv3_fd); + kvm_vm_free(vm); +} + +/** + * Test GICR_TYPER last bit with new redist regions + * rdist regions #1 and #2 are contiguous + * rdist region #0 @0x100000 1 rdist capacity + * rdists: 0 (Last) + * rdist region #1 @0x240000 3 rdist capacity + * rdists: 3, 5 (Last), 4 (Last) + * rdist region #2 @0x200000 2 rdist capacity + * rdists: 1, 2 + */ +static void test_last_bit_2(void) +{ + int ret, gicv3_fd; + uint64_t addr; + struct kvm_vm *vm; + uint32_t val; + + vm = vm_create_default(0, 0, guest_code); + vm_vcpu_add_default(vm, 3, guest_code); + vm_vcpu_add_default(vm, 5, guest_code); + vm_vcpu_add_default(vm, 4, guest_code); + vm_vcpu_add_default(vm, 1, guest_code); + vm_vcpu_add_default(vm, 2, guest_code); + + ucall_init(vm, NULL); + + gicv3_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, false); + TEST_ASSERT(gicv3_fd >= 0, "VGIC_V3 device created"); + + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true); + TEST_ASSERT(!ret, "init the vgic after the vcpu creations"); + + addr = REDIST_REGION_ATTR_ADDR(1, 0x100000, 0, 0); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "rdist region #0 (1 rdist)"); + + addr = REDIST_REGION_ATTR_ADDR(3, 0x240000, 0, 1); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "rdist region #1 (1 rdist) contiguous with #2"); + + addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 2); + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true); + TEST_ASSERT(!ret, "rdist region #2 with a capacity of 3 rdists"); + + + ret = access_redist_reg(gicv3_fd, 0, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x010, "read typer of rdist #0"); + + ret = access_redist_reg(gicv3_fd, 1, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #1"); + + ret = access_redist_reg(gicv3_fd, 2, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x200, "read typer of rdist #2"); + + ret = access_redist_reg(gicv3_fd, 3, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x300, "read typer of rdist #3"); + + ret = access_redist_reg(gicv3_fd, 5, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x510, "read typer of rdist #3"); + + ret = access_redist_reg(gicv3_fd, 4, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x410, "read typer of rdist #3"); + + close(gicv3_fd); + kvm_vm_free(vm); +} + +/* Test last bit with legacy region */ +static void test_last_bit_3(void) +{ + int ret, gicv3_fd; + uint64_t addr; + struct kvm_vm *vm; + uint32_t val; + + vm = vm_create_default(0, 0, guest_code); + vm_vcpu_add_default(vm, 3, guest_code); + vm_vcpu_add_default(vm, 5, guest_code); + vm_vcpu_add_default(vm, 4, guest_code); + vm_vcpu_add_default(vm, 1, guest_code); + vm_vcpu_add_default(vm, 2, guest_code); + + ucall_init(vm, NULL); + + gicv3_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3, false); + TEST_ASSERT(gicv3_fd >= 0, "VGIC_V3 device created"); + + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true); + TEST_ASSERT(!ret, "init the vgic after the vcpu creations"); + + addr = 0x10000; + ret = kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, + KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true); + + ret = access_redist_reg(gicv3_fd, 0, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x000, "read typer of rdist #0"); + + ret = access_redist_reg(gicv3_fd, 3, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x300, "read typer of rdist #1"); + + ret = access_redist_reg(gicv3_fd, 5, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x510, "read typer of rdist #2"); + + ret = access_redist_reg(gicv3_fd, 1, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #3"); + + ret = access_redist_reg(gicv3_fd, 2, GICR_TYPER, &val, false); + TEST_ASSERT(!ret && val == 0x210, "read typer of rdist #3"); + + close(gicv3_fd); + kvm_vm_free(vm); +} + +int main(int ac, char **av) +{ + test_vcpus_then_vgic(); + test_vgic_then_vcpus(); + test_new_redist_regions(); + test_typer_accesses(); + test_last_bit_1(); + test_last_bit_2(); + test_last_bit_3(); + + return 0; +} + diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index 2d7eb6989e83..f82277cadc6b 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -223,6 +223,11 @@ int vcpu_nested_state_set(struct kvm_vm *vm, uint32_t vcpuid, #endif void *vcpu_map_dirty_ring(struct kvm_vm *vm, uint32_t vcpuid); +int kvm_device_check_attr(int dev_fd, uint32_t group, uint64_t attr); +int kvm_create_device(struct kvm_vm *vm, uint64_t type, bool test); +int kvm_device_access(int dev_fd, uint32_t group, uint64_t attr, + void *val, bool write); + const char *exit_reason_str(unsigned int exit_reason); void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot); diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index e5fbf16f725b..da43c1f5730e 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -1728,6 +1728,57 @@ int _kvm_ioctl(struct kvm_vm *vm, unsigned long cmd, void *arg) return ioctl(vm->kvm_fd, cmd, arg); } +/* + * Device Ioctl + */ + +int kvm_device_check_attr(int dev_fd, uint32_t group, uint64_t attr) +{ + struct kvm_device_attr attribute = { + .group = group, + .attr = attr, + .flags = 0, + }; + int ret; + + ret = ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attribute); + if (ret == -1) + return -errno; + return ret; +} + +int kvm_create_device(struct kvm_vm *vm, uint64_t type, bool test) +{ + struct kvm_create_device create_dev; + int ret; + + create_dev.type = type; + create_dev.fd = -1; + create_dev.flags = test ? KVM_CREATE_DEVICE_TEST : 0; + ret = ioctl(vm_get_fd(vm), KVM_CREATE_DEVICE, &create_dev); + if (ret == -1) + return -errno; + return test ? 0 : create_dev.fd; +} + +int kvm_device_access(int dev_fd, uint32_t group, uint64_t attr, + void *val, bool write) +{ + struct kvm_device_attr kvmattr = { + .group = group, + .attr = attr, + .flags = 0, + .addr = (uintptr_t)val, + }; + int ret; + + ret = ioctl(dev_fd, write ? KVM_SET_DEVICE_ATTR : KVM_GET_DEVICE_ATTR, + &kvmattr); + if (ret) + return -errno; + return ret; +} + /* * VM Dump *