From nobody Wed Apr 8 02:48:30 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 EFAEBC32793 for ; Wed, 24 Aug 2022 03:21:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234246AbiHXDV0 (ORCPT ); Tue, 23 Aug 2022 23:21:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233815AbiHXDVV (ORCPT ); Tue, 23 Aug 2022 23:21:21 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 406747E010 for ; Tue, 23 Aug 2022 20:21:20 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id 92-20020a17090a09e500b001d917022847so6814829pjo.1 for ; Tue, 23 Aug 2022 20:21:20 -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=wtLUCfKzRSBKyqzo4FVzGqM9LhFt5R903IOvXYqBYBc=; b=eESBbT2+W9zCsVMpXik4dEDPaalIRvqdfo16s/t6/J7UBvxuox/eTDwod741qM/q42 V2jOf16DCIo7j9ygYiiPJD4hMuiWpHhxEuDgXGn7BC8srOGyGn3fROIwULAmeLOWmUWD Xm6Nezf8Hn5vhndS0c7qiGNnDX52X0nSVAWjGnj2ixKQbyOWm/kNtdYni8gzyX13EM7l ulC6jj4JgYmWenwU0fSZulZLKxWfv5NaOt1UPHvsRYX16Lm37yJ3uewDiWK+oFri4mR1 UPND6Wsjc1qKNkDoEQSdFKXAiACb7pNJy7OLaLGPmb7jBV0LFGf4UWuz9Impqpe6vdUj i5zg== 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=wtLUCfKzRSBKyqzo4FVzGqM9LhFt5R903IOvXYqBYBc=; b=GkTtzBOqYD7z9j/oTLTfHiegQcKmmgGqmyFaL9lFlgRy0GfTg2fncOF0ARQcots2LH yKgzhbLFNvE7BHGfsV0D7iVMy7NDauCxb/RRcX484CIe64rKU7flehe2zgEnzoL0nWp6 m2aTP311reMrOtqUIEESirZ8FSB6ofyQX6u1QtNto+nQ0Jt7hBomNBuA4GzEn/xKdDSE FIRCbncVDy8ko5EY63nHjG1lmxZUBrwztF8g1fMqAiI7BSMC3h+ls/fzh5VwEJHOaTzu 1JLRsmBFsxeCRex6bwWBm9SAZDqZYkptz0ySibrvLHbXNJZd8aX1DmYtF2euJhjOx/uk 3sJA== X-Gm-Message-State: ACgBeo2Dcf6mRYLlPrWJekWVrFrjSxhns2Y3spygR2I/b8R7aAU9GuOc zZSzWpOZtOy+cUh0D6udDSvDss2TPK8= X-Google-Smtp-Source: AA6agR7nWH/v46q+tJqwDgyPv3qjQXZ6329HUyxQYK0CjAquGSgm9hmktSh4bMhhS4QHH6ZbXrQZdF1h+pQ= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a17:902:c9cc:b0:172:e18d:4703 with SMTP id q12-20020a170902c9cc00b00172e18d4703mr14110982pld.41.1661311279817; Tue, 23 Aug 2022 20:21:19 -0700 (PDT) Reply-To: Sean Christopherson Date: Wed, 24 Aug 2022 03:21:10 +0000 In-Reply-To: <20220824032115.3563686-1-seanjc@google.com> Message-Id: <20220824032115.3563686-2-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 1/6] KVM: selftests: Consolidate common code for populating ucall struct 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" Make ucall() a common helper that populates struct ucall, and only calls into arch code to make the actually call out to userspace. Rename all arch-specific helpers to make it clear they're arch-specific, and to avoid collisions with common helpers (one more on its way...) Add WRITE_ONCE() to stores in ucall() code (as already done to aarch64 code in commit 9e2f6498efbb ("selftests: KVM: Handle compiler optimizations in ucall")) to prevent clang optimizations breaking ucalls. Cc: Colton Lewis Cc: Peter Gonda Reviewed-by: Andrew Jones Signed-off-by: Sean Christopherson --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/ucall_common.h | 23 ++++++++++++++++--- .../testing/selftests/kvm/lib/aarch64/ucall.c | 22 ++++-------------- tools/testing/selftests/kvm/lib/riscv/ucall.c | 23 ++++--------------- tools/testing/selftests/kvm/lib/s390x/ucall.c | 23 ++++--------------- .../testing/selftests/kvm/lib/ucall_common.c | 20 ++++++++++++++++ .../testing/selftests/kvm/lib/x86_64/ucall.c | 23 ++++--------------- 7 files changed, 61 insertions(+), 74 deletions(-) create mode 100644 tools/testing/selftests/kvm/lib/ucall_common.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests= /kvm/Makefile index 4c122f1b1737..23649c5d42fc 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -47,6 +47,7 @@ LIBKVM +=3D lib/perf_test_util.c LIBKVM +=3D lib/rbtree.c LIBKVM +=3D lib/sparsebit.c LIBKVM +=3D lib/test_util.c +LIBKVM +=3D lib/ucall_common.c =20 LIBKVM_x86_64 +=3D lib/x86_64/apic.c LIBKVM_x86_64 +=3D lib/x86_64/handlers.S diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/tes= ting/selftests/kvm/include/ucall_common.h index ee79d180e07e..5a85f5318bbe 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -24,10 +24,27 @@ struct ucall { uint64_t args[UCALL_MAX_ARGS]; }; =20 -void ucall_init(struct kvm_vm *vm, void *arg); -void ucall_uninit(struct kvm_vm *vm); +void ucall_arch_init(struct kvm_vm *vm, void *arg); +void ucall_arch_uninit(struct kvm_vm *vm); +void ucall_arch_do_ucall(vm_vaddr_t uc); +uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); + void ucall(uint64_t cmd, int nargs, ...); -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); + +static inline void ucall_init(struct kvm_vm *vm, void *arg) +{ + ucall_arch_init(vm, arg); +} + +static inline void ucall_uninit(struct kvm_vm *vm) +{ + ucall_arch_uninit(vm); +} + +static inline uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +{ + return ucall_arch_get_ucall(vcpu, uc); +} =20 #define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \ ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4) diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testin= g/selftests/kvm/lib/aarch64/ucall.c index ed237b744690..3630708c32d6 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c +++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c @@ -21,7 +21,7 @@ static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t= gpa) return true; } =20 -void ucall_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, void *arg) { vm_paddr_t gpa, start, end, step, offset; unsigned int bits; @@ -64,30 +64,18 @@ void ucall_init(struct kvm_vm *vm, void *arg) TEST_FAIL("Can't find a ucall mmio address"); } =20 -void ucall_uninit(struct kvm_vm *vm) +void ucall_arch_uninit(struct kvm_vm *vm) { ucall_exit_mmio_addr =3D 0; sync_global_to_guest(vm, ucall_exit_mmio_addr); } =20 -void ucall(uint64_t cmd, int nargs, ...) +void ucall_arch_do_ucall(vm_vaddr_t uc) { - struct ucall uc =3D {}; - va_list va; - int i; - - WRITE_ONCE(uc.cmd, cmd); - nargs =3D min(nargs, UCALL_MAX_ARGS); - - va_start(va, nargs); - for (i =3D 0; i < nargs; ++i) - WRITE_ONCE(uc.args[i], va_arg(va, uint64_t)); - va_end(va); - - WRITE_ONCE(*ucall_exit_mmio_addr, (vm_vaddr_t)&uc); + WRITE_ONCE(*ucall_exit_mmio_addr, uc); } =20 -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) { struct kvm_run *run =3D vcpu->run; struct ucall ucall =3D {}; diff --git a/tools/testing/selftests/kvm/lib/riscv/ucall.c b/tools/testing/= selftests/kvm/lib/riscv/ucall.c index 087b9740bc8f..b1598f418c1f 100644 --- a/tools/testing/selftests/kvm/lib/riscv/ucall.c +++ b/tools/testing/selftests/kvm/lib/riscv/ucall.c @@ -10,11 +10,11 @@ #include "kvm_util.h" #include "processor.h" =20 -void ucall_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, void *arg) { } =20 -void ucall_uninit(struct kvm_vm *vm) +void ucall_arch_uninit(struct kvm_vm *vm) { } =20 @@ -44,27 +44,14 @@ struct sbiret sbi_ecall(int ext, int fid, unsigned long= arg0, return ret; } =20 -void ucall(uint64_t cmd, int nargs, ...) +void ucall_arch_do_ucall(vm_vaddr_t uc) { - struct ucall uc =3D { - .cmd =3D cmd, - }; - va_list va; - int i; - - nargs =3D min(nargs, UCALL_MAX_ARGS); - - va_start(va, nargs); - for (i =3D 0; i < nargs; ++i) - uc.args[i] =3D va_arg(va, uint64_t); - va_end(va); - sbi_ecall(KVM_RISCV_SELFTESTS_SBI_EXT, KVM_RISCV_SELFTESTS_SBI_UCALL, - (vm_vaddr_t)&uc, 0, 0, 0, 0, 0); + uc, 0, 0, 0, 0, 0); } =20 -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) { struct kvm_run *run =3D vcpu->run; struct ucall ucall =3D {}; diff --git a/tools/testing/selftests/kvm/lib/s390x/ucall.c b/tools/testing/= selftests/kvm/lib/s390x/ucall.c index 73dc4e21190f..114cb4af295f 100644 --- a/tools/testing/selftests/kvm/lib/s390x/ucall.c +++ b/tools/testing/selftests/kvm/lib/s390x/ucall.c @@ -6,34 +6,21 @@ */ #include "kvm_util.h" =20 -void ucall_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, void *arg) { } =20 -void ucall_uninit(struct kvm_vm *vm) +void ucall_arch_uninit(struct kvm_vm *vm) { } =20 -void ucall(uint64_t cmd, int nargs, ...) +void ucall_arch_do_ucall(vm_vaddr_t uc) { - struct ucall uc =3D { - .cmd =3D cmd, - }; - va_list va; - int i; - - nargs =3D min(nargs, UCALL_MAX_ARGS); - - va_start(va, nargs); - for (i =3D 0; i < nargs; ++i) - uc.args[i] =3D va_arg(va, uint64_t); - va_end(va); - /* Exit via DIAGNOSE 0x501 (normally used for breakpoints) */ - asm volatile ("diag 0,%0,0x501" : : "a"(&uc) : "memory"); + asm volatile ("diag 0,%0,0x501" : : "a"(uc) : "memory"); } =20 -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) { struct kvm_run *run =3D vcpu->run; struct ucall ucall =3D {}; diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing= /selftests/kvm/lib/ucall_common.c new file mode 100644 index 000000000000..2395c7f1d543 --- /dev/null +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include "kvm_util.h" + +void ucall(uint64_t cmd, int nargs, ...) +{ + struct ucall uc =3D {}; + va_list va; + int i; + + WRITE_ONCE(uc.cmd, cmd); + + nargs =3D min(nargs, UCALL_MAX_ARGS); + + va_start(va, nargs); + for (i =3D 0; i < nargs; ++i) + WRITE_ONCE(uc.args[i], va_arg(va, uint64_t)); + va_end(va); + + ucall_arch_do_ucall((vm_vaddr_t)&uc); +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing= /selftests/kvm/lib/x86_64/ucall.c index e5f0f9e0d3ee..9f532dba1003 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c +++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c @@ -8,34 +8,21 @@ =20 #define UCALL_PIO_PORT ((uint16_t)0x1000) =20 -void ucall_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, void *arg) { } =20 -void ucall_uninit(struct kvm_vm *vm) +void ucall_arch_uninit(struct kvm_vm *vm) { } =20 -void ucall(uint64_t cmd, int nargs, ...) +void ucall_arch_do_ucall(vm_vaddr_t uc) { - struct ucall uc =3D { - .cmd =3D cmd, - }; - va_list va; - int i; - - nargs =3D min(nargs, UCALL_MAX_ARGS); - - va_start(va, nargs); - for (i =3D 0; i < nargs; ++i) - uc.args[i] =3D va_arg(va, uint64_t); - va_end(va); - asm volatile("in %[port], %%al" - : : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax", "memory"); + : : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax", "memory"); } =20 -uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) { struct kvm_run *run =3D vcpu->run; struct ucall ucall =3D {}; --=20 2.37.1.595.g718a3a8f04-goog From nobody Wed Apr 8 02:48:30 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 B5E3FC32792 for ; Wed, 24 Aug 2022 03:21:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234287AbiHXDVd (ORCPT ); Tue, 23 Aug 2022 23:21:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234162AbiHXDVY (ORCPT ); Tue, 23 Aug 2022 23:21:24 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2DD367E328 for ; Tue, 23 Aug 2022 20:21:22 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-3339532b6a8so269580907b3.1 for ; Tue, 23 Aug 2022 20:21:22 -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=AvRcIKqXhz2XvQML00z0+kznKqDBRZMFG+kMQw3jc5A=; b=XpQjjgzdSGq8hzuZ2ZUhJD8vVlRVHCKyE4hPgAH3kqKZoAaUAAR3DET82ZXrD4hf9R o4IiQYmouIpztKHOYGMuCn5oJaTvpi+qYOTHUOsEeeb8NvqsxL+7VmoQCpLgm3aTMjQd YgfExVVj9unrGyJtuuL/FwkyGsHzL22MSq/7KxpeFhbP1quYqO/7tESatzwUm0a+DUiP xakNmKKpwErccCjsyhLfBgyEV5xEK1rYgkBZllqKD5Jj3XVlVc+aSSiy7k+KT/W8L6IR GNiB7g1/MiLk6378t1rp9dYG+S1Mgah532mMxsAWOwjs7EHgnY55jENx8NjiRqL0wbdo tSLw== 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=AvRcIKqXhz2XvQML00z0+kznKqDBRZMFG+kMQw3jc5A=; b=HK+gSq2kBZ2IeI8wXEcvYoNOwtgMvG8IT7Q+n9MM5QJ6tppau0HkxTy3eFuVowk9nZ q/MqKWVyBKuNKz9Llm1NzFrb5KmzpQkOg6T2mWNg1D/889OIuJj67dDjm9Mnt2OUypLM 8tyhuLEwcd+aWzyGUelzV0WXkctOXcKodH9Z9TrdsntVV+ItaToi9ZFZxz2lScoJPBB3 YVyDJVFQGTtPSdhhkFfopi8tedqYVIh5PYGXIen8Aeyhb1cFcSAgAxXk4gGjZ0+DdmxK n8WhY89Uyfqj3A4wglyURm8Ic5P0OPka/HjlgcclbhGzXH+cdHCmQJtndtf9Ig1tLVvC o12Q== X-Gm-Message-State: ACgBeo0yN7a5Ew8nj53BbsCr74hkdH5EPLDktxdlrtVG5suRm2UvbYJe MOMwuKimWj456aXOX0LhUKYZOEUrNPk= X-Google-Smtp-Source: AA6agR7+lFJvOnmwfxAf8eTG09+epZU2PiugxhJc+RAdOUcW/Ym1L6pF9LqP+9hIKIiaT5O4hRaEX0qI/xQ= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a0d:d7cd:0:b0:33d:a7ad:6c29 with SMTP id z196-20020a0dd7cd000000b0033da7ad6c29mr77558ywd.466.1661311281468; Tue, 23 Aug 2022 20:21:21 -0700 (PDT) Reply-To: Sean Christopherson Date: Wed, 24 Aug 2022 03:21:11 +0000 In-Reply-To: <20220824032115.3563686-1-seanjc@google.com> Message-Id: <20220824032115.3563686-3-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 2/6] KVM: selftests: Consolidate boilerplate code in get_ucall() 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" Consolidate the actual copying of a ucall struct from guest=3D>host into the common get_ucall(). Return a host virtual address instead of a guest virtual address even though the addr_gva2hva() part could be moved to get_ucall() too. Conceptually, get_ucall() is invoked from the host and should return a host virtual address (and returning NULL for "nothing to see here" is far superior to returning 0). Use pointer shenanigans instead of an unnecessary bounce buffer when the caller of get_ucall() provides a valid pointer. Reviewed-by: Andrew Jones Signed-off-by: Sean Christopherson --- .../selftests/kvm/include/ucall_common.h | 8 ++------ .../testing/selftests/kvm/lib/aarch64/ucall.c | 14 +++----------- tools/testing/selftests/kvm/lib/riscv/ucall.c | 19 +++---------------- tools/testing/selftests/kvm/lib/s390x/ucall.c | 16 +++------------- .../testing/selftests/kvm/lib/ucall_common.c | 19 +++++++++++++++++++ .../testing/selftests/kvm/lib/x86_64/ucall.c | 16 +++------------- 6 files changed, 33 insertions(+), 59 deletions(-) diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/tes= ting/selftests/kvm/include/ucall_common.h index 5a85f5318bbe..63bfc60be995 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -27,9 +27,10 @@ struct ucall { void ucall_arch_init(struct kvm_vm *vm, void *arg); void ucall_arch_uninit(struct kvm_vm *vm); void ucall_arch_do_ucall(vm_vaddr_t uc); -uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); =20 void ucall(uint64_t cmd, int nargs, ...); +uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); =20 static inline void ucall_init(struct kvm_vm *vm, void *arg) { @@ -41,11 +42,6 @@ static inline void ucall_uninit(struct kvm_vm *vm) ucall_arch_uninit(vm); } =20 -static inline uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) -{ - return ucall_arch_get_ucall(vcpu, uc); -} - #define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \ ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4) #define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage) diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testin= g/selftests/kvm/lib/aarch64/ucall.c index 3630708c32d6..f214f5cc53d3 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c +++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c @@ -75,13 +75,9 @@ void ucall_arch_do_ucall(vm_vaddr_t uc) WRITE_ONCE(*ucall_exit_mmio_addr, uc); } =20 -uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) { struct kvm_run *run =3D vcpu->run; - struct ucall ucall =3D {}; - - if (uc) - memset(uc, 0, sizeof(*uc)); =20 if (run->exit_reason =3D=3D KVM_EXIT_MMIO && run->mmio.phys_addr =3D=3D (uint64_t)ucall_exit_mmio_addr) { @@ -90,12 +86,8 @@ uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, str= uct ucall *uc) TEST_ASSERT(run->mmio.is_write && run->mmio.len =3D=3D 8, "Unexpected ucall exit mmio address access"); memcpy(&gva, run->mmio.data, sizeof(gva)); - memcpy(&ucall, addr_gva2hva(vcpu->vm, gva), sizeof(ucall)); - - vcpu_run_complete_io(vcpu); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); + return addr_gva2hva(vcpu->vm, gva); } =20 - return ucall.cmd; + return NULL; } diff --git a/tools/testing/selftests/kvm/lib/riscv/ucall.c b/tools/testing/= selftests/kvm/lib/riscv/ucall.c index b1598f418c1f..37e091d4366e 100644 --- a/tools/testing/selftests/kvm/lib/riscv/ucall.c +++ b/tools/testing/selftests/kvm/lib/riscv/ucall.c @@ -51,27 +51,15 @@ void ucall_arch_do_ucall(vm_vaddr_t uc) uc, 0, 0, 0, 0, 0); } =20 -uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) { struct kvm_run *run =3D vcpu->run; - struct ucall ucall =3D {}; - - if (uc) - memset(uc, 0, sizeof(*uc)); =20 if (run->exit_reason =3D=3D KVM_EXIT_RISCV_SBI && run->riscv_sbi.extension_id =3D=3D KVM_RISCV_SELFTESTS_SBI_EXT) { switch (run->riscv_sbi.function_id) { case KVM_RISCV_SELFTESTS_SBI_UCALL: - memcpy(&ucall, - addr_gva2hva(vcpu->vm, run->riscv_sbi.args[0]), - sizeof(ucall)); - - vcpu_run_complete_io(vcpu); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); - - break; + return addr_gva2hva(vcpu->vm, run->riscv_sbi.args[0]); case KVM_RISCV_SELFTESTS_SBI_UNEXP: vcpu_dump(stderr, vcpu, 2); TEST_ASSERT(0, "Unexpected trap taken by guest"); @@ -80,6 +68,5 @@ uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, stru= ct ucall *uc) break; } } - - return ucall.cmd; + return NULL; } diff --git a/tools/testing/selftests/kvm/lib/s390x/ucall.c b/tools/testing/= selftests/kvm/lib/s390x/ucall.c index 114cb4af295f..0f695a031d35 100644 --- a/tools/testing/selftests/kvm/lib/s390x/ucall.c +++ b/tools/testing/selftests/kvm/lib/s390x/ucall.c @@ -20,13 +20,9 @@ void ucall_arch_do_ucall(vm_vaddr_t uc) asm volatile ("diag 0,%0,0x501" : : "a"(uc) : "memory"); } =20 -uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) { struct kvm_run *run =3D vcpu->run; - struct ucall ucall =3D {}; - - if (uc) - memset(uc, 0, sizeof(*uc)); =20 if (run->exit_reason =3D=3D KVM_EXIT_S390_SIEIC && run->s390_sieic.icptcode =3D=3D 4 && @@ -34,13 +30,7 @@ uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, str= uct ucall *uc) (run->s390_sieic.ipb >> 16) =3D=3D 0x501) { int reg =3D run->s390_sieic.ipa & 0xf; =20 - memcpy(&ucall, addr_gva2hva(vcpu->vm, run->s.regs.gprs[reg]), - sizeof(ucall)); - - vcpu_run_complete_io(vcpu); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); + return addr_gva2hva(vcpu->vm, run->s.regs.gprs[reg]); } - - return ucall.cmd; + return NULL; } diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing= /selftests/kvm/lib/ucall_common.c index 2395c7f1d543..ced480860746 100644 --- a/tools/testing/selftests/kvm/lib/ucall_common.c +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -18,3 +18,22 @@ void ucall(uint64_t cmd, int nargs, ...) =20 ucall_arch_do_ucall((vm_vaddr_t)&uc); } + +uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +{ + struct ucall ucall; + void *addr; + + if (!uc) + uc =3D &ucall; + + addr =3D ucall_arch_get_ucall(vcpu); + if (addr) { + memcpy(uc, addr, sizeof(*uc)); + vcpu_run_complete_io(vcpu); + } else { + memset(uc, 0, sizeof(*uc)); + } + + return uc->cmd; +} diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing= /selftests/kvm/lib/x86_64/ucall.c index 9f532dba1003..ead9946399ab 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c +++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c @@ -22,25 +22,15 @@ void ucall_arch_do_ucall(vm_vaddr_t uc) : : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax", "memory"); } =20 -uint64_t ucall_arch_get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) +void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) { struct kvm_run *run =3D vcpu->run; - struct ucall ucall =3D {}; - - if (uc) - memset(uc, 0, sizeof(*uc)); =20 if (run->exit_reason =3D=3D KVM_EXIT_IO && run->io.port =3D=3D UCALL_PIO_= PORT) { struct kvm_regs regs; =20 vcpu_regs_get(vcpu, ®s); - memcpy(&ucall, addr_gva2hva(vcpu->vm, (vm_vaddr_t)regs.rdi), - sizeof(ucall)); - - vcpu_run_complete_io(vcpu); - if (uc) - memcpy(uc, &ucall, sizeof(ucall)); + return addr_gva2hva(vcpu->vm, regs.rdi); } - - return ucall.cmd; + return NULL; } --=20 2.37.1.595.g718a3a8f04-goog From nobody Wed Apr 8 02:48:30 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 4B067C32792 for ; Wed, 24 Aug 2022 03:21:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234502AbiHXDVm (ORCPT ); Tue, 23 Aug 2022 23:21:42 -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 S234228AbiHXDV0 (ORCPT ); Tue, 23 Aug 2022 23:21:26 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BD9397E319 for ; Tue, 23 Aug 2022 20:21:24 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id s8-20020a170902ea0800b00172e456031eso5253521plg.3 for ; Tue, 23 Aug 2022 20:21:24 -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=BDUdPPFVmg48+iWFRgfZWp6MDxFAyXarlMqdFhUo6yE=; b=PNYwL5ej6jQhXOyo7Ay9js2pcHORA2nOY4FeQDYcHWAitF4012kptwH+pbfQVro3fM VFzSb9M/rcID4bIoGm5YVEyHN5ki6/L3POmmjMFUwIVsOSqn92QgKc7C4/jluuLdOeIt na+/zxQAjgExMVXJTn+5NDbY1e5ywbMkDmVl2Mwa/wXzmKNgVV8xrSvuQT3t0GWGNI4t sFCxMWumTlrIcKzv+UDr4bV6fmDVI0g8i0X4npjeMbRKt/psNoGi6VE3xCvQe0Ba42Gc 1CDnnBeoY0mJdNVIn7isfsj+/ZQ/2jKry6UeoSn9qXsZPFIeOBCDyIfPN2sjr0JWTqKS HaPw== 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=BDUdPPFVmg48+iWFRgfZWp6MDxFAyXarlMqdFhUo6yE=; b=2c4xMh9UWd61xzfisMURHpR0G3IZbTVBBfArf6OiWVsAaHB/rTOkpGnvvWRJSWZ1NO auy0Wn/TtwsE/kWcMu6PZ2UAGndocTeO2rwX0PcUS8KBP+fPMBtM77t9WZphfOLgtYyS YFJB4/WmArWn+a6JH7Gja7RzIPvthfpxVJNYqZvmU/hPilj1XzP8jiGkuwC4ehwhGFjq psHK2UziEFXew5dlxa8NR6SBekYux3Dt53i0v1r3+YntXeTCJQM70mDh6AkQvxaLugY1 5NXAN9ULQBoqGD4pAjWWdlH2Cx0g2+00xq3DWvDQBCyp4g/XmLqPTzz3myaDqyqs5OOZ TMOw== X-Gm-Message-State: ACgBeo2oRCqUqfrVEQ2Rcfga8VowWBTTfSsg4q6Zz7qU1KYQRiK9uCtN wDYUq9jcFSBkKA014CIePtZkWPjxuyE= X-Google-Smtp-Source: AA6agR4diYe3XKRjcT81HHLEM+vxhb+vpRg5/wYrDDTyMniAyRoYb31j/sX1Ch/Df02VfgCqipZQnFSU0Uo= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a17:90a:249:b0:1e0:a8a3:3c6c with SMTP id t9-20020a17090a024900b001e0a8a33c6cmr154647pje.0.1661311283300; Tue, 23 Aug 2022 20:21:23 -0700 (PDT) Reply-To: Sean Christopherson Date: Wed, 24 Aug 2022 03:21:12 +0000 In-Reply-To: <20220824032115.3563686-1-seanjc@google.com> Message-Id: <20220824032115.3563686-4-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 3/6] KVM: selftests: Automatically do init_ucall() for non-barebones VMs 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" Do init_ucall() automatically during VM creation to kill two (three?) birds with one stone. First, initializing ucall immediately after VM creations allows forcing aarch64's MMIO ucall address to immediately follow memslot0. This is still somewhat fragile as tests could clobber the MMIO address with a new memslot, but it's safe-ish since tests have to be conversative when accounting for memslot0. And this can be hardened in the future by creating a read-only memslot for the MMIO page (KVM ARM exits with MMIO if the guest writes to a read-only memslot). Add a TODO to document that selftests can and should use a memslot for the ucall MMIO (doing so requires yet more rework because tests assumes thay can use all memslots except memslot0). Second, initializing ucall for all VMs prepares for making ucall initialization meaningful on all architectures. aarch64 is currently the only arch that needs to do any setup, but that will change in the future by switching to a pool-based implementation (instead of the current stack-based approach). Lastly, defining the ucall MMIO address from common code will simplify switching all architectures (except s390) to a common MMIO-based ucall implementation (if there's ever sufficient motivation to do so). Cc: Oliver Upton Signed-off-by: Sean Christopherson --- .../selftests/kvm/aarch64/arch_timer.c | 1 - .../selftests/kvm/aarch64/debug-exceptions.c | 1 - .../selftests/kvm/aarch64/hypercalls.c | 1 - .../testing/selftests/kvm/aarch64/psci_test.c | 1 - .../testing/selftests/kvm/aarch64/vgic_init.c | 2 - .../testing/selftests/kvm/aarch64/vgic_irq.c | 1 - tools/testing/selftests/kvm/dirty_log_test.c | 2 - .../selftests/kvm/include/ucall_common.h | 6 +-- .../selftests/kvm/kvm_page_table_test.c | 1 - .../testing/selftests/kvm/lib/aarch64/ucall.c | 54 ++----------------- tools/testing/selftests/kvm/lib/kvm_util.c | 11 ++++ .../selftests/kvm/lib/perf_test_util.c | 2 - tools/testing/selftests/kvm/lib/riscv/ucall.c | 2 +- tools/testing/selftests/kvm/lib/s390x/ucall.c | 2 +- .../testing/selftests/kvm/lib/x86_64/ucall.c | 2 +- .../testing/selftests/kvm/memslot_perf_test.c | 1 - tools/testing/selftests/kvm/rseq_test.c | 1 - tools/testing/selftests/kvm/steal_time.c | 1 - .../kvm/system_counter_offset_test.c | 1 - 19 files changed, 20 insertions(+), 73 deletions(-) diff --git a/tools/testing/selftests/kvm/aarch64/arch_timer.c b/tools/testi= ng/selftests/kvm/aarch64/arch_timer.c index 574eb73f0e90..37c0ddebf4db 100644 --- a/tools/testing/selftests/kvm/aarch64/arch_timer.c +++ b/tools/testing/selftests/kvm/aarch64/arch_timer.c @@ -375,7 +375,6 @@ static struct kvm_vm *test_vm_create(void) for (i =3D 0; i < nr_vcpus; i++) vcpu_init_descriptor_tables(vcpus[i]); =20 - ucall_init(vm, NULL); test_init_timer_irq(vm); gic_fd =3D vgic_v3_setup(vm, nr_vcpus, 64, GICD_BASE_GPA, GICR_BASE_GPA); __TEST_REQUIRE(gic_fd >=3D 0, "Failed to create vgic-v3"); diff --git a/tools/testing/selftests/kvm/aarch64/debug-exceptions.c b/tools= /testing/selftests/kvm/aarch64/debug-exceptions.c index 2ee35cf9801e..eaf225fd2a4a 100644 --- a/tools/testing/selftests/kvm/aarch64/debug-exceptions.c +++ b/tools/testing/selftests/kvm/aarch64/debug-exceptions.c @@ -254,7 +254,6 @@ int main(int argc, char *argv[]) int stage; =20 vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); - ucall_init(vm, NULL); =20 vm_init_descriptor_tables(vm); vcpu_init_descriptor_tables(vcpu); diff --git a/tools/testing/selftests/kvm/aarch64/hypercalls.c b/tools/testi= ng/selftests/kvm/aarch64/hypercalls.c index a39da3fe4952..3dceecfd1f62 100644 --- a/tools/testing/selftests/kvm/aarch64/hypercalls.c +++ b/tools/testing/selftests/kvm/aarch64/hypercalls.c @@ -236,7 +236,6 @@ static struct kvm_vm *test_vm_create(struct kvm_vcpu **= vcpu) =20 vm =3D vm_create_with_one_vcpu(vcpu, guest_code); =20 - ucall_init(vm, NULL); steal_time_init(*vcpu); =20 return vm; diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testin= g/selftests/kvm/aarch64/psci_test.c index f7621f6e938e..56278f3df891 100644 --- a/tools/testing/selftests/kvm/aarch64/psci_test.c +++ b/tools/testing/selftests/kvm/aarch64/psci_test.c @@ -77,7 +77,6 @@ static struct kvm_vm *setup_vm(void *guest_code, struct k= vm_vcpu **source, struct kvm_vm *vm; =20 vm =3D vm_create(2); - ucall_init(vm, NULL); =20 vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init); init.features[0] |=3D (1 << KVM_ARM_VCPU_PSCI_0_2); diff --git a/tools/testing/selftests/kvm/aarch64/vgic_init.c b/tools/testin= g/selftests/kvm/aarch64/vgic_init.c index e05ecb31823f..cc828fb53d8f 100644 --- a/tools/testing/selftests/kvm/aarch64/vgic_init.c +++ b/tools/testing/selftests/kvm/aarch64/vgic_init.c @@ -68,8 +68,6 @@ static void guest_code(void) /* we don't want to assert on run execution, hence that helper */ static int run_vcpu(struct kvm_vcpu *vcpu) { - ucall_init(vcpu->vm, NULL); - return __vcpu_run(vcpu) ? -errno : 0; } =20 diff --git a/tools/testing/selftests/kvm/aarch64/vgic_irq.c b/tools/testing= /selftests/kvm/aarch64/vgic_irq.c index 17417220a083..d1817f852daf 100644 --- a/tools/testing/selftests/kvm/aarch64/vgic_irq.c +++ b/tools/testing/selftests/kvm/aarch64/vgic_irq.c @@ -756,7 +756,6 @@ static void test_vgic(uint32_t nr_irqs, bool level_sens= itive, bool eoi_split) print_args(&args); =20 vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); - ucall_init(vm, NULL); =20 vm_init_descriptor_tables(vm); vcpu_init_descriptor_tables(vcpu); diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/s= elftests/kvm/dirty_log_test.c index 9c883c94d478..583b46250d07 100644 --- a/tools/testing/selftests/kvm/dirty_log_test.c +++ b/tools/testing/selftests/kvm/dirty_log_test.c @@ -754,8 +754,6 @@ static void run_test(enum vm_guest_mode mode, void *arg) /* Cache the HVA pointer of the region */ host_test_mem =3D addr_gpa2hva(vm, (vm_paddr_t)guest_test_phys_mem); =20 - ucall_init(vm, NULL); - /* Export the shared variables to the guest */ sync_global_to_guest(vm, host_page_size); sync_global_to_guest(vm, guest_page_size); diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/tes= ting/selftests/kvm/include/ucall_common.h index 63bfc60be995..8077a6d8b1ba 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -24,7 +24,7 @@ struct ucall { uint64_t args[UCALL_MAX_ARGS]; }; =20 -void ucall_arch_init(struct kvm_vm *vm, void *arg); +void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa); void ucall_arch_uninit(struct kvm_vm *vm); void ucall_arch_do_ucall(vm_vaddr_t uc); void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); @@ -32,9 +32,9 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); void ucall(uint64_t cmd, int nargs, ...); uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); =20 -static inline void ucall_init(struct kvm_vm *vm, void *arg) +static inline void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) { - ucall_arch_init(vm, arg); + ucall_arch_init(vm, mmio_gpa); } =20 static inline void ucall_uninit(struct kvm_vm *vm) diff --git a/tools/testing/selftests/kvm/kvm_page_table_test.c b/tools/test= ing/selftests/kvm/kvm_page_table_test.c index f42c6ac6d71d..20533c48ba3d 100644 --- a/tools/testing/selftests/kvm/kvm_page_table_test.c +++ b/tools/testing/selftests/kvm/kvm_page_table_test.c @@ -289,7 +289,6 @@ static struct kvm_vm *pre_init_before_test(enum vm_gues= t_mode mode, void *arg) host_test_mem =3D addr_gpa2hva(vm, (vm_paddr_t)guest_test_phys_mem); =20 /* Export shared structure test_args to guest */ - ucall_init(vm, NULL); sync_global_to_guest(vm, test_args); =20 ret =3D sem_init(&test_stage_updated, 0, 0); diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testin= g/selftests/kvm/lib/aarch64/ucall.c index f214f5cc53d3..f02ae27c3e43 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c +++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c @@ -8,60 +8,12 @@ =20 static vm_vaddr_t *ucall_exit_mmio_addr; =20 -static bool ucall_mmio_init(struct kvm_vm *vm, vm_paddr_t gpa) +void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) { - if (kvm_userspace_memory_region_find(vm, gpa, gpa + 1)) - return false; + virt_pg_map(vm, mmio_gpa, mmio_gpa); =20 - virt_pg_map(vm, gpa, gpa); - - ucall_exit_mmio_addr =3D (vm_vaddr_t *)gpa; + ucall_exit_mmio_addr =3D (vm_vaddr_t *)mmio_gpa; sync_global_to_guest(vm, ucall_exit_mmio_addr); - - return true; -} - -void ucall_arch_init(struct kvm_vm *vm, void *arg) -{ - vm_paddr_t gpa, start, end, step, offset; - unsigned int bits; - bool ret; - - if (arg) { - gpa =3D (vm_paddr_t)arg; - ret =3D ucall_mmio_init(vm, gpa); - TEST_ASSERT(ret, "Can't set ucall mmio address to %lx", gpa); - return; - } - - /* - * Find an address within the allowed physical and virtual address - * spaces, that does _not_ have a KVM memory region associated with - * it. Identity mapping an address like this allows the guest to - * access it, but as KVM doesn't know what to do with it, it - * will assume it's something userspace handles and exit with - * KVM_EXIT_MMIO. Well, at least that's how it works for AArch64. - * Here we start with a guess that the addresses around 5/8th - * of the allowed space are unmapped and then work both down and - * up from there in 1/16th allowed space sized steps. - * - * Note, we need to use VA-bits - 1 when calculating the allowed - * virtual address space for an identity mapping because the upper - * half of the virtual address space is the two's complement of the - * lower and won't match physical addresses. - */ - bits =3D vm->va_bits - 1; - bits =3D min(vm->pa_bits, bits); - end =3D 1ul << bits; - start =3D end * 5 / 8; - step =3D end / 16; - for (offset =3D 0; offset < end - start; offset +=3D step) { - if (ucall_mmio_init(vm, start - offset)) - return; - if (ucall_mmio_init(vm, start + offset)) - return; - } - TEST_FAIL("Can't find a ucall mmio address"); } =20 void ucall_arch_uninit(struct kvm_vm *vm) diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 9889fe0d8919..846f9f6c5a17 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -292,6 +292,7 @@ struct kvm_vm *__vm_create(enum vm_guest_mode mode, uin= t32_t nr_runnable_vcpus, { uint64_t nr_pages =3D vm_nr_pages_required(mode, nr_runnable_vcpus, nr_extra_pages); + struct userspace_mem_region *slot0; struct kvm_vm *vm; =20 vm =3D ____vm_create(mode, nr_pages); @@ -301,6 +302,16 @@ struct kvm_vm *__vm_create(enum vm_guest_mode mode, ui= nt32_t nr_runnable_vcpus, #ifdef __x86_64__ vm_create_irqchip(vm); #endif + + /* + * TODO: Add proper defines to protect the library's memslots, and then + * carve out memslot1 for the ucall MMIO address. KVM treats writes to + * read-only memslots as MMIO, and creating a read-only memslot for the + * MMIO region would prevent silently clobbering the MMIO region. + */ + slot0 =3D memslot2region(vm, 0); + ucall_init(vm, slot0->region.guest_phys_addr + slot0->region.memory_size); + return vm; } =20 diff --git a/tools/testing/selftests/kvm/lib/perf_test_util.c b/tools/testi= ng/selftests/kvm/lib/perf_test_util.c index 9618b37c66f7..5161fa68cdf3 100644 --- a/tools/testing/selftests/kvm/lib/perf_test_util.c +++ b/tools/testing/selftests/kvm/lib/perf_test_util.c @@ -209,8 +209,6 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode m= ode, int nr_vcpus, perf_test_setup_nested(vm, nr_vcpus, vcpus); } =20 - ucall_init(vm, NULL); - /* Export the shared variables to the guest. */ sync_global_to_guest(vm, perf_test_args); =20 diff --git a/tools/testing/selftests/kvm/lib/riscv/ucall.c b/tools/testing/= selftests/kvm/lib/riscv/ucall.c index 37e091d4366e..c58ecb8a0981 100644 --- a/tools/testing/selftests/kvm/lib/riscv/ucall.c +++ b/tools/testing/selftests/kvm/lib/riscv/ucall.c @@ -10,7 +10,7 @@ #include "kvm_util.h" #include "processor.h" =20 -void ucall_arch_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) { } =20 diff --git a/tools/testing/selftests/kvm/lib/s390x/ucall.c b/tools/testing/= selftests/kvm/lib/s390x/ucall.c index 0f695a031d35..208f0f04299b 100644 --- a/tools/testing/selftests/kvm/lib/s390x/ucall.c +++ b/tools/testing/selftests/kvm/lib/s390x/ucall.c @@ -6,7 +6,7 @@ */ #include "kvm_util.h" =20 -void ucall_arch_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) { } =20 diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing= /selftests/kvm/lib/x86_64/ucall.c index ead9946399ab..016a0487cf72 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c +++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c @@ -8,7 +8,7 @@ =20 #define UCALL_PIO_PORT ((uint16_t)0x1000) =20 -void ucall_arch_init(struct kvm_vm *vm, void *arg) +void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) { } =20 diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testin= g/selftests/kvm/memslot_perf_test.c index 44995446d942..4ed5acd74278 100644 --- a/tools/testing/selftests/kvm/memslot_perf_test.c +++ b/tools/testing/selftests/kvm/memslot_perf_test.c @@ -277,7 +277,6 @@ static bool prepare_vm(struct vm_data *data, int nslots= , uint64_t *maxslots, TEST_ASSERT(data->hva_slots, "malloc() fail"); =20 data->vm =3D __vm_create_with_one_vcpu(&data->vcpu, mempages, guest_code); - ucall_init(data->vm, NULL); =20 pr_info_v("Adding slots 1..%i, each slot with %"PRIu64" pages + %"PRIu64"= extra pages last\n", max_mem_slots - 1, data->pages_per_slot, rempages); diff --git a/tools/testing/selftests/kvm/rseq_test.c b/tools/testing/selfte= sts/kvm/rseq_test.c index fac248a43666..8dc745effb5e 100644 --- a/tools/testing/selftests/kvm/rseq_test.c +++ b/tools/testing/selftests/kvm/rseq_test.c @@ -224,7 +224,6 @@ int main(int argc, char *argv[]) * CPU affinity. */ vm =3D vm_create_with_one_vcpu(&vcpu, guest_code); - ucall_init(vm, NULL); =20 pthread_create(&migration_thread, NULL, migration_worker, (void *)(unsigned long)gettid()); diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selft= ests/kvm/steal_time.c index db8967f1a17b..c87f38712073 100644 --- a/tools/testing/selftests/kvm/steal_time.c +++ b/tools/testing/selftests/kvm/steal_time.c @@ -266,7 +266,6 @@ int main(int ac, char **av) gpages =3D vm_calc_num_guest_pages(VM_MODE_DEFAULT, STEAL_TIME_SIZE * NR_= VCPUS); vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, ST_GPA_BASE, 1, gpa= ges, 0); virt_map(vm, ST_GPA_BASE, ST_GPA_BASE, gpages); - ucall_init(vm, NULL); =20 TEST_REQUIRE(is_steal_time_supported(vcpus[0])); =20 diff --git a/tools/testing/selftests/kvm/system_counter_offset_test.c b/too= ls/testing/selftests/kvm/system_counter_offset_test.c index 1c274933912b..7f5b330b6a1b 100644 --- a/tools/testing/selftests/kvm/system_counter_offset_test.c +++ b/tools/testing/selftests/kvm/system_counter_offset_test.c @@ -121,7 +121,6 @@ int main(void) =20 vm =3D vm_create_with_one_vcpu(&vcpu, guest_main); check_preconditions(vcpu); - ucall_init(vm, NULL); =20 enter_guest(vcpu); kvm_vm_free(vm); --=20 2.37.1.595.g718a3a8f04-goog From nobody Wed Apr 8 02:48:30 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 09088C32774 for ; Wed, 24 Aug 2022 03:21:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234521AbiHXDVs (ORCPT ); Tue, 23 Aug 2022 23:21:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36574 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234261AbiHXDV1 (ORCPT ); Tue, 23 Aug 2022 23:21:27 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2D8447FE7D for ; Tue, 23 Aug 2022 20:21:26 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id m11-20020a17090a3f8b00b001fabfce6a26so169366pjc.4 for ; Tue, 23 Aug 2022 20:21:26 -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=DiPDkyCUU5+qWi0FAGBrmfRDeC2PU2rAf87l6jKus4Q=; b=XvXBevlrlAqE9wagoH125syNrQYxrpHCiRlRfiVQtu1MdNipV2GG0TAviWCkY42kue 40hfNKd+srF0kxrbk+L6cIyjcvRD8ldiLVaaVnTF7/0DWZuQLDQlKmMKu1ugP09CeNj6 VfX9VSOzSDrnlZamHjfahcZ2qWLNHssJ6Tq+/c4s295toNWRhLpMaKG2PErS9+FS8eu/ nEwvow02yLb8KzgPd+H/QmXmd4FUVqVHY6f7qsUkwmsM976gLKCuj3wk6E+/Ec1o7Qk2 rSKdgFoFxqyd41Hj6wSl65wgpFaa3s0g/kZVmRXjxDr+uNytf2U5o026FzYj9bwJFc5X barw== 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=DiPDkyCUU5+qWi0FAGBrmfRDeC2PU2rAf87l6jKus4Q=; b=l9JdAAElbWJcyMUrOgtPES/zctDO6a9gShFzkW5YLvZ7zXmOGCQlpphEUU9Gcd6wao yKT/16P96FxkZ6gurRj8YMnpd4ddxlGjR/Usc45t1Gxf/i1qJ4pY1j/XzP20tYTLtsEr 2ucbxLWKuk7wIvBTbA+sYgKYHXn5S/KLNvepy9bhH5pV2yG6ukGG+W2moDUW0X5zSPCY ly8xBPvlXWJ8sc/zZjlVf2OVMdX/1JfzURcA4FvYHIu5Ah8Sp6j8noh8pzMEO95CJT1g eGMnRLSOt9BwfcgBXJuUV34d+S1/o4mBEfMRn8YAeXrRKrEqHDo8k3wv/65XvSg8dq9o lArA== X-Gm-Message-State: ACgBeo2AbLqPiX4orLg+gSO5FDo5qd0SdGXHY2hUsVNsbKX8a25+zOzl CljGLN9e0afwE9teSCKlo361+WDTCQg= X-Google-Smtp-Source: AA6agR7hkMAlHzZjMos7RFjUz8V/HjO4UccQUnDLH/uwK3wpKW33JaEUPX9HlB35rLdBTEQmTcaewjVzFKc= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6a00:301c:b0:52d:bff9:5004 with SMTP id ay28-20020a056a00301c00b0052dbff95004mr27937449pfb.84.1661311285738; Tue, 23 Aug 2022 20:21:25 -0700 (PDT) Reply-To: Sean Christopherson Date: Wed, 24 Aug 2022 03:21:13 +0000 In-Reply-To: <20220824032115.3563686-1-seanjc@google.com> Message-Id: <20220824032115.3563686-5-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 4/6] tools: Add atomic_test_and_set_bit() 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" From: Peter Gonda Add x86 and generic implementations of atomic_test_and_set_bit() to allow KVM selftests to atomically manage bitmaps. Note, the generic version is taken from arch_test_and_set_bit() as of commit 415d83249709 ("locking/atomic: Make test_and_*_bit() ordered on failure"). Signed-off-by: Peter Gonda Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- tools/arch/x86/include/asm/atomic.h | 7 +++++++ tools/include/asm-generic/atomic-gcc.h | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/tools/arch/x86/include/asm/atomic.h b/tools/arch/x86/include/a= sm/atomic.h index 1f5e26aae9fc..01cc27ec4520 100644 --- a/tools/arch/x86/include/asm/atomic.h +++ b/tools/arch/x86/include/asm/atomic.h @@ -8,6 +8,7 @@ =20 #define LOCK_PREFIX "\n\tlock; " =20 +#include #include =20 /* @@ -70,4 +71,10 @@ static __always_inline int atomic_cmpxchg(atomic_t *v, i= nt old, int new) return cmpxchg(&v->counter, old, new); } =20 +static inline int atomic_test_and_set_bit(long nr, unsigned long *addr) +{ + GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(bts), *addr, "Ir", nr, "%0", "c"); + +} + #endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */ diff --git a/tools/include/asm-generic/atomic-gcc.h b/tools/include/asm-gen= eric/atomic-gcc.h index 4c1966f7c77a..6daa68bf5b9e 100644 --- a/tools/include/asm-generic/atomic-gcc.h +++ b/tools/include/asm-generic/atomic-gcc.h @@ -4,6 +4,7 @@ =20 #include #include +#include =20 /* * Atomic operations that C can't guarantee us. Useful for @@ -69,4 +70,15 @@ static inline int atomic_cmpxchg(atomic_t *v, int oldval= , int newval) return cmpxchg(&(v)->counter, oldval, newval); } =20 +static inline int atomic_test_and_set_bit(long nr, unsigned long *addr) +{ + unsigned long mask =3D BIT_MASK(nr); + long old; + + addr +=3D BIT_WORD(nr); + + old =3D __sync_fetch_and_or(addr, mask); + return !!(old & mask); +} + #endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */ --=20 2.37.1.595.g718a3a8f04-goog From nobody Wed Apr 8 02:48:30 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 From nobody Wed Apr 8 02:48:30 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 353D7C32774 for ; Wed, 24 Aug 2022 03:22:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234612AbiHXDWH (ORCPT ); Tue, 23 Aug 2022 23:22:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36574 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234308AbiHXDVb (ORCPT ); Tue, 23 Aug 2022 23:21:31 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 623F682D12 for ; Tue, 23 Aug 2022 20:21:30 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id q73-20020a17090a1b4f00b001fb633703fcso167565pjq.5 for ; Tue, 23 Aug 2022 20:21:30 -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=ID0LEN54g4SKI12YiNIJ9Ou03DYNCbuKZq4SDDiKjA0=; b=MIyLxnBhPREuMmCFGfdXhP05WPcmtjb1vwHFIbVVRFVs4jR2fonrTaIHNxayLeWFvI vRIjETuqqQtEl/oOfOlexNo6GSKg/65OOqECKXQJ9aAlA6XqJOBIwRcWgqfXOosk9D8j VPRBAhNwIIePzlmHjVuRHYhBIqcj0KGWUssusNH9xb3aVQ1PlhWKDMm/JNNBiztkl5/a dYhqP9ERH/fzgi8b5B88DLfvDynm0gh2FDpbyJuPInhEFP5GUhGS+IgiPBueJYfLLNjJ Ba+i6EfGZxmNdAYIRxaAyRtMlp9m8RqE/9c+o55oeMkydrSq6gQyilcJhm8JhRVM3xYo aHYg== 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=ID0LEN54g4SKI12YiNIJ9Ou03DYNCbuKZq4SDDiKjA0=; b=7+mWxzWOX/AMVFZSsAFLnveE6B48j4BPcM1kW5bR8DJoQBK5Zn5XJ+tA6CmJlvJI1b k4BcRscwY+xIYVSJXa0Lf1tY66btBKQo22NPBxFeSjDSg4wnTRmi4itI6Oc5cpdrvq4d CECOH/Z6uSQd7xFzptVdLt5RiIDeSsYV5gaq5rTnO43ZZqWZNCBBQcbRcMvYPmvdzU8T 0t614o/CHHk3JeSEyo+yVl4IT0omLToeP1bPhNNrpikgNE8sCkSbo9lXhZMAqrNHmAXN 6TOeaiMwcZcd53V7h/q8pRyKefuxpgscGw1itcEPn1p68n+iYbFga695Duov3NcPGp/4 AwDw== X-Gm-Message-State: ACgBeo3hM/Jlx3GivCEh8s83SGX99uxfCF5VaiAk/rdhOGBLDwdHDvlq yhGES0PLCtIAPfFawGQQqEijWTcyY2c= X-Google-Smtp-Source: AA6agR7qJXZ060IVlHFYw5MostRiExgVNSpQSb5aqpoFfJhg5KBymx9MNvVNgiIbEitImrJ5lWzWN1hYAyQ= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a17:90b:a14:b0:1fa:bc6e:e5e8 with SMTP id gg20-20020a17090b0a1400b001fabc6ee5e8mr154528pjb.1.1661311289328; Tue, 23 Aug 2022 20:21:29 -0700 (PDT) Reply-To: Sean Christopherson Date: Wed, 24 Aug 2022 03:21:15 +0000 In-Reply-To: <20220824032115.3563686-1-seanjc@google.com> Message-Id: <20220824032115.3563686-7-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 6/6] KVM: selftests: Add ucall pool based implementation 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" From: Peter Gonda To play nice with guests whose stack memory is encrypted, e.g. AMD SEV, introduce a new "ucall pool" implementation that passes the ucall struct via dedicated memory (which can be mapped shared, a.k.a. as plain text). Because not all architectures have access to the vCPU index in the guest, use a bitmap with atomic accesses to track which entries in the pool are free/used. A list+lock could also work in theory, but synchronizing the individual pointers to the guest would be a mess. Note, there's no need to rewalk the bitmap to ensure success. If all vCPUs are simply allocating, success is guaranteed because there are enough entries for all vCPUs. If one or more vCPUs are freeing and then reallocating, success is guaranteed because vCPUs _always_ walk the bitmap from 0=3D>N; if vCPU frees an entry and then wins a race to re-allocate, then either it will consume the entry it just freed (bit is the first free bit), or the losing vCPU is guaranteed to see the freed bit (winner consumes an earlier bit, which the loser hasn't yet visited). Signed-off-by: Peter Gonda Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- .../selftests/kvm/include/ucall_common.h | 14 ++-- .../testing/selftests/kvm/lib/aarch64/ucall.c | 7 +- tools/testing/selftests/kvm/lib/riscv/ucall.c | 2 +- tools/testing/selftests/kvm/lib/s390x/ucall.c | 2 +- .../testing/selftests/kvm/lib/ucall_common.c | 83 ++++++++++++++++++- .../testing/selftests/kvm/lib/x86_64/ucall.c | 2 +- 6 files changed, 89 insertions(+), 21 deletions(-) diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/tes= ting/selftests/kvm/include/ucall_common.h index 8077a6d8b1ba..360397e3cbf5 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -22,6 +22,9 @@ enum { struct ucall { uint64_t cmd; uint64_t args[UCALL_MAX_ARGS]; + + /* Host virtual address of this struct. */ + struct ucall *hva; }; =20 void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa); @@ -32,15 +35,8 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); void ucall(uint64_t cmd, int nargs, ...); uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); =20 -static inline void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) -{ - ucall_arch_init(vm, mmio_gpa); -} - -static inline void ucall_uninit(struct kvm_vm *vm) -{ - ucall_arch_uninit(vm); -} +void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa); +void ucall_uninit(struct kvm_vm *vm); =20 #define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \ ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4) diff --git a/tools/testing/selftests/kvm/lib/aarch64/ucall.c b/tools/testin= g/selftests/kvm/lib/aarch64/ucall.c index acb47c813477..5f79c9fc72d7 100644 --- a/tools/testing/selftests/kvm/lib/aarch64/ucall.c +++ b/tools/testing/selftests/kvm/lib/aarch64/ucall.c @@ -43,12 +43,9 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) =20 if (run->exit_reason =3D=3D KVM_EXIT_MMIO && run->mmio.phys_addr =3D=3D vcpu->vm->ucall_mmio_addr) { - vm_vaddr_t gva; - - TEST_ASSERT(run->mmio.is_write && run->mmio.len =3D=3D 8, + TEST_ASSERT(run->mmio.is_write && run->mmio.len =3D=3D sizeof(uint64_t), "Unexpected ucall exit mmio address access"); - memcpy(&gva, run->mmio.data, sizeof(gva)); - return addr_gva2hva(vcpu->vm, gva); + return (void *)(*((uint64_t *)run->mmio.data)); } =20 return NULL; diff --git a/tools/testing/selftests/kvm/lib/riscv/ucall.c b/tools/testing/= selftests/kvm/lib/riscv/ucall.c index c58ecb8a0981..9526a200d038 100644 --- a/tools/testing/selftests/kvm/lib/riscv/ucall.c +++ b/tools/testing/selftests/kvm/lib/riscv/ucall.c @@ -59,7 +59,7 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) run->riscv_sbi.extension_id =3D=3D KVM_RISCV_SELFTESTS_SBI_EXT) { switch (run->riscv_sbi.function_id) { case KVM_RISCV_SELFTESTS_SBI_UCALL: - return addr_gva2hva(vcpu->vm, run->riscv_sbi.args[0]); + return (void *)run->riscv_sbi.args[0]; case KVM_RISCV_SELFTESTS_SBI_UNEXP: vcpu_dump(stderr, vcpu, 2); TEST_ASSERT(0, "Unexpected trap taken by guest"); diff --git a/tools/testing/selftests/kvm/lib/s390x/ucall.c b/tools/testing/= selftests/kvm/lib/s390x/ucall.c index 208f0f04299b..1efdeac60b4e 100644 --- a/tools/testing/selftests/kvm/lib/s390x/ucall.c +++ b/tools/testing/selftests/kvm/lib/s390x/ucall.c @@ -30,7 +30,7 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) (run->s390_sieic.ipb >> 16) =3D=3D 0x501) { int reg =3D run->s390_sieic.ipa & 0xf; =20 - return addr_gva2hva(vcpu->vm, run->s.regs.gprs[reg]); + return (void *)run->s.regs.gprs[reg]; } return NULL; } diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing= /selftests/kvm/lib/ucall_common.c index ced480860746..29f8cb614382 100644 --- a/tools/testing/selftests/kvm/lib/ucall_common.c +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -1,22 +1,97 @@ // SPDX-License-Identifier: GPL-2.0-only #include "kvm_util.h" +#include "linux/types.h" +#include "linux/bitmap.h" +#include "linux/atomic.h" + +struct ucall_header { + DECLARE_BITMAP(in_use, KVM_MAX_VCPUS); + struct ucall ucalls[KVM_MAX_VCPUS]; +}; + +/* + * 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 struct ucall_header *ucall_pool; + +static void ucall_set_pool(struct kvm_vm *vm, struct ucall_header *val) +{ + atomic_sync_global_pointer_to_guest(vm, ucall_pool, val); +} + +void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) +{ + struct ucall_header *hdr; + struct ucall *uc; + vm_vaddr_t vaddr; + int i; + + vaddr =3D vm_vaddr_alloc(vm, sizeof(*hdr), KVM_UTIL_MIN_VADDR); + hdr =3D (struct ucall_header *)addr_gva2hva(vm, vaddr); + memset(hdr, 0, sizeof(*hdr)); + + for (i =3D 0; i < KVM_MAX_VCPUS; ++i) { + uc =3D &hdr->ucalls[i]; + uc->hva =3D uc; + } + + ucall_set_pool(vm, (void *)vaddr); + + ucall_arch_init(vm, mmio_gpa); +} + +void ucall_uninit(struct kvm_vm *vm) +{ + ucall_set_pool(vm, NULL); + + ucall_arch_uninit(vm); +} + +static struct ucall *ucall_alloc(void) +{ + struct ucall *uc; + int i; + + GUEST_ASSERT(ucall_pool && ucall_pool->in_use); + + for (i =3D 0; i < KVM_MAX_VCPUS; ++i) { + if (!atomic_test_and_set_bit(i, ucall_pool->in_use)) { + uc =3D &ucall_pool->ucalls[i]; + memset(uc->args, 0, sizeof(uc->args)); + return uc; + } + } + GUEST_ASSERT(0); + return NULL; +} + +static noinline void ucall_free(struct ucall *uc) +{ + /* Beware, here be pointer arithmetic. */ + clear_bit(uc - ucall_pool->ucalls, ucall_pool->in_use); +} =20 void ucall(uint64_t cmd, int nargs, ...) { - struct ucall uc =3D {}; + struct ucall *uc; va_list va; int i; =20 - WRITE_ONCE(uc.cmd, cmd); + uc =3D ucall_alloc(); + + WRITE_ONCE(uc->cmd, cmd); =20 nargs =3D min(nargs, UCALL_MAX_ARGS); =20 va_start(va, nargs); for (i =3D 0; i < nargs; ++i) - WRITE_ONCE(uc.args[i], va_arg(va, uint64_t)); + WRITE_ONCE(uc->args[i], va_arg(va, uint64_t)); va_end(va); =20 - ucall_arch_do_ucall((vm_vaddr_t)&uc); + ucall_arch_do_ucall((vm_vaddr_t)uc->hva); + + ucall_free(uc); } =20 uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing= /selftests/kvm/lib/x86_64/ucall.c index 016a0487cf72..82e7f6ae7811 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c +++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c @@ -30,7 +30,7 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) struct kvm_regs regs; =20 vcpu_regs_get(vcpu, ®s); - return addr_gva2hva(vcpu->vm, regs.rdi); + return (void *)regs.rdi; } return NULL; } --=20 2.37.1.595.g718a3a8f04-goog