From nobody Thu Jan 1 11:02:24 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 60903C25B47 for ; Mon, 23 Oct 2023 19:15:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232230AbjJWTPx (ORCPT ); Mon, 23 Oct 2023 15:15:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43020 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231827AbjJWTPo (ORCPT ); Mon, 23 Oct 2023 15:15:44 -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 D1B3594 for ; Mon, 23 Oct 2023 12:15:41 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-5a7aa816c5bso50607777b3.1 for ; Mon, 23 Oct 2023 12:15:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1698088541; x=1698693341; darn=vger.kernel.org; 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=l32i13KcogKJQmerzZJpCfXVsXKJyNALXo7FvnlM4Uc=; b=ERgrCEMBpKe68DyX3DohbCPwr3jF6VlzXxTabQIhuY/dfvAmPYbO2SMMpjxwARcJYI FQ7D93D5mv4TcQMFlNpvw8sAFE2ZtjjlH2BXbWkgJfz/vd2u2HxgrHeegJDLhuetE7dW derthwJITwauhvGq7eN2RepX/G60Yrf4FX+PeTcUeVBatVGl4By9x8aWCfOAoPzOxWXY L/9ueKGj42k/lFb7u2+SiR7qDzqnl41X9jkR7Sdyaia0G7hc4wiB2615lWJ8i5gmzJAY OF5CLeCXPx5QQMDPWJi2+BI//ZEYITsK/uqHF38JEf/QaR0f+FYcZuNvRoyoB5OHNQWI 35Nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698088541; x=1698693341; 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=l32i13KcogKJQmerzZJpCfXVsXKJyNALXo7FvnlM4Uc=; b=E4tHM1Y7DhjV/AwO3tL/ib6BCJg5qis9XgrFLjSUgxbEZAWhhIii4xwznbVFlLSTiu Ylv1Od1hjLFN92mXwSFBTzIfdPqOsSc47lOtzV8t2W6XB643WvAS4hcVSOhB/Bptx848 kCRdfp0Trxvf2fmlvVgxVx//Idxw8gKEIBc0Bjplot/1rGyzX3roXu25064g5xtUGDUc AqkY1sAeDJfojx6EDb2QAXcUe/DGZvBLbg0UNAoI81T9GuzUO0cYcfRsOMxSn7JzsXs0 gGUn5QfOeTmW4fD/jYf66oAhgh3VGWd6jOM94XknTgrNnB7rmu3C54MLVvasCZ9zdisy ReuA== X-Gm-Message-State: AOJu0YyrwrwxFKhNkDqnwH0tddnmYaQqnl3IeW8SIjG4kLFHFERO4fkf JJJ/zH7HsQpVkkvyeaTH+kNv6pPPTU4= X-Google-Smtp-Source: AGHT+IEQcCsMq3tPPe7PSzyt3r8+n1h3f3utWlxgcaG+hWrHTq9qJU45bmze9KHC5eWQQHiBs0MeF2KWKD4= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a25:ad8e:0:b0:d90:e580:88e5 with SMTP id z14-20020a25ad8e000000b00d90e58088e5mr175588ybi.10.1698088541059; Mon, 23 Oct 2023 12:15:41 -0700 (PDT) Reply-To: Sean Christopherson Date: Mon, 23 Oct 2023 12:15:30 -0700 In-Reply-To: <20231023191532.2405326-1-seanjc@google.com> Mime-Version: 1.0 References: <20231023191532.2405326-1-seanjc@google.com> X-Mailer: git-send-email 2.42.0.758.gaed0368e0e-goog Message-ID: <20231023191532.2405326-4-seanjc@google.com> Subject: [PATCH gmem 3/5] KVM: selftests: Let user specify nr of memslots in private mem conversion From: Sean Christopherson To: Sean Christopherson , Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Michael Roth Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Let the user specify the number of memslots in the private mem conversion test, i.e. don't require the number of memslots to be '1' or "nr_vcpus". Creating more memslots than vCPUs is particularly interesting, e.g. it can result in a single KVM_SET_MEMORY_ATTRIBUTES spanning multiple memslots. This also fixes an issue where the test will crash when running with multiple vCPUs but only a single memslot. To keep the math reasonable, align each vCPU's chunk to at least 2MiB (the size is 2MiB+4KiB), and require the total size to be cleanly divisible by the number of memslots. The goal is to be able to validate that KVM plays nice with multiple memslots, being able to create a truly arbitrary number of memslots doesn't add meaningful value, i.e. isn't worth the cost. Reported-by: Michael Roth Signed-off-by: Sean Christopherson --- .../kvm/x86_64/private_mem_conversions_test.c | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/private_mem_conversions_tes= t.c b/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c index c3992a295b5a..3f6d8d4dbc53 100644 --- a/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c +++ b/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c @@ -371,8 +371,10 @@ static void test_mem_conversions(enum vm_mem_backing_s= rc_type src_type, uint32_t * Allocate enough memory so that each vCPU's chunk of memory can be * naturally aligned with respect to the size of the backing store. */ - const size_t size =3D align_up(PER_CPU_DATA_SIZE, get_backing_src_pagesz(= src_type)); - const size_t memfd_size =3D size * nr_vcpus; + const size_t alignment =3D max_t(size_t, SZ_2M, get_backing_src_pagesz(sr= c_type)); + const size_t per_cpu_size =3D align_up(PER_CPU_DATA_SIZE, alignment); + const size_t memfd_size =3D per_cpu_size * nr_vcpus; + const size_t slot_size =3D memfd_size / nr_memslots; struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; pthread_t threads[KVM_MAX_VCPUS]; uint64_t gmem_flags; @@ -384,6 +386,9 @@ static void test_mem_conversions(enum vm_mem_backing_sr= c_type src_type, uint32_t .type =3D KVM_X86_SW_PROTECTED_VM, }; =20 + TEST_ASSERT(slot_size * nr_memslots =3D=3D memfd_size, + "The memfd size (0x%lx) needs to be cleanly divisible by the number = of memslots (%u)", + memfd_size, nr_memslots); vm =3D __vm_create_with_vcpus(shape, nr_vcpus, 0, guest_code, vcpus); =20 vm_enable_cap(vm, KVM_CAP_EXIT_HYPERCALL, (1 << KVM_HC_MAP_GPA_RANGE)); @@ -395,16 +400,20 @@ static void test_mem_conversions(enum vm_mem_backing_= src_type src_type, uint32_t memfd =3D vm_create_guest_memfd(vm, memfd_size, gmem_flags); =20 for (i =3D 0; i < nr_memslots; i++) - vm_mem_add(vm, src_type, BASE_DATA_GPA + size * i, - BASE_DATA_SLOT + i, size / vm->page_size, - KVM_MEM_PRIVATE, memfd, size * i); + vm_mem_add(vm, src_type, BASE_DATA_GPA + slot_size * i, + BASE_DATA_SLOT + i, slot_size / vm->page_size, + KVM_MEM_PRIVATE, memfd, slot_size * i); =20 for (i =3D 0; i < nr_vcpus; i++) { - uint64_t gpa =3D BASE_DATA_GPA + i * size; + uint64_t gpa =3D BASE_DATA_GPA + i * per_cpu_size; =20 vcpu_args_set(vcpus[i], 1, gpa); =20 - virt_map(vm, gpa, gpa, size / vm->page_size); + /* + * Map only what is needed so that an out-of-bounds access + * results #PF =3D> SHUTDOWN instead of data corruption. + */ + virt_map(vm, gpa, gpa, PER_CPU_DATA_SIZE / vm->page_size); =20 pthread_create(&threads[i], NULL, __test_mem_conversions, vcpus[i]); } @@ -432,29 +441,28 @@ static void test_mem_conversions(enum vm_mem_backing_= src_type src_type, uint32_t static void usage(const char *cmd) { puts(""); - printf("usage: %s [-h] [-m] [-s mem_type] [-n nr_vcpus]\n", cmd); + printf("usage: %s [-h] [-m nr_memslots] [-s mem_type] [-n nr_vcpus]\n", c= md); puts(""); backing_src_help("-s"); puts(""); puts(" -n: specify the number of vcpus (default: 1)"); puts(""); - puts(" -m: use multiple memslots (default: 1)"); + puts(" -m: specify the number of memslots (default: 1)"); puts(""); } =20 int main(int argc, char *argv[]) { enum vm_mem_backing_src_type src_type =3D DEFAULT_VM_MEM_SRC; - bool use_multiple_memslots =3D false; + uint32_t nr_memslots =3D 1; uint32_t nr_vcpus =3D 1; - uint32_t nr_memslots; int opt; =20 TEST_REQUIRE(kvm_has_cap(KVM_CAP_GUEST_MEMFD)); TEST_REQUIRE(kvm_has_cap(KVM_CAP_EXIT_HYPERCALL)); TEST_REQUIRE(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_V= M)); =20 - while ((opt =3D getopt(argc, argv, "hms:n:")) !=3D -1) { + while ((opt =3D getopt(argc, argv, "hm:s:n:")) !=3D -1) { switch (opt) { case 's': src_type =3D parse_backing_src_type(optarg); @@ -463,7 +471,7 @@ int main(int argc, char *argv[]) nr_vcpus =3D atoi_positive("nr_vcpus", optarg); break; case 'm': - use_multiple_memslots =3D true; + nr_memslots =3D atoi_positive("nr_memslots", optarg); break; case 'h': default: @@ -472,8 +480,6 @@ int main(int argc, char *argv[]) } } =20 - nr_memslots =3D use_multiple_memslots ? nr_vcpus : 1; - test_mem_conversions(src_type, nr_vcpus, nr_memslots); =20 return 0; --=20 2.42.0.758.gaed0368e0e-goog