From nobody Mon Apr 6 22:00:02 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 AD3B1C43217 for ; Thu, 6 Oct 2022 00:34:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229668AbiJFAer (ORCPT ); Wed, 5 Oct 2022 20:34:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58286 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229880AbiJFAeX (ORCPT ); Wed, 5 Oct 2022 20:34:23 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B6FA868AD for ; Wed, 5 Oct 2022 17:34:22 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id br14-20020a056a00440e00b00548434985cdso239396pfb.8 for ; Wed, 05 Oct 2022 17:34:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=9KMeIXPq6GpOVcN55NK7DLftKaRG2/H9/8QOpBzCftA=; b=mEbovaZUu6KW+QLA8E55+qeFjie4ez91koDXMg/9jrSIxWWEn7uEXQSfyV6u9Rbj0q au+eMV2cQU3MEP1qaqbhmLXZQ22xX+sXG6ruwTxeU1jSpEp6tgybSt375ZJjx+bepNLM ShKht/UF9CsHv4HlbDU1Rt5Aheu1FTSX309sP2UUTedYtoOrW+vfR9f+Rms2jv0qL311 xhlrOVJUHNxdYz4Uf6SXwcR5JfRoPwVhg+kAqr6R6aeYjuIwiPye2GNCzJ2FMX2W/GIu ZBZjpz3Kikj1neTh8F0SJ5mQd3pQSFV0yDiAcIjnkYV9DVRUgpC7CVc4TxECrfjAs5Jp /dpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=9KMeIXPq6GpOVcN55NK7DLftKaRG2/H9/8QOpBzCftA=; b=5Ej6C39amfYPSfl2b6EaS47DeXErIdeRDTht61YPWiJ1mHBGXF+wejtdv48JcKk8kC QXibkdDM56ZJQmpMaqt2Xz4MltLXLZNmhiCn78N67AopF0onGAbaTDi8y6LdUkCsCXy4 JbPJ4oOi2vH/URoRgAvoO3w6xFVnSO77dtjnSSDJxHUpnCh6vSLXe+29vuXP8xSBjBx4 s8GI9hP8P8DpiDq/S2aYvk7alLFjv5suS2hmLXR7fJtli8/hNwG2qmzBahEC0ewLlOXb TqSfSVJVccSD1hqyKBUEbDxWHrUClZZ+S9FlQ6VRA8s4mIOn6blUFOa4pwTscbFtYRf9 HBMg== X-Gm-Message-State: ACrzQf2k3J5rEJQs7DrWSsgtA/V5hHQreJXKxvazli2YMH0oO/cItg2E W958jF5Z0iERkh1CtNoxnQ60S9++ObM= X-Google-Smtp-Source: AMsMyM45qnrI9G6azK6iw6bHSpADVc1CoVnhaNByhJReWqWjXc5QYOLtqbmuu2pzhK5ymOSC9YZe69vGWgs= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6a00:f0f:b0:562:3169:eba1 with SMTP id cr15-20020a056a000f0f00b005623169eba1mr2284230pfb.59.1665016461754; Wed, 05 Oct 2022 17:34:21 -0700 (PDT) Reply-To: Sean Christopherson Date: Thu, 6 Oct 2022 00:34:07 +0000 In-Reply-To: <20221006003409.649993-1-seanjc@google.com> Mime-Version: 1.0 References: <20221006003409.649993-1-seanjc@google.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog Message-ID: <20221006003409.649993-6-seanjc@google.com> Subject: [PATCH v6 5/7] KVM: selftests: Make arm64's MMIO ucall multi-VM friendly From: Sean Christopherson To: Paolo Bonzini , Shuah Khan , 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 , linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, kvmarm@lists.cs.columbia.edu, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, llvm@lists.linux.dev, Colton Lewis , Andrew Jones , Peter Gonda , 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 is not thread-safe. To fix that bug, add write_guest_global() to allow stuffing a VM's copy of a "global" without modifying the host value. Reviewed-by: Andrew Jones Tested-by: Peter Gonda Signed-off-by: Sean Christopherson --- .../selftests/kvm/include/kvm_util_base.h | 15 +++++++++++++++ .../testing/selftests/kvm/lib/aarch64/ucall.c | 19 ++++++++++++++----- 2 files changed, 29 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 e42a09cd24a0..c14d531a942a 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; @@ -718,6 +720,19 @@ kvm_userspace_memory_region_find(struct kvm_vm *vm, ui= nt64_t start, memcpy(&(g), _p, sizeof(g)); \ }) =20 +/* + * Write a global value, but only in the VM's (guest's) domain. Primarily= used + * for "globals" that hold per-VM values (VMs always duplicate code and gl= obal + * data into their own region of physical memory), but can be used anytime= it's + * undesirable to change the host's copy of the global. + */ +#define write_guest_global(vm, g, val) ({ \ + typeof(g) *_p =3D addr_gva2hva(vm, (vm_vaddr_t)&(g)); \ + typeof(g) _val =3D val; \ + \ + memcpy(_p, &(_val), sizeof(g)); \ +}) + 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..1c38bd260f90 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c +++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c @@ -6,20 +6,29 @@ */ #include "kvm_util.h" =20 +/* + * ucall_exit_mmio_addr holds per-VM values (global data is duplicated by = each + * VM), it must not be accessed from host code. + */ 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; + + write_guest_global(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 +41,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.38.0.rc1.362.ged0d419d3c-goog