From nobody Wed Apr 8 04:25:14 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B599C32774 for ; Wed, 24 Aug 2022 03:22:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234284AbiHXDV7 (ORCPT ); Tue, 23 Aug 2022 23:21:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36570 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234288AbiHXDVb (ORCPT ); Tue, 23 Aug 2022 23:21:31 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 14756816B2 for ; Tue, 23 Aug 2022 20:21:28 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id a19-20020aa780d3000000b0052bccd363f8so6876480pfn.22 for ; Tue, 23 Aug 2022 20:21:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:reply-to:from:to:cc; bh=0Zu9CHYeQLsVtyyQt2AMWvNl6eTy619WBuTXQTtixSA=; b=D55RlPmRHY3855ha+O8WFuydY7xxV00RTpgiyt0tc+7sqW+ZITwJ8rHH4cS6Rgj2Tp EHuWTZwJYb/z5yGCzhd4wR6f3rStHwPGFgRn6L9kMUUWot/3PnViuvUo20Btnb7i66Tw dO9NyUSAB9cSeN4t5FJi7jZBt1djQF7nRCc7u2BDQCLlF0FJx0JuKeXkajK/Bb3xsZqK 6tk7zhNHVsj4IdF9tAKxyVew8z6dGtaEOw8q0I3USCIsdic62o4PAhO7p8dmL04RYw3+ vJCAytqgW15ccVK1stFdEfYnKwvHjs8FRvcUj5bQpNDEkEcfzdtOUCoq+wKJQBUaP8ql g1NA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc; bh=0Zu9CHYeQLsVtyyQt2AMWvNl6eTy619WBuTXQTtixSA=; b=MU5S0ihdUWeNLFxaI8RP8u4yv+vBfWv9Bfp8aKKn+0DOgY9kVv5G59MA3TBzq/+7JO NQSFXb8c8SeMXTm+moTW7bKH8GuBSguKMRZ1N+TUhtE49Gk5q41BO3IvKMN7nLDAqWYz f32+A+3JNpJPFz/hnk6uJSYxeZa+moqxWllBU8R0AW0p7lVMoYRy4Y8pzJag5zigv+L1 73FaXJRLmYAhr77jeE7vHrjcgGxENxkutyuqF2hQipy8pRV2TzXkoNOuoYq/h0BG9O97 TnBkyXb9Z7ibPiwgj9+eFC30Yd+pCSYHabvq8bl1rL414nVL8CBRkK5YuonqR+jct80y cC7A== X-Gm-Message-State: ACgBeo3RbfxfmcV93xuHlMqN/Cf57+wH9DXPh9J5kQbn2LpJR7hzy+YK d07FPxXTdFYiNvDyCq2HrJXbrML1ckU= X-Google-Smtp-Source: AA6agR573qzRI9fRUFVPY21n41Xn0zzpTI2fab3hBfHK20jtmnw9qYoXs3mBXpBUgtjKB0V2MjEeiqR0SSg= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:aa7:814d:0:b0:535:c875:dd4f with SMTP id d13-20020aa7814d000000b00535c875dd4fmr27515181pfn.4.1661311287578; Tue, 23 Aug 2022 20:21:27 -0700 (PDT) Reply-To: Sean Christopherson Date: Wed, 24 Aug 2022 03:21:14 +0000 In-Reply-To: <20220824032115.3563686-1-seanjc@google.com> Message-Id: <20220824032115.3563686-6-seanjc@google.com> Mime-Version: 1.0 References: <20220824032115.3563686-1-seanjc@google.com> X-Mailer: git-send-email 2.37.1.595.g718a3a8f04-goog Subject: [PATCH v4 5/6] KVM: selftests: Make arm64's MMIO ucall multi-VM friendly From: Sean Christopherson To: Paolo Bonzini , Marc Zyngier , Anup Patel , Paul Walmsley , Palmer Dabbelt , Albert Ou , Christian Borntraeger , Janosch Frank , Claudio Imbrenda , Nathan Chancellor , Nick Desaulniers Cc: James Morse , Alexandru Elisei , Suzuki K Poulose , Oliver Upton , Atish Patra , David Hildenbrand , Tom Rix , kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, llvm@lists.linux.dev, linux-kernel@vger.kernel.org, Colton Lewis , Peter Gonda , Andrew Jones , Sean Christopherson Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Fix a mostly-theoretical bug where ARM's ucall MMIO setup could result in different VMs stomping on each other by cloberring the global pointer. Fix the most obvious issue by saving the MMIO gpa into the VM. A more subtle bug is that creating VMs in parallel (on multiple tasks) could result in a VM using the wrong address. Synchronizing a global to a guest effectively snapshots the value on a per-VM basis, i.e. the "global" is already prepped to work with multiple VMs, but setting the global in the host and copying it to the guest needs to happen atomically. To fix that bug, add atomic_sync_global_pointer_to_guest() to sync "global" pointers that hold per-VM values, i.e. technically need to be handled in a thread-safe manner. Signed-off-by: Sean Christopherson --- .../selftests/kvm/include/kvm_util_base.h | 16 +++++++++++++++ .../testing/selftests/kvm/lib/aarch64/ucall.c | 20 ++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/te= sting/selftests/kvm/include/kvm_util_base.h index 24fde97f6121..9ec7fbe941aa 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -16,6 +16,7 @@ #include #include "linux/rbtree.h" =20 +#include =20 #include =20 @@ -81,6 +82,7 @@ struct kvm_vm { struct sparsebit *vpages_mapped; bool has_irqchip; bool pgd_created; + vm_paddr_t ucall_mmio_addr; vm_paddr_t pgd; vm_vaddr_t gdt; vm_vaddr_t tss; @@ -714,6 +716,20 @@ kvm_userspace_memory_region_find(struct kvm_vm *vm, ui= nt64_t start, memcpy(&(g), _p, sizeof(g)); \ }) =20 +/* + * Sync a global pointer to the guest that has a per-VM value, in which ca= se + * writes to the host copy of the "global" must be serialized (in case a t= est + * is being truly crazy and spawning multiple VMs concurrently). + */ +#define atomic_sync_global_pointer_to_guest(vm, g, val) ({ \ + typeof(g) *_p =3D addr_gva2hva(vm, (vm_vaddr_t)&(g)); \ + \ + while (cmpxchg(&g, NULL, val)) \ + ; \ + memcpy(_p, &(g), sizeof(g)); \ + WRITE_ONCE(g, NULL); \ +}) + void assert_on_unhandled_exception(struct kvm_vcpu *vcpu); =20 void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testin= g/selftests/kvm/lib/aarch64/ucall.c index f02ae27c3e43..acb47c813477 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c +++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c @@ -6,20 +6,30 @@ */ #include "kvm_util.h" =20 +/* + * This "global" holds different per-VM values, it must not be accessed fr= om + * host code except to sync the guest value, and that must be done atomica= lly. + */ static vm_vaddr_t *ucall_exit_mmio_addr; =20 +static void ucall_set_mmio_addr(struct kvm_vm *vm, vm_paddr_t mmio_gpa) +{ + vm->ucall_mmio_addr =3D mmio_gpa; + + atomic_sync_global_pointer_to_guest(vm, ucall_exit_mmio_addr, + (vm_vaddr_t *)mmio_gpa); +} + void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) { virt_pg_map(vm, mmio_gpa, mmio_gpa); =20 - ucall_exit_mmio_addr =3D (vm_vaddr_t *)mmio_gpa; - sync_global_to_guest(vm, ucall_exit_mmio_addr); + ucall_set_mmio_addr(vm, mmio_gpa); } =20 void ucall_arch_uninit(struct kvm_vm *vm) { - ucall_exit_mmio_addr =3D 0; - sync_global_to_guest(vm, ucall_exit_mmio_addr); + ucall_set_mmio_addr(vm, (vm_paddr_t)NULL); } =20 void ucall_arch_do_ucall(vm_vaddr_t uc) @@ -32,7 +42,7 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) struct kvm_run *run =3D vcpu->run; =20 if (run->exit_reason =3D=3D KVM_EXIT_MMIO && - run->mmio.phys_addr =3D=3D (uint64_t)ucall_exit_mmio_addr) { + run->mmio.phys_addr =3D=3D vcpu->vm->ucall_mmio_addr) { vm_vaddr_t gva; =20 TEST_ASSERT(run->mmio.is_write && run->mmio.len =3D=3D 8, --=20 2.37.1.595.g718a3a8f04-goog