From patchwork Wed Nov 6 08:30:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jing Zhang X-Patchwork-Id: 13864099 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4476ED29FB8 for ; Wed, 6 Nov 2024 08:34:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:Cc:To:From: Subject:Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=T4GbN8ZDurMjcmVHL6T0Xi9xUq1GYOGvqk92rYIEnWQ=; b=P2xiYRI8741ri2oyUsqmFHudTY l6KS04nBuV5frPrarbWujLLdhBtSkRtXLoP6D/GqpyHGqE1KX5aaqV9gbdzqCz5v3z72JO2w3IJYp t8U9M3tz4g1uCvrOKywA78w0oId2xk3fZbfiWrBJLv7nnjKqUgCdhufb7dGn6aCT90fs7XTSGhHE0 u/g0S7AkYtdQRRm7MEgYrlPLddxpALUe7yMUAC7Z17u5ok/ViXLb6QfVX6BHhIqZIBa7zBdqQyum/ qL/elf0rdL/paYJqBtrNoAQhAwN3ZUr1Zu0tp7m4/fOYUOmVQpUQnUBBQY/3u8P+l5OL3MTorMXeU JT1UG45A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1t8bUY-00000002J43-1pjq; Wed, 06 Nov 2024 08:34:18 +0000 Received: from mail-yb1-xb4a.google.com ([2607:f8b0:4864:20::b4a]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1t8bR6-00000002IRI-02Ws for linux-arm-kernel@lists.infradead.org; Wed, 06 Nov 2024 08:30:45 +0000 Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-e30ceaa5feeso10910328276.2 for ; Wed, 06 Nov 2024 00:30:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1730881842; x=1731486642; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=T4GbN8ZDurMjcmVHL6T0Xi9xUq1GYOGvqk92rYIEnWQ=; b=MiUKvEYiK4axmCytd+Me8b0pRf3ZKHqKbwT8gFIAKOFUdHwLuzJ8lzPDu9lkXqRFvh kPGuBz8PeoO2Ybz0ijD2A2+NJNKgANN0zydQ0slcJLhwxjRhYDsDwdR9Tc9lSwAk7c7x SHojyrIx1PNX8+csF5b1gIcOKTsmv8D1+tvpWtgrQ3PnqAZzLCO/lBHho6x72aTJApbB OKf2o5p15ec51slyqU/tb6+VoHSVGshCSO1Pp46d0J3IzA5HSQLS6i+Dlj8SpBrG8CUC yFRsIl9TnQvkugWSt+1GbjRSZ22T4NYVBuK2JcJJXi4yw+wWSna5Uzs9QlpeBylxr9eN b8Uw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730881842; x=1731486642; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=T4GbN8ZDurMjcmVHL6T0Xi9xUq1GYOGvqk92rYIEnWQ=; b=cFrqkVb+SH1SIVN398fqMY17EZKb4VBZBIOxyFv2Ei8rCwg3gPlGUQkncfRnWVFrzy mLyIQPgUlUjfiPYKWHHxsI3fMDIgcj2CEz+eoaF7GL0UZak6W4NBnZ9TvkZv1eEfk/Mq ffKyPLUV9Hycby6PeDCAAkBz+5ksv0UtepxskDKvg6GF30kSsCidDypowXO7AJLBGRCw rShZrTlACQj1zA9iAjlY3FbPnjNjKr3itS/7J+si1PcX7cclUZp4W3DfGiQHapB3VUVp nqg1Hu82qyxnXVeUPshR5JjQUleCjWzZQPP9uQSOzT+miJpp9BCIZ7d7939tQSN99e8v e8TQ== X-Forwarded-Encrypted: i=1; AJvYcCXqRVa79Ef14k+qEf1wz2+3vci8vJGGDc5QbelMMj0tshpemkODMEJmi3lXvRYuadMaEvU4HT9mxx5jdznkUehq@lists.infradead.org X-Gm-Message-State: AOJu0Ywpdy1KcjWZ3T4mVyb9eMdHguxrC4ciRYZxQAARna+y6VHSb3i7 +oUWmTAlyAl9uzWVJOypV0tndobchDdje5wVKiByl2VeXDnf59XUUe1agDPR6FW2fi/iu/kMr9M oH1KsCBRezBevJwQkWrz6TA== X-Google-Smtp-Source: AGHT+IESgZ2HUDGTGAdUvYoZM+ViRqBFK9RcS/H99OhminhorZqyukanemB5KOr2KI9Z7I4wBJZ181jopq1rHk8LBA== X-Received: from jgzg.c.googlers.com ([fda3:e722:ac3:cc00:36:e7b8:ac13:c96f]) (user=jingzhangos job=sendgmr) by 2002:a5b:308:0:b0:e33:2432:8b75 with SMTP id 3f1490d57ef6-e3324328dedmr19767276.7.1730881841856; Wed, 06 Nov 2024 00:30:41 -0800 (PST) Date: Wed, 6 Nov 2024 00:30:32 -0800 In-Reply-To: <20241106083035.2813799-1-jingzhangos@google.com> Mime-Version: 1.0 References: <20241106083035.2813799-1-jingzhangos@google.com> X-Mailer: git-send-email 2.47.0.277.g8800431eea-goog Message-ID: <20241106083035.2813799-2-jingzhangos@google.com> Subject: [PATCH v3 1/4] KVM: arm64: vgic-its: Add a data length check in vgic_its_save_* From: Jing Zhang To: KVM , KVMARM , ARMLinux , Marc Zyngier , Oliver Upton , Joey Gouly , Zenghui Yu , Suzuki K Poulose , Kunkun Jiang Cc: Paolo Bonzini , Andre Przywara , Colton Lewis , Raghavendra Rao Ananta , Shusen Li , Jing Zhang X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241106_003044_413943_1086407D X-CRM114-Status: GOOD ( 13.59 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Kunkun Jiang In all the vgic_its_save_*() functinos, they do not check whether the data length is 8 bytes before calling vgic_write_guest_lock. This patch adds the check. To prevent the kernel from being blown up when the fault occurs, KVM_BUG_ON() is used. And the other BUG_ON()s are replaced together. Signed-off-by: Kunkun Jiang Signed-off-by: Jing Zhang --- arch/arm64/kvm/vgic/vgic-its.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index ba945ba78cc7..2381bc5ce544 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -2095,6 +2095,10 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev, ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) | ite->collection->collection_id; val = cpu_to_le64(val); + + if (KVM_BUG_ON(ite_esz != sizeof(val), kvm)) + return -EINVAL; + return vgic_write_guest_lock(kvm, gpa, &val, ite_esz); } @@ -2250,6 +2254,10 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev, (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) | (dev->num_eventid_bits - 1)); val = cpu_to_le64(val); + + if (KVM_BUG_ON(dte_esz != sizeof(val), kvm)) + return -EINVAL; + return vgic_write_guest_lock(kvm, ptr, &val, dte_esz); } @@ -2431,12 +2439,17 @@ static int vgic_its_save_cte(struct vgic_its *its, struct its_collection *collection, gpa_t gpa, int esz) { + struct kvm *kvm = its->dev->kvm; u64 val; val = (1ULL << KVM_ITS_CTE_VALID_SHIFT | ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) | collection->collection_id); val = cpu_to_le64(val); + + if (KVM_BUG_ON(esz != sizeof(val), kvm)) + return -EINVAL; + return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz); } @@ -2453,7 +2466,9 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz) u64 val; int ret; - BUG_ON(esz > sizeof(val)); + if (KVM_BUG_ON(esz != sizeof(val), kvm)) + return -EINVAL; + ret = kvm_read_guest_lock(kvm, gpa, &val, esz); if (ret) return ret; @@ -2517,7 +2532,9 @@ static int vgic_its_save_collection_table(struct vgic_its *its) * with valid bit unset */ val = 0; - BUG_ON(cte_esz > sizeof(val)); + if (KVM_BUG_ON(cte_esz != sizeof(val), its->dev->kvm)) + return -EINVAL; + ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz); return ret; } From patchwork Wed Nov 6 08:30:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jing Zhang X-Patchwork-Id: 13864100 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A59E4D29FB8 for ; Wed, 6 Nov 2024 08:36:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:Cc:To:From: Subject:Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=diXjwQHhYDrLApdizCzZAM2Cz7No88ZBnmospkxRJcg=; b=f9WQNsZ70YYk41PLEAw0YETArX aTi+e4GjzjK/Staa0YH9B9V7CwKTGUgn1gzqTdaaHy65ueYGcl55W7CXMK4nHSo1ml2yi8RdMX88s G/dthcSvtZLk8t4ss+sz/x6N4yuus/7MEzcpGE2KPzxbL05GROuYAEz02b7Nrguva6FkuXFrXCxrd O1UWDjPWyfLPTd1lNyLROJasp+wfHN8v6QKtFONB4V+ilCyEPuv9cjmPeZGqmJ4oUhf4fQaoJPeG+ pPHpRx23Pp+lZwpy30MmEsPJSQsusOIMpLnTBzQO/yG5jztXHyiKwI80KH9pHGXhxY2yrd3FC5jVc GnOExVEw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1t8bWE-00000002JRl-3Q96; Wed, 06 Nov 2024 08:36:02 +0000 Received: from mail-yw1-x114a.google.com ([2607:f8b0:4864:20::114a]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1t8bR7-00000002IRk-0Hgo for linux-arm-kernel@lists.infradead.org; Wed, 06 Nov 2024 08:30:46 +0000 Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-6e59dc7df64so7779507b3.1 for ; Wed, 06 Nov 2024 00:30:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1730881843; x=1731486643; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=diXjwQHhYDrLApdizCzZAM2Cz7No88ZBnmospkxRJcg=; b=DjX//2zizE4JcCkk/wy6AlE1aryqFObunUhqCd7zcuAZ2x+u+8g5mi1fUrZ8Xf0G07 8nvkLYfxdbGzeMWry4bev86ZHK0KrTptG5QiRPqiExOa+vSZU2RybP3/ODk2MSZweyYo UD77AqGmoJ63yfFcUYzSCJeZ3nGp4TpJuwx+R3HxUT7ypmbjxd5zUTnNFkmIbHTx/2M7 5U9pWQnyMBDmXzosRr8dbazteRk8nGDpJSuy9ogApVxxr/gbupAfdULECYjZnaRvnINx GfcWihdaZ9V3ghGytx5wcMijJaTk7vnirCdtWBN0UfNla9A2b4oPhywaRVpJx0s3M8Xg AkwQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730881843; x=1731486643; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=diXjwQHhYDrLApdizCzZAM2Cz7No88ZBnmospkxRJcg=; b=aQsG9OUG2bH7EFipfB6+M/ykh2xiqofsefE4tU7looXo0PNB19NWpw/5tQw5VEIzug mFb+080Y9KBDRo5nLIL9O6+i8Nmw1iNWwcg/bgcK0isgq61oiOgI7jO0fdBHA9fbPK11 VTnbSJz8ZZqFOIlem2irO9PulBhgHIg9HT1/xoZzlBA3bKerUBfYvC/CPA5IqaJsi5RE dn4fIfys3f5zQ52ZvbqAG2su6RcmoU7IEo5XWgmEhGR/PwjRj8uNPv0qHaealtYP864M Kxm0sI8NTIYQP264+jsJ5m4fUovayWxAfurBcDs4nGPxKwrhDBo+cJ/9PNlPnhwW1lSv IfFA== X-Forwarded-Encrypted: i=1; AJvYcCUz495xE/cuZnVe9HdOcdj7QusBnBHib7GYYbmEJRAWPokC/z1Mg7jYcdApZuLF5rNcvw4OEUSw78yQ9o/e9kSB@lists.infradead.org X-Gm-Message-State: AOJu0YwwWrEBbQzUk2Lz5Xa2/WaVt1eobv+QyrdwwHp1V+sfsZV72E9L PQS0rMKBgQOG1cabq0crafC11xv7o1Vng7jygTaAv2LKbMJVImmYJ8z+VCkNdW3DOxW6RuZ0lDn wIANm0kI28vzgcu664kzQ6A== X-Google-Smtp-Source: AGHT+IHBjq15b6Y9u9NLiJuGhJ0HwVi1u2HdYmZIETeo0dLVKCCo/ZW6prnAhvaB3StzEMzIb/ffCzTWRHXU7A2VXw== X-Received: from jgzg.c.googlers.com ([fda3:e722:ac3:cc00:36:e7b8:ac13:c96f]) (user=jingzhangos job=sendgmr) by 2002:a05:690c:4a04:b0:6ea:881b:b545 with SMTP id 00721157ae682-6eabf0290c6mr591907b3.4.1730881843278; Wed, 06 Nov 2024 00:30:43 -0800 (PST) Date: Wed, 6 Nov 2024 00:30:33 -0800 In-Reply-To: <20241106083035.2813799-1-jingzhangos@google.com> Mime-Version: 1.0 References: <20241106083035.2813799-1-jingzhangos@google.com> X-Mailer: git-send-email 2.47.0.277.g8800431eea-goog Message-ID: <20241106083035.2813799-3-jingzhangos@google.com> Subject: [PATCH v3 2/4] KVM: arm64: vgic-its: Clear DTE when MAPD unmaps a device From: Jing Zhang To: KVM , KVMARM , ARMLinux , Marc Zyngier , Oliver Upton , Joey Gouly , Zenghui Yu , Suzuki K Poulose , Kunkun Jiang Cc: Paolo Bonzini , Andre Przywara , Colton Lewis , Raghavendra Rao Ananta , Shusen Li , Jing Zhang X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241106_003045_134002_AF5E5134 X-CRM114-Status: GOOD ( 15.22 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Kunkun Jiang vgic_its_save_device_tables will traverse its->device_list to save DTE for each device. vgic_its_restore_device_tables will traverse each entry of device table and check if it is valid. Restore if valid. But when MAPD unmaps a device, it does not invalidate the corresponding DTE. In the scenario of continuous saves and restores, there may be a situation where a device's DTE is not saved but is restored. This is unreasonable and may cause restore to fail. This patch clears the corresponding DTE when MAPD unmaps a device. Co-developed-by: Shusen Li Signed-off-by: Shusen Li Signed-off-by: Kunkun Jiang Signed-off-by: Jing Zhang --- arch/arm64/kvm/vgic/vgic-its.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index 2381bc5ce544..7c57c7c6fbff 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -1140,8 +1140,9 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its, u8 num_eventid_bits = its_cmd_get_size(its_cmd); gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd); struct its_device *device; + gpa_t gpa; - if (!vgic_its_check_id(its, its->baser_device_table, device_id, NULL)) + if (!vgic_its_check_id(its, its->baser_device_table, device_id, &gpa)) return E_ITS_MAPD_DEVICE_OOR; if (valid && num_eventid_bits > VITS_TYPER_IDBITS) @@ -1161,8 +1162,17 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its, * The spec does not say whether unmapping a not-mapped device * is an error, so we are done in any case. */ - if (!valid) + if (!valid) { + struct kvm *kvm = its->dev->kvm; + int dte_esz = vgic_its_get_abi(its)->dte_esz; + u64 val = 0; + + if (KVM_BUG_ON(dte_esz != sizeof(val), kvm)) + return -EINVAL; + + vgic_write_guest_lock(kvm, gpa, &val, dte_esz); return 0; + } device = vgic_its_alloc_device(its, device_id, itt_addr, num_eventid_bits); From patchwork Wed Nov 6 08:30:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jing Zhang X-Patchwork-Id: 13864101 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 03C13D29FB3 for ; Wed, 6 Nov 2024 08:38:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:Cc:To:From: Subject:Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=E9OqfUOMAqbpcWXjOPS3HeNW6CbTb26wA4+Tx2JMJgo=; b=heUmFxkg1fwr50qm8uPBOsMVQb nwsi03FoRVLBKqW7irCL9XYVFJSzYRdRKHMyJ4aTD7T/z6uQUBCO84ey2HxQ6M++4c+jqZyfMd3v3 wTw/tvH2Bv2TFfzWZDKT9nx6q1u1NPC5WXnoW+shtD7844aLzNRHYUfXcHihOmaeHYl2BFxioh3Kc lq+jfSi20wzIm2lgmvfnDeZkggK1Ik8QAaDj4rYDcInA76GzHI3WE4ReZ2gPrg02VsenwI+y+TLTr BwY/d979y418nUqByqYLYRPwonApf4jHSz4nWy7lfgE3kSFFgiGWcqv/i8m0r1c5xW6XQ1xBP0EVa 8lkeac1Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1t8bXv-00000002JsD-24mO; Wed, 06 Nov 2024 08:37:47 +0000 Received: from mail-pg1-x549.google.com ([2607:f8b0:4864:20::549]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1t8bR8-00000002ISY-1X07 for linux-arm-kernel@lists.infradead.org; Wed, 06 Nov 2024 08:30:47 +0000 Received: by mail-pg1-x549.google.com with SMTP id 41be03b00d2f7-7e6cc094c2fso583510a12.1 for ; Wed, 06 Nov 2024 00:30:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1730881845; x=1731486645; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=E9OqfUOMAqbpcWXjOPS3HeNW6CbTb26wA4+Tx2JMJgo=; b=2BYExZQREs7TGkDYsfJvlIzXZqqX7Jep8Ng53GMFdMGPAISNTwnx+Lia5YqTIjoIOm rV1Rr7sPvLpGA2u8erqTmWWuHUKJ1TFcSsjqpy6y5DaE9w7OvuHkpEyMiEam2IMYg/Jr H0sY5C1wSmeX4RthRzbzrerZywUvRvJ+jK3gLAZ1znbTpY/wJoHHIxw6qHF2ME+xOR2Q q1qhJSMlHoaWPNbXQyVj8YYWFtx8o7ab5A36JmIFWHSuFPA2z/XbJTaMVCq8pbqxJ9p1 +qYZV+l0Dv+tMLKjfdIMZEZ8piVC2Pu3EbgOBpd3MnBTvqv80jVpSkiYKl9PjlQ/rR3n VzEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730881845; x=1731486645; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=E9OqfUOMAqbpcWXjOPS3HeNW6CbTb26wA4+Tx2JMJgo=; b=Ix9siBPLFwiHcAN0+VRhIRbuLaE5K0q9jz2aTUWfexDw2lx6Bx7+SU74qgeV1QEuXD 0HPcbsYGs90XDeznMDSnND3sZpEmadV+uFBSzMOmYJkJv2l/Ml6OtSbIhz3YINYDWKHd Pp640vFlT4r4CmPcxFWgm/FiE5FSA6fXvaTK++cSW9QJ4kDo94VIHNgRU3KOoVSoIEoG FVZ0xRK6FqUBw+f1Mq1/soMRYDXaVULFlDwcVHefnU1TMOUW+xKDzYA2JBQSlSUnRbz6 eISy6BqhAu7f3M79USLKkpAzRgDkyJ5ltQwaAKMu8KgJ0k3UtHs+qYTZw9MysUiItOTi 9ebQ== X-Forwarded-Encrypted: i=1; AJvYcCXdaA1eAj43pqMtv+Wc+k4V+SCTJsIXdmpVwRbL0jU8hnUdV9lj6yKiqvKSJmsNUl/GXB1tQiOWA9UHT96+w0NJ@lists.infradead.org X-Gm-Message-State: AOJu0Yzrr3EfUpoYsX6Rxo9box4YLG6XMdzLOGj0OFo1sD8Y3+2HBvbu z5yuDMo7CsXK7fT1MomAirHrCIlMS8ny3xr4ICWooZDL2yRS+vpo9Kl+NEiA7YHGhP8tHztL8lT nN5y9nT8Ui7L5jHl6ysqmvw== X-Google-Smtp-Source: AGHT+IEIX/6hVDGOmxY1iHcCV7jeryOMcpYeUgvJ4PGHYdhp40R/dK9bTBilzwLgwCsXlLEKi3MnqQQmu9vQlZaSIw== X-Received: from jgzg.c.googlers.com ([fda3:e722:ac3:cc00:36:e7b8:ac13:c96f]) (user=jingzhangos job=sendgmr) by 2002:a17:902:b686:b0:20b:8d7d:fe08 with SMTP id d9443c01a7336-2116c9c51demr90245ad.6.1730881844849; Wed, 06 Nov 2024 00:30:44 -0800 (PST) Date: Wed, 6 Nov 2024 00:30:34 -0800 In-Reply-To: <20241106083035.2813799-1-jingzhangos@google.com> Mime-Version: 1.0 References: <20241106083035.2813799-1-jingzhangos@google.com> X-Mailer: git-send-email 2.47.0.277.g8800431eea-goog Message-ID: <20241106083035.2813799-4-jingzhangos@google.com> Subject: [PATCH v3 3/4] KVM: arm64: vgic-its: Clear ITE when DISCARD frees an ITE From: Jing Zhang To: KVM , KVMARM , ARMLinux , Marc Zyngier , Oliver Upton , Joey Gouly , Zenghui Yu , Suzuki K Poulose , Kunkun Jiang Cc: Paolo Bonzini , Andre Przywara , Colton Lewis , Raghavendra Rao Ananta , Shusen Li , Jing Zhang X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241106_003046_440020_B8A5D6AC X-CRM114-Status: GOOD ( 12.48 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Kunkun Jiang When DISCARD frees an ITE, it does not invalidate the corresponding ITE. In the scenario of continuous saves and restores, there may be a situation where an ITE is not saved but is restored. This is unreasonable and may cause restore to fail. This patch clears the corresponding ITE when DISCARD frees an ITE. Signed-off-by: Kunkun Jiang Signed-off-by: Jing Zhang --- arch/arm64/kvm/vgic/vgic-its.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index 7c57c7c6fbff..df8408ceae30 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -782,6 +782,10 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its, ite = find_ite(its, device_id, event_id); if (ite && its_is_collection_mapped(ite->collection)) { + struct its_device *device = find_its_device(its, device_id); + int ite_esz = vgic_its_get_abi(its)->ite_esz; + gpa_t gpa = device->itt_addr + ite->event_id * ite_esz; + u64 val = 0; /* * Though the spec talks about removing the pending state, we * don't bother here since we clear the ITTE anyway and the @@ -790,6 +794,11 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its, vgic_its_invalidate_cache(its); its_free_ite(kvm, ite); + + if (KVM_BUG_ON(ite_esz != sizeof(val), kvm)) + return -EINVAL; + + vgic_write_guest_lock(kvm, gpa, &val, ite_esz); return 0; } From patchwork Wed Nov 6 08:30:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jing Zhang X-Patchwork-Id: 13864114 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4651DD29FB8 for ; Wed, 6 Nov 2024 08:39:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:Cc:To:From: Subject:Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=IhYU6xsoZSmywlyu/tpDX/Oy0BRxtDtDnKJQvaCFt88=; b=pzgRUkGgp8lYplh1pNZipl410m KxVBvALkr3aw7tYtdFLxtMheShtjO0G6ZB3tEyK62TXWCm11RND8jgng8JjOQ2uljHvYZmxCkKtQv V6x+h1OV5z5TRv1CtXROyIVhtcpX0VKO2vwZW4KKPag7r2H3447Z8aG0gp/hJDh79YGUSEWZOs20Y fVUCK8hwbpNJzHaw/2Q/AwQYxbVifhaUgELgNfDgQLRYwuBAxYxq2pKQPzEIVZoO43cVc//MeH3+c xXkM4lGPLlFIiHI8BJQIzfPYh+7svBx5L0gj9NnyCahk3VwxUaFq7B6O+co0NwL74DaIh5qAAewX7 qiXOYVbA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1t8bZd-00000002KEK-3k7I; Wed, 06 Nov 2024 08:39:34 +0000 Received: from mail-yw1-x114a.google.com ([2607:f8b0:4864:20::114a]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1t8bRA-00000002ITH-0VZe for linux-arm-kernel@lists.infradead.org; Wed, 06 Nov 2024 08:30:50 +0000 Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-6e9d6636498so123407897b3.2 for ; Wed, 06 Nov 2024 00:30:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1730881847; x=1731486647; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=IhYU6xsoZSmywlyu/tpDX/Oy0BRxtDtDnKJQvaCFt88=; b=C76Uyxxf49Q4Job/R4S3lw0PQB+Bq0B3M+QlMfIsQdTeHhOWqKKg3HNo8BKEz+slLA DYjiURjqWEY88M6MgTYr5zDpMknrwDgBM38IYhQTtEGTvInrycD6r6bgDDuPWuj/2E7Z eAbk3yu2i8jlmfH3hfIFNKVBLy22y+CpwbVb8eGVAaraqQ+a21oLr67zp/on2Xub4cqF XRkSSkH+LZRAVbhkB0X7gGdRcu2/2geYx+kKgRtT5T+naf0HJzvXnzE+Ci5l0T7dRIAi e84A2lJ9Zuzra5Xd0uyIz7qZ2dRY8ILoENlPpbY+W89gD/Wkoqx3Q+hXl5fhcGWtghGj ihSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730881847; x=1731486647; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=IhYU6xsoZSmywlyu/tpDX/Oy0BRxtDtDnKJQvaCFt88=; b=LfD4w9QoOeSwgMiK4/K3xVSIfR6xli8y4Kf7coEJ7mUYBiK7X6QSXeWNTugPfpsjiS EStPKLOAve/N3eMzMz2RLwC9/Z17PPYJA4Y8m3RIab0LaalxwWsi3MBt0iG+jxX4kjYq emwSBEy55c/2IJ26HVcq2H0b8X60dXbKkxhPmJnMbcSfsbURy5RPs2ZMJLMDoEVPOwVC JatbSjL400GXQfGS9mazgPwagnA+oIQLaMYQ0qU1a/PjL4Icrmc5YbEJYcjjGSgXsPk5 96z3e02TCD/N7JILyfhBWejWxuFoKfne5EfMnQ1ps3g1VXvmkiuwlcxTGx9BAf8sTG9v V4Kg== X-Forwarded-Encrypted: i=1; AJvYcCVCokxPdAeopzJ0ob8gvtJ23tHdJS62MfyUVTNofDezv5JzMc5QXxGwrfs1b315qKuefOHX8rRmR9G+SIPgygcX@lists.infradead.org X-Gm-Message-State: AOJu0YzcX4GjpL6zEvs7BlOAnBdeQLKgwGWFeIBsj7xZZtgZ7/i/niDw u1LIxoi1gcklingwuTKQXrn/2tplPB1XkdSEXr4ifSNYboko+uig7nPpW0PTHrsXEyqNCcH12X8 r5Q1KrK/7iuB2fBfxgClUvA== X-Google-Smtp-Source: AGHT+IHlYun/LypTmpSFvCKkM7CvBv/fUf1NqmC8c4ENStSnDu5Gzo+yAW+MOXAKjWRJ5uTjGFQvvHlkpBKFLYMkPw== X-Received: from jgzg.c.googlers.com ([fda3:e722:ac3:cc00:36:e7b8:ac13:c96f]) (user=jingzhangos job=sendgmr) by 2002:a05:690c:620a:b0:68d:52a1:be9 with SMTP id 00721157ae682-6ea5231f6c3mr654667b3.1.1730881846553; Wed, 06 Nov 2024 00:30:46 -0800 (PST) Date: Wed, 6 Nov 2024 00:30:35 -0800 In-Reply-To: <20241106083035.2813799-1-jingzhangos@google.com> Mime-Version: 1.0 References: <20241106083035.2813799-1-jingzhangos@google.com> X-Mailer: git-send-email 2.47.0.277.g8800431eea-goog Message-ID: <20241106083035.2813799-5-jingzhangos@google.com> Subject: [PATCH v3 4/4] KVM: selftests: aarch64: Test VGIC ITS tables save/restore From: Jing Zhang To: KVM , KVMARM , ARMLinux , Marc Zyngier , Oliver Upton , Joey Gouly , Zenghui Yu , Suzuki K Poulose , Kunkun Jiang Cc: Paolo Bonzini , Andre Przywara , Colton Lewis , Raghavendra Rao Ananta , Shusen Li , Jing Zhang X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241106_003048_209279_5BA47D33 X-CRM114-Status: GOOD ( 24.92 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add a selftest to verify the correctness of the VGIC ITS mappings after the save/restore operations (KVM_DEV_ARM_ITS_SAVE_TABLES / KVM_DEV_ARM_ITS_RESTORE_TABLES). Also calculate the time spending on save/restore operations. This test uses some corner cases to capture the save/restore bugs. It will be used to verify the future incoming changes for the VGIC ITS tables save/restore. To capture the "Invalid argument (-22)" error, run the test without any option. To capture the wrong/lost mappings, run the test with '-s' option. Since the VGIC ITS save/restore bug is caused by orphaned DTE/ITE entries, if we run the test with '-c' option whih clears the tables before the save operation, the test will complete successfully. Signed-off-by: Jing Zhang --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/aarch64/vgic_its_tables.c | 566 ++++++++++++++++++ .../kvm/include/aarch64/gic_v3_its.h | 3 +- .../testing/selftests/kvm/include/kvm_util.h | 4 +- .../selftests/kvm/lib/aarch64/gic_v3_its.c | 24 +- 5 files changed, 592 insertions(+), 6 deletions(-) create mode 100644 tools/testing/selftests/kvm/aarch64/vgic_its_tables.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 156fbfae940f..9cba573c23f3 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -163,6 +163,7 @@ TEST_GEN_PROGS_aarch64 += aarch64/smccc_filter TEST_GEN_PROGS_aarch64 += aarch64/vcpu_width_config TEST_GEN_PROGS_aarch64 += aarch64/vgic_init TEST_GEN_PROGS_aarch64 += aarch64/vgic_irq +TEST_GEN_PROGS_aarch64 += aarch64/vgic_its_tables TEST_GEN_PROGS_aarch64 += aarch64/vgic_lpi_stress TEST_GEN_PROGS_aarch64 += aarch64/vpmu_counter_access TEST_GEN_PROGS_aarch64 += aarch64/no-vgic-v3 diff --git a/tools/testing/selftests/kvm/aarch64/vgic_its_tables.c b/tools/testing/selftests/kvm/aarch64/vgic_its_tables.c new file mode 100644 index 000000000000..4e105163dec3 --- /dev/null +++ b/tools/testing/selftests/kvm/aarch64/vgic_its_tables.c @@ -0,0 +1,566 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * vgic_its_tables - Sanity and performance test for VGIC ITS tables + * save/restore. + * + * Copyright (c) 2024 Google LLC + */ + +#include +#include +#include +#include + +#include "kvm_util.h" +#include "gic.h" +#include "gic_v3.h" +#include "gic_v3_its.h" +#include "processor.h" +#include "ucall.h" +#include "vgic.h" +#include "kselftest.h" + + +#define GIC_LPI_OFFSET 8192 +#define TEST_MEMSLOT_INDEX 1 +#define TABLE_SIZE SZ_64K +#define DEFAULT_NR_L2 4ULL +#define DTE_SIZE 8ULL +#define ITE_SIZE 8ULL +#define NR_EVENTS (TABLE_SIZE / ITE_SIZE) +/* We only have 64K PEND/PROP tables */ +#define MAX_NR_L2 ((TABLE_SIZE - GIC_LPI_OFFSET) * DTE_SIZE / TABLE_SIZE) + +static vm_paddr_t gpa_base; + +static struct kvm_vm *vm; +static struct kvm_vcpu *vcpu; +static int gic_fd, its_fd; +static u32 collection_id = 0; + +struct event_id_block { + u32 start; + u32 size; +}; + +static struct mappings_tracker { + struct event_id_block *devices; + struct event_id_block *devices_va; +} mtracker; + +static struct test_data { + vm_paddr_t l1_device_table; + vm_paddr_t l2_device_tables; + vm_paddr_t collection_table; + vm_paddr_t cmdq_base; + void *cmdq_base_va; + vm_paddr_t itt_tables; + + vm_paddr_t lpi_prop_table; + vm_paddr_t lpi_pend_tables; + + int control_cmd; + bool clear_before_save; + bool same_coll_id; + size_t nr_l2_tables; + size_t nr_devices; +} td = { + .clear_before_save = false, + .same_coll_id = false, + .nr_l2_tables = DEFAULT_NR_L2, + .nr_devices = DEFAULT_NR_L2 * TABLE_SIZE / DTE_SIZE, +}; + +static void guest_its_mappings_clear(void) +{ + memset((void *)td.l2_device_tables, 0, TABLE_SIZE * td.nr_l2_tables); + memset((void *)td.collection_table, 0, TABLE_SIZE); + memset((void *)td.itt_tables, 0, td.nr_devices * TABLE_SIZE); +} + +static void guest_its_unmap_all(bool update_tracker) +{ + u32 device_id, event_id; + + for (device_id = 0; device_id < td.nr_devices; device_id++) { + vm_paddr_t itt_base = td.itt_tables + (device_id * TABLE_SIZE); + u32 start_id = mtracker.devices[device_id].start; + u32 end_id = start_id + mtracker.devices[device_id].size; + + for (event_id = start_id; event_id < end_id ; event_id++) + its_send_discard_cmd(td.cmdq_base_va, + device_id, event_id); + + if (end_id - start_id > 0) + its_send_mapd_cmd(td.cmdq_base_va, device_id, + itt_base, TABLE_SIZE, false); + + if (update_tracker) { + mtracker.devices[device_id].start = 0; + mtracker.devices[device_id].size = 0; + } + + } + + for (u32 i= 0; i <= collection_id; i++) + its_send_mapc_cmd(td.cmdq_base_va, 0, i, false); +} + +static void guest_its_map_single_event(u32 device_id, u32 event_id, u32 coll_id) +{ + u32 intid = GIC_LPI_OFFSET; + + guest_its_unmap_all(true); + + its_send_mapc_cmd(td.cmdq_base_va, guest_get_vcpuid(), coll_id, true); + its_send_mapd_cmd(td.cmdq_base_va, device_id, + td.itt_tables + (device_id * TABLE_SIZE), TABLE_SIZE, true); + its_send_mapti_cmd(td.cmdq_base_va, device_id, + event_id, coll_id, intid); + + + mtracker.devices[device_id].start = event_id; + mtracker.devices[device_id].size = 1; +} + +static void guest_its_map_event_per_device(u32 event_id, u32 coll_id) +{ + u32 device_id, intid = GIC_LPI_OFFSET; + + guest_its_unmap_all(true); + + its_send_mapc_cmd(td.cmdq_base_va, guest_get_vcpuid(), coll_id, true); + + for (device_id = 0; device_id < td.nr_devices; device_id++) { + vm_paddr_t itt_base = td.itt_tables + (device_id * TABLE_SIZE); + + its_send_mapd_cmd(td.cmdq_base_va, device_id, + itt_base, TABLE_SIZE, true); + + its_send_mapti_cmd(td.cmdq_base_va, device_id, + event_id, coll_id, intid++); + + mtracker.devices[device_id].start = event_id; + mtracker.devices[device_id].size = 1; + + } +} + +static void guest_setup_gic(void) +{ + u32 cpuid = guest_get_vcpuid(); + + gic_init(GIC_V3, 1); + gic_rdist_enable_lpis(td.lpi_prop_table, TABLE_SIZE, + td.lpi_pend_tables + (cpuid * TABLE_SIZE)); + + guest_its_mappings_clear(); + + its_init(td.collection_table, TABLE_SIZE, + td.l1_device_table, TABLE_SIZE, + td.cmdq_base, TABLE_SIZE, true); +} + +enum { + GUEST_EXIT, + MAP_INIT, + MAP_INIT_DONE, + MAP_DONE, + PREPARE_FOR_SAVE, + PREPARE_DONE, + MAP_EMPTY, + MAP_SINGLE_EVENT_FIRST, + MAP_SINGLE_EVENT_LAST, + MAP_FIRST_EVENT_PER_DEVICE, + MAP_LAST_EVENT_PER_DEVICE, +}; + +static void guest_code(size_t nr_lpis) +{ + int cmd; + + guest_setup_gic(); + GUEST_SYNC1(MAP_INIT_DONE); + + while ((cmd = READ_ONCE(td.control_cmd)) != GUEST_EXIT) { + switch (cmd) { + case MAP_INIT: + guest_its_unmap_all(true); + if (td.clear_before_save) + guest_its_mappings_clear(); + GUEST_SYNC1(MAP_INIT_DONE); + break; + case PREPARE_FOR_SAVE: + its_init(td.collection_table, TABLE_SIZE, + td.l1_device_table, TABLE_SIZE, + td.cmdq_base, TABLE_SIZE, true); + GUEST_SYNC1(PREPARE_DONE); + break; + case MAP_EMPTY: + guest_its_mappings_clear(); + GUEST_SYNC1(MAP_DONE); + break; + case MAP_SINGLE_EVENT_FIRST: + guest_its_map_single_event(1, 1, collection_id); + if (!td.same_coll_id) + collection_id++; + GUEST_SYNC1(MAP_DONE); + break; + case MAP_SINGLE_EVENT_LAST: + guest_its_map_single_event(td.nr_devices - 2, NR_EVENTS - 2, + collection_id); + if (!td.same_coll_id) + collection_id++; + GUEST_SYNC1(MAP_DONE); + break; + case MAP_FIRST_EVENT_PER_DEVICE: + guest_its_map_event_per_device(2, collection_id); + if (!td.same_coll_id) + collection_id++; + GUEST_SYNC1(MAP_DONE); + break; + case MAP_LAST_EVENT_PER_DEVICE: + guest_its_map_event_per_device(NR_EVENTS - 3, + collection_id); + if (!td.same_coll_id) + collection_id++; + GUEST_SYNC1(MAP_DONE); + break; + default: + break; + } + } + + GUEST_DONE(); +} + +static void setup_memslot(void) +{ + size_t pages; + size_t sz; + + /* + * For the ITS: + * - A single l1 level device table + * - td.nr_l2_tables l2 level device tables + * - A single level collection table + * - The command queue + * - An ITT for each device + */ + sz = (3 + td.nr_l2_tables + td.nr_devices) * TABLE_SIZE; + + /* + * For the redistributors: + * - A shared LPI configuration table + * - An LPI pending table for the vCPU + */ + sz += 2 * TABLE_SIZE; + + /* + * For the mappings tracker + */ + sz += sizeof(*mtracker.devices) * td.nr_devices; + + pages = sz / vm->page_size; + gpa_base = ((vm_compute_max_gfn(vm) + 1) * vm->page_size) - sz; + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, gpa_base, + TEST_MEMSLOT_INDEX, pages, 0); +} + +#define KVM_ITS_L1E_VALID_MASK BIT_ULL(63) +#define KVM_ITS_L1E_ADDR_MASK GENMASK_ULL(51, 16) + +static void setup_test_data(void) +{ + size_t pages_per_table = vm_calc_num_guest_pages(vm->mode, TABLE_SIZE); + size_t pages_mt = sizeof(*mtracker.devices) * td.nr_devices / vm->page_size; + + mtracker.devices = (void *)vm_phy_pages_alloc(vm, pages_mt, gpa_base, + TEST_MEMSLOT_INDEX); + virt_map(vm, (vm_paddr_t)mtracker.devices, + (vm_paddr_t)mtracker.devices, pages_mt); + mtracker.devices_va = (void *)addr_gpa2hva(vm, (vm_paddr_t)mtracker.devices); + + td.l2_device_tables = vm_phy_pages_alloc(vm, + pages_per_table * td.nr_l2_tables, + gpa_base, TEST_MEMSLOT_INDEX); + td.l1_device_table = vm_phy_pages_alloc(vm, pages_per_table, + gpa_base, + TEST_MEMSLOT_INDEX); + td.collection_table = vm_phy_pages_alloc(vm, pages_per_table, + gpa_base, + TEST_MEMSLOT_INDEX); + td.itt_tables = vm_phy_pages_alloc(vm, pages_per_table * td.nr_devices, + gpa_base, TEST_MEMSLOT_INDEX); + td.lpi_prop_table = vm_phy_pages_alloc(vm, pages_per_table, + gpa_base, TEST_MEMSLOT_INDEX); + td.lpi_pend_tables = vm_phy_pages_alloc(vm, pages_per_table, + gpa_base, TEST_MEMSLOT_INDEX); + td.cmdq_base = vm_phy_pages_alloc(vm, pages_per_table, gpa_base, + TEST_MEMSLOT_INDEX); + + u64 *l1_tbl = addr_gpa2hva(vm, td.l1_device_table); + for (int i = 0; i < td.nr_l2_tables; i++) { + u64 l2_addr = ((u64)td.l2_device_tables + i * TABLE_SIZE); + *(l1_tbl + i) = cpu_to_le64(l2_addr | KVM_ITS_L1E_VALID_MASK); + } + + virt_map(vm, td.l2_device_tables, td.l2_device_tables, + pages_per_table * td.nr_l2_tables); + virt_map(vm, td.l1_device_table, + td.l1_device_table, pages_per_table); + virt_map(vm, td.collection_table, + td.collection_table, pages_per_table); + virt_map(vm, td.itt_tables, + td.itt_tables, pages_per_table * td.nr_devices); + virt_map(vm, td.cmdq_base, td.cmdq_base, pages_per_table); + td.cmdq_base_va = (void *)td.cmdq_base; + + sync_global_to_guest(vm, mtracker); + sync_global_to_guest(vm, td); +} + +static void setup_gic(void) +{ + gic_fd = vgic_v3_setup(vm, 1, 64); + __TEST_REQUIRE(gic_fd >= 0, "Failed to create GICv3"); + + its_fd = vgic_its_setup(vm); +} + +static bool is_mapped(u32 device_id, u32 event_id) +{ + vm_paddr_t db_addr = GITS_BASE_GPA + GITS_TRANSLATER; + + struct kvm_msi msi = { + .address_lo = db_addr, + .address_hi = db_addr >> 32, + .data = event_id, + .devid = device_id, + .flags = KVM_MSI_VALID_DEVID, + }; + + /* + * KVM_SIGNAL_MSI returns 1 if the MSI wasn't 'blocked' by the VM, + * which for arm64 implies having a valid translation in the ITS. + */ + return __vm_ioctl(vm, KVM_SIGNAL_MSI, &msi); +} + +static bool restored_mappings_sanity_check(void) +{ + u64 lost_count = 0, wrong_count = 0; + bool pass = true; + + sync_global_from_guest(vm, mtracker); + + ksft_print_msg("\tChecking restored ITS mappings ...\n"); + for(u32 dev_id = 0; dev_id < td.nr_devices; dev_id++) { + u32 start_id = mtracker.devices_va[dev_id].start; + u32 end_id = start_id + mtracker.devices_va[dev_id].size; + + for (u32 eid = 0; eid < NR_EVENTS; eid++) { + bool save_mapped = eid >= start_id && eid < end_id; + bool restore_mapped = is_mapped(dev_id, eid); + + if(save_mapped && !restore_mapped && ++lost_count < 6) { + ksft_print_msg("\t\tMapping lost for device:%u, event:%u\n", + dev_id, eid); + pass = false; + } else if (!save_mapped && restore_mapped && ++wrong_count < 6) { + ksft_print_msg("\t\tWrong mapping from device:%u, event:%u\n", + dev_id, eid); + pass = false; + } + /* + * For test purpose, we only use the first and last 3 events + * per device. + */ + if (eid == 2) + eid = NR_EVENTS - 4; + } + if (lost_count > 5 || wrong_count > 5) { + ksft_print_msg("\tThere are more lost/wrong mappings found.\n"); + break; + } + } + + return pass; +} + +static void run_its_tables_save_restore_test(int test_cmd) +{ + struct timespec start, delta; + struct ucall uc; + bool done = false; + double duration; + bool pass = true; + + write_guest_global(vm, td.control_cmd, MAP_INIT); + while (!done) { + vcpu_run(vcpu); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_SYNC: + switch (uc.args[0]) { + case MAP_INIT_DONE: + write_guest_global(vm, td.control_cmd, test_cmd); + break; + case MAP_DONE: + clock_gettime(CLOCK_MONOTONIC, &start); + + kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_ITS_SAVE_TABLES, NULL); + + delta = timespec_elapsed(start); + duration = (double)delta.tv_sec * USEC_PER_SEC; + duration += (double)delta.tv_nsec / NSEC_PER_USEC; + ksft_print_msg("\tITS tables save time: %.2f (us)\n", duration); + + /* Prepare for restoring */ + kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_ITS_CTRL_RESET, NULL); + write_guest_global(vm, td.control_cmd, PREPARE_FOR_SAVE); + break; + case PREPARE_DONE: + done = true; + break; + } + break; + case UCALL_DONE: + done = true; + break; + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + break; + default: + TEST_FAIL("Unknown ucall: %lu", uc.cmd); + } + } + + + clock_gettime(CLOCK_MONOTONIC, &start); + + int ret = __kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_ITS_RESTORE_TABLES, NULL); + if (ret) { + ksft_print_msg("\t"); + ksft_print_msg(KVM_IOCTL_ERROR(KVM_SET_DEVICE_ATTR, ret)); + ksft_print_msg("\n"); + ksft_print_msg("\tFailed to restore ITS tables.\n"); + pass = false; + } + + delta = timespec_elapsed(start); + duration = (double)delta.tv_sec * USEC_PER_SEC; + duration += (double)delta.tv_nsec / NSEC_PER_USEC; + ksft_print_msg("\tITS tables restore time: %.2f (us)\n", duration); + + if (restored_mappings_sanity_check() && pass) + ksft_test_result_pass("*** PASSED ***\n"); + else + ksft_test_result_fail("*** FAILED ***\n"); + +} + +static void setup_vm(void) +{ + vm = __vm_create_with_one_vcpu(&vcpu, 1024*1024, guest_code); + + setup_memslot(); + + setup_gic(); + + setup_test_data(); +} + +static void destroy_vm(void) +{ + close(its_fd); + close(gic_fd); + kvm_vm_free(vm); +} + +static void run_test(int test_cmd) +{ + pr_info("------------------------------------------------------------------------------\n"); + switch (test_cmd) { + case MAP_EMPTY: + pr_info("Test ITS save/restore with empty mapping\n"); + break; + case MAP_SINGLE_EVENT_FIRST: + pr_info("Test ITS save/restore with one mapping (device:1, event:1)\n"); + break; + case MAP_SINGLE_EVENT_LAST: + pr_info("Test ITS save/restore with one mapping (device:%zu, event:%llu)\n", + td.nr_devices - 2, NR_EVENTS - 2); + break; + case MAP_FIRST_EVENT_PER_DEVICE: + pr_info("Test ITS save/restore with one small event per device (device:[0-%zu], event:2)\n", + td.nr_devices - 1); + break; + case MAP_LAST_EVENT_PER_DEVICE: + pr_info("Test ITS save/restore with one big event per device (device:[0-%zu], event:%llu)\n", + td.nr_devices - 1, NR_EVENTS - 3); + break; + } + pr_info("------------------------------------------------------------------------------\n"); + + run_its_tables_save_restore_test(test_cmd); + + ksft_print_msg("\n"); +} + +static void pr_usage(const char *name) +{ + pr_info("%s -c -s -h\n", name); + pr_info(" -c:\tclear ITS tables entries before saving\n"); + pr_info(" -s:\tuse the same collection ID for all mappings\n"); + pr_info(" -n:\tnumber of L2 device tables (default: %zu, range: [1 - %llu])\n", + td.nr_l2_tables, MAX_NR_L2); +} + +int main(int argc, char **argv) +{ + int c; + + while ((c = getopt(argc, argv, "hcsn:")) != -1) { + switch (c) { + case 'c': + td.clear_before_save = true; + break; + case 's': + td.same_coll_id = true; + break; + case 'n': + td.nr_l2_tables = atoi(optarg); + if (td.nr_l2_tables > 0 && td.nr_l2_tables <= MAX_NR_L2) { + td.nr_devices = td.nr_l2_tables * TABLE_SIZE / DTE_SIZE; + break; + } + pr_info("The specified number of L2 device tables is out of range!\n"); + case 'h': + default: + pr_usage(argv[0]); + return 1; + } + } + + ksft_print_header(); + + setup_vm(); + + ksft_set_plan(5); + + run_test(MAP_EMPTY); + run_test(MAP_SINGLE_EVENT_FIRST); + run_test(MAP_SINGLE_EVENT_LAST); + run_test(MAP_FIRST_EVENT_PER_DEVICE); + run_test(MAP_LAST_EVENT_PER_DEVICE); + + destroy_vm(); + + ksft_finished(); + + return 0; +} diff --git a/tools/testing/selftests/kvm/include/aarch64/gic_v3_its.h b/tools/testing/selftests/kvm/include/aarch64/gic_v3_its.h index 3722ed9c8f96..ecf1eb955471 100644 --- a/tools/testing/selftests/kvm/include/aarch64/gic_v3_its.h +++ b/tools/testing/selftests/kvm/include/aarch64/gic_v3_its.h @@ -7,7 +7,7 @@ void its_init(vm_paddr_t coll_tbl, size_t coll_tbl_sz, vm_paddr_t device_tbl, size_t device_tbl_sz, - vm_paddr_t cmdq, size_t cmdq_size); + vm_paddr_t cmdq, size_t cmdq_size, bool indirect_device_tbl); void its_send_mapd_cmd(void *cmdq_base, u32 device_id, vm_paddr_t itt_base, size_t itt_size, bool valid); @@ -15,5 +15,6 @@ void its_send_mapc_cmd(void *cmdq_base, u32 vcpu_id, u32 collection_id, bool val void its_send_mapti_cmd(void *cmdq_base, u32 device_id, u32 event_id, u32 collection_id, u32 intid); void its_send_invall_cmd(void *cmdq_base, u32 collection_id); +void its_send_discard_cmd(void *cmdq_base, u32 device_id, u32 event_id); #endif // __SELFTESTS_GIC_V3_ITS_H__ diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h index bc7c242480d6..3abe06ad1f85 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -27,7 +27,9 @@ #define KVM_DEV_PATH "/dev/kvm" #define KVM_MAX_VCPUS 512 -#define NSEC_PER_SEC 1000000000L +#define NSEC_PER_USEC 1000L +#define USEC_PER_SEC 1000000L +#define NSEC_PER_SEC 1000000000L struct userspace_mem_region { struct kvm_userspace_memory_region2 region; diff --git a/tools/testing/selftests/kvm/lib/aarch64/gic_v3_its.c b/tools/testing/selftests/kvm/lib/aarch64/gic_v3_its.c index 09f270545646..cd3c65d762d2 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/gic_v3_its.c +++ b/tools/testing/selftests/kvm/lib/aarch64/gic_v3_its.c @@ -52,7 +52,8 @@ static unsigned long its_find_baser(unsigned int type) return -1; } -static void its_install_table(unsigned int type, vm_paddr_t base, size_t size) +static void its_install_table(unsigned int type, vm_paddr_t base, + size_t size, bool indirect) { unsigned long offset = its_find_baser(type); u64 baser; @@ -64,6 +65,9 @@ static void its_install_table(unsigned int type, vm_paddr_t base, size_t size) GITS_BASER_RaWaWb | GITS_BASER_VALID; + if (indirect) + baser |= GITS_BASER_INDIRECT; + its_write_u64(offset, baser); } @@ -82,12 +86,13 @@ static void its_install_cmdq(vm_paddr_t base, size_t size) void its_init(vm_paddr_t coll_tbl, size_t coll_tbl_sz, vm_paddr_t device_tbl, size_t device_tbl_sz, - vm_paddr_t cmdq, size_t cmdq_size) + vm_paddr_t cmdq, size_t cmdq_size, bool indirect_device_tbl) { u32 ctlr; - its_install_table(GITS_BASER_TYPE_COLLECTION, coll_tbl, coll_tbl_sz); - its_install_table(GITS_BASER_TYPE_DEVICE, device_tbl, device_tbl_sz); + its_install_table(GITS_BASER_TYPE_COLLECTION, coll_tbl, coll_tbl_sz, false); + its_install_table(GITS_BASER_TYPE_DEVICE, device_tbl, device_tbl_sz, + indirect_device_tbl); its_install_cmdq(cmdq, cmdq_size); ctlr = its_read_u32(GITS_CTLR); @@ -237,6 +242,17 @@ void its_send_mapti_cmd(void *cmdq_base, u32 device_id, u32 event_id, its_send_cmd(cmdq_base, &cmd); } +void its_send_discard_cmd(void *cmdq_base, u32 device_id, u32 event_id) +{ + struct its_cmd_block cmd = {}; + + its_encode_cmd(&cmd, GITS_CMD_DISCARD); + its_encode_devid(&cmd, device_id); + its_encode_event_id(&cmd, event_id); + + its_send_cmd(cmdq_base, &cmd); +} + void its_send_invall_cmd(void *cmdq_base, u32 collection_id) { struct its_cmd_block cmd = {};