From nobody Tue Apr 7 15:55:20 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 9A2F0C43217 for ; Tue, 18 Oct 2022 04:05:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230244AbiJREFa (ORCPT ); Tue, 18 Oct 2022 00:05:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44208 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230140AbiJREFT (ORCPT ); Tue, 18 Oct 2022 00:05:19 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 697C53DBF9 for ; Mon, 17 Oct 2022 21:05:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1666065915; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Vvc9nSeTOx+R9O1KRdNsOErR2cLTeHQp0FKXCgftjxs=; b=UtvkP4flYRfwfRdy8uEHwx3gOiinNAjGNhHneE4s8cSC6+6NxsrBiJp+QcNp1kb9k9rDNd 5JCPg55QIx6cE1kMMkykbCaVq/xiwiEwSOnvp0bl9aPXWgapeMlDLPWk3mFXVLvZ9noiW2 LeVZ/XH2Rp6HWLL7k2jsIKB7Hhh1Zj8= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-528-zSOD3oF5P3itk5-d8L2GxA-1; Tue, 18 Oct 2022 00:05:10 -0400 X-MC-Unique: zSOD3oF5P3itk5-d8L2GxA-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5273229AB3E9; Tue, 18 Oct 2022 04:05:10 +0000 (UTC) Received: from gshan.redhat.com (vpn2-54-70.bne.redhat.com [10.64.54.70]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8F55E2166B41; Tue, 18 Oct 2022 04:05:04 +0000 (UTC) From: Gavin Shan To: kvmarm@lists.linux.dev Cc: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, ajones@ventanamicro.com, pbonzini@redhat.com, maz@kernel.org, shuah@kernel.org, oliver.upton@linux.dev, mail@maciej.szmigiero.name, maciej.szmigiero@oracle.com, seanjc@google.com, peterx@redhat.com, ricarkol@google.com, zhenyzha@redhat.com, shan.gavin@gmail.com Subject: [PATCH v2 1/6] KVM: selftests: memslot_perf_test: Use data->nslots in prepare_vm() Date: Tue, 18 Oct 2022 12:04:49 +0800 Message-Id: <20221018040454.405719-2-gshan@redhat.com> In-Reply-To: <20221018040454.405719-1-gshan@redhat.com> References: <20221018040454.405719-1-gshan@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" In prepare_vm(), 'data->nslots' is assigned with 'max_mem_slots - 1' at the beginning, meaning they are interchangeable. Use 'data->nslots' isntead of 'max_mem_slots - 1'. With this, it becomes easier to move the logic of probing number of slots into upper layer in subsequent patches. No functional change intended. Signed-off-by: Gavin Shan --- tools/testing/selftests/kvm/memslot_perf_test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testin= g/selftests/kvm/memslot_perf_test.c index 44995446d942..231cc8449c2e 100644 --- a/tools/testing/selftests/kvm/memslot_perf_test.c +++ b/tools/testing/selftests/kvm/memslot_perf_test.c @@ -280,14 +280,14 @@ static bool prepare_vm(struct vm_data *data, int nslo= ts, uint64_t *maxslots, 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); + data->nslots, data->pages_per_slot, rempages); =20 clock_gettime(CLOCK_MONOTONIC, &tstart); - for (slot =3D 1, guest_addr =3D MEM_GPA; slot < max_mem_slots; slot++) { + for (slot =3D 1, guest_addr =3D MEM_GPA; slot <=3D data->nslots; slot++) { uint64_t npages; =20 npages =3D data->pages_per_slot; - if (slot =3D=3D max_mem_slots - 1) + if (slot =3D=3D data->nslots) npages +=3D rempages; =20 vm_userspace_mem_region_add(data->vm, VM_MEM_SRC_ANONYMOUS, @@ -297,12 +297,12 @@ static bool prepare_vm(struct vm_data *data, int nslo= ts, uint64_t *maxslots, } *slot_runtime =3D timespec_elapsed(tstart); =20 - for (slot =3D 0, guest_addr =3D MEM_GPA; slot < max_mem_slots - 1; slot++= ) { + for (slot =3D 0, guest_addr =3D MEM_GPA; slot < data->nslots; slot++) { uint64_t npages; uint64_t gpa; =20 npages =3D data->pages_per_slot; - if (slot =3D=3D max_mem_slots - 2) + if (slot =3D=3D data->nslots - 1) npages +=3D rempages; =20 gpa =3D vm_phy_pages_alloc(data->vm, npages, guest_addr, --=20 2.23.0 From nobody Tue Apr 7 15:55:20 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 4D8BCC4332F for ; Tue, 18 Oct 2022 04:05:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230262AbiJREFh (ORCPT ); Tue, 18 Oct 2022 00:05:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45670 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230238AbiJREFa (ORCPT ); Tue, 18 Oct 2022 00:05:30 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5585E52FF2 for ; Mon, 17 Oct 2022 21:05:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1666065920; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9FjkKJ4RB0wBhJUFjtqAZ3VQdnrJF4akYRPmacZ3lG8=; b=bFxN5F/75k0NzoOyPgFqnNI/FVTZslDAVD3xa/y120K6g5JS6cwuc5UUFj0cZzpceV50uO ETY0unH+c2XDsHnxfRm2kdO1Q4F4Bn07Qi2ViAUk16dHrOw676K6JPkKrg1uFLk0lBgcqi sKgOYp6/kBfq3ulI+qtsxJv2qAkn5nE= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-265-KFKb15AGP3Oh9hIgeZ4WZw-1; Tue, 18 Oct 2022 00:05:17 -0400 X-MC-Unique: KFKb15AGP3Oh9hIgeZ4WZw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A7B4238041CB; Tue, 18 Oct 2022 04:05:16 +0000 (UTC) Received: from gshan.redhat.com (vpn2-54-70.bne.redhat.com [10.64.54.70]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E9C7B2166B41; Tue, 18 Oct 2022 04:05:10 +0000 (UTC) From: Gavin Shan To: kvmarm@lists.linux.dev Cc: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, ajones@ventanamicro.com, pbonzini@redhat.com, maz@kernel.org, shuah@kernel.org, oliver.upton@linux.dev, mail@maciej.szmigiero.name, maciej.szmigiero@oracle.com, seanjc@google.com, peterx@redhat.com, ricarkol@google.com, zhenyzha@redhat.com, shan.gavin@gmail.com Subject: [PATCH v2 2/6] KVM: selftests: memslot_perf_test: Consolidate loop conditions in prepare_vm() Date: Tue, 18 Oct 2022 12:04:50 +0800 Message-Id: <20221018040454.405719-3-gshan@redhat.com> In-Reply-To: <20221018040454.405719-1-gshan@redhat.com> References: <20221018040454.405719-1-gshan@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" There are two loops in prepare_vm(), which have different conditions. 'slot' is treated as meory slot index in the first loop, but index of the host virtual address array in the second loop. It makes it a bit hard to understand the code. Change the usage of 'slot' in the second loop, to treat it as the memory slot index either. No functional change intended. Signed-off-by: Gavin Shan --- tools/testing/selftests/kvm/memslot_perf_test.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testin= g/selftests/kvm/memslot_perf_test.c index 231cc8449c2e..dcb492b3f27b 100644 --- a/tools/testing/selftests/kvm/memslot_perf_test.c +++ b/tools/testing/selftests/kvm/memslot_perf_test.c @@ -297,21 +297,20 @@ static bool prepare_vm(struct vm_data *data, int nslo= ts, uint64_t *maxslots, } *slot_runtime =3D timespec_elapsed(tstart); =20 - for (slot =3D 0, guest_addr =3D MEM_GPA; slot < data->nslots; slot++) { + for (slot =3D 1, guest_addr =3D MEM_GPA; slot <=3D data->nslots; slot++) { uint64_t npages; uint64_t gpa; =20 npages =3D data->pages_per_slot; - if (slot =3D=3D data->nslots - 1) + if (slot =3D=3D data->nslots) npages +=3D rempages; =20 - gpa =3D vm_phy_pages_alloc(data->vm, npages, guest_addr, - slot + 1); + gpa =3D vm_phy_pages_alloc(data->vm, npages, guest_addr, slot); TEST_ASSERT(gpa =3D=3D guest_addr, "vm_phy_pages_alloc() failed\n"); =20 - data->hva_slots[slot] =3D addr_gpa2hva(data->vm, guest_addr); - memset(data->hva_slots[slot], 0, npages * 4096); + data->hva_slots[slot - 1] =3D addr_gpa2hva(data->vm, guest_addr); + memset(data->hva_slots[slot - 1], 0, npages * 4096); =20 guest_addr +=3D npages * 4096; } --=20 2.23.0 From nobody Tue Apr 7 15:55:20 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 3D3C7C433FE for ; Tue, 18 Oct 2022 04:05:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230210AbiJREFv (ORCPT ); Tue, 18 Oct 2022 00:05:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46088 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230248AbiJREFo (ORCPT ); Tue, 18 Oct 2022 00:05:44 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7DA8A69F72 for ; Mon, 17 Oct 2022 21:05:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1666065930; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PqVmt5YoyTpdybpQLaBWLMwp2J8t1L+xxmd4ToLLOLQ=; b=GjxbN1d4hUg6Jkuow+zMndfVqEow9+nkUEYp/F+DOdA83tBHaWJjDgQofsrMlxbkDX6R+q 84UgyQ1ZtS0KfeT5nmER5g9lxf4wCTUqq2rp92SxHsmofgl67lfPFHmj8whIQaMKt0DlAR rXoHflJz+p5AUvKUApVQTwCVncs8sY4= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-629-Qa1Yv4GQM22PAcvLiooxIQ-1; Tue, 18 Oct 2022 00:05:23 -0400 X-MC-Unique: Qa1Yv4GQM22PAcvLiooxIQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 21DBB38041D0; Tue, 18 Oct 2022 04:05:23 +0000 (UTC) Received: from gshan.redhat.com (vpn2-54-70.bne.redhat.com [10.64.54.70]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 461312166B41; Tue, 18 Oct 2022 04:05:16 +0000 (UTC) From: Gavin Shan To: kvmarm@lists.linux.dev Cc: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, ajones@ventanamicro.com, pbonzini@redhat.com, maz@kernel.org, shuah@kernel.org, oliver.upton@linux.dev, mail@maciej.szmigiero.name, maciej.szmigiero@oracle.com, seanjc@google.com, peterx@redhat.com, ricarkol@google.com, zhenyzha@redhat.com, shan.gavin@gmail.com Subject: [PATCH v2 3/6] KVM: selftests: memslot_perf_test: Probe memory slots for once Date: Tue, 18 Oct 2022 12:04:51 +0800 Message-Id: <20221018040454.405719-4-gshan@redhat.com> In-Reply-To: <20221018040454.405719-1-gshan@redhat.com> References: <20221018040454.405719-1-gshan@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" prepare_vm() is called in every iteration and run. The allowed memory slots (KVM_CAP_NR_MEMSLOTS) are probed for multiple times. It's not free and unnecessary. Move the probing logic for the allowed memory slots to parse_args() for once, which is upper layer of prepare_vm(). No functional change intended. Signed-off-by: Gavin Shan --- .../testing/selftests/kvm/memslot_perf_test.c | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testin= g/selftests/kvm/memslot_perf_test.c index dcb492b3f27b..f0ea3f75b6e1 100644 --- a/tools/testing/selftests/kvm/memslot_perf_test.c +++ b/tools/testing/selftests/kvm/memslot_perf_test.c @@ -245,27 +245,17 @@ static bool prepare_vm(struct vm_data *data, int nslo= ts, uint64_t *maxslots, void *guest_code, uint64_t mempages, struct timespec *slot_runtime) { - uint32_t max_mem_slots; uint64_t rempages; uint64_t guest_addr; uint32_t slot; struct timespec tstart; struct sync_area *sync; =20 - max_mem_slots =3D kvm_check_cap(KVM_CAP_NR_MEMSLOTS); - TEST_ASSERT(max_mem_slots > 1, - "KVM_CAP_NR_MEMSLOTS should be greater than 1"); - TEST_ASSERT(nslots > 1 || nslots =3D=3D -1, - "Slot count cap should be greater than 1"); - if (nslots !=3D -1) - max_mem_slots =3D min(max_mem_slots, (uint32_t)nslots); - pr_info_v("Allowed number of memory slots: %"PRIu32"\n", max_mem_slots); - TEST_ASSERT(mempages > 1, "Can't test without any memory"); =20 data->npages =3D mempages; - data->nslots =3D max_mem_slots - 1; + data->nslots =3D nslots; data->pages_per_slot =3D mempages / data->nslots; if (!data->pages_per_slot) { *maxslots =3D mempages + 1; @@ -869,6 +859,7 @@ static void help(char *name, struct test_args *targs) static bool parse_args(int argc, char *argv[], struct test_args *targs) { + uint32_t max_mem_slots; int opt; =20 while ((opt =3D getopt(argc, argv, "hvds:f:e:l:r:")) !=3D -1) { @@ -885,8 +876,8 @@ static bool parse_args(int argc, char *argv[], break; case 's': targs->nslots =3D atoi(optarg); - if (targs->nslots <=3D 0 && targs->nslots !=3D -1) { - pr_info("Slot count cap has to be positive or -1 for no cap\n"); + if (targs->nslots <=3D 1 && targs->nslots !=3D -1) { + pr_info("Slot count cap must be larger than 1 or -1 for no cap\n"); return false; } break; @@ -932,6 +923,21 @@ static bool parse_args(int argc, char *argv[], return false; } =20 + max_mem_slots =3D kvm_check_cap(KVM_CAP_NR_MEMSLOTS); + if (max_mem_slots <=3D 1) { + pr_info("KVM_CAP_NR_MEMSLOTS should be greater than 1\n"); + return false; + } + + /* Memory slot 0 is reserved */ + if (targs->nslots =3D=3D -1) + targs->nslots =3D max_mem_slots - 1; + else + targs->nslots =3D min_t(int, targs->nslots, max_mem_slots) - 1; + + pr_info_v("Allowed Number of memory slots: %"PRIu32"\n", + targs->nslots + 1); + return true; } =20 --=20 2.23.0 From nobody Tue Apr 7 15:55:20 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 0DCBEC433FE for ; Tue, 18 Oct 2022 04:06:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230163AbiJREGG (ORCPT ); Tue, 18 Oct 2022 00:06:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230226AbiJREFw (ORCPT ); Tue, 18 Oct 2022 00:05:52 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 52AFA895FA for ; Mon, 17 Oct 2022 21:05:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1666065940; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=l2kMjJT2gQOqLs+6Ax6VYCYJviQ4N0CnEnBTOZvxZ6w=; b=U75BXwzu/mzlkT3WHdfobuPraPnb7RjblF6DP1EhQn9dHRmgZT+2sc82J+NREPYq75fXJ7 zB51ystWx9P5RtzEQYd4zGAt+Ov+LVZgtM4CpwziSttlWqK452QdevmcaOvgjb5D3sYohX tg9SRQUX90csVNR/7KXIHZdeZRzE568= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-299-LlFnDejqPwesysaqJeIqkQ-1; Tue, 18 Oct 2022 00:05:30 -0400 X-MC-Unique: LlFnDejqPwesysaqJeIqkQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C7C802999B2E; Tue, 18 Oct 2022 04:05:29 +0000 (UTC) Received: from gshan.redhat.com (vpn2-54-70.bne.redhat.com [10.64.54.70]) by smtp.corp.redhat.com (Postfix) with ESMTPS id B3FEC2166B41; Tue, 18 Oct 2022 04:05:23 +0000 (UTC) From: Gavin Shan To: kvmarm@lists.linux.dev Cc: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, ajones@ventanamicro.com, pbonzini@redhat.com, maz@kernel.org, shuah@kernel.org, oliver.upton@linux.dev, mail@maciej.szmigiero.name, maciej.szmigiero@oracle.com, seanjc@google.com, peterx@redhat.com, ricarkol@google.com, zhenyzha@redhat.com, shan.gavin@gmail.com Subject: [PATCH v2 4/6] KVM: selftests: memslot_perf_test: Support variable guest page size Date: Tue, 18 Oct 2022 12:04:52 +0800 Message-Id: <20221018040454.405719-5-gshan@redhat.com> In-Reply-To: <20221018040454.405719-1-gshan@redhat.com> References: <20221018040454.405719-1-gshan@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The test case is obviously broken on aarch64 because non-4KB guest page size is supported. The guest page size on aarch64 could be 4KB, 16KB or 64KB. This supports variable guest page size, mostly for aarch64. - The host determines the guest page size when virtual machine is created. The value is also passed to guest through the synchronization area. - The number of guest pages are unknown until the virtual machine is to be created. So all the related macros are dropped. Instead, their values are dynamically calculated based on the guest page size. - The static checks on memory sizes and pages becomes dependent on guest page size, which is unknown until the virtual machine is about to be created. So all the static checks are converted to dynamic checks, done in check_memory_sizes(). - As the address passed to madvise() should be aligned to host page, the size of page chunk is automatically selected, other than one page. - All other changes included in this patch are almost mechanical replacing '4096' with 'guest_page_size'. Signed-off-by: Gavin Shan --- .../testing/selftests/kvm/memslot_perf_test.c | 201 +++++++++++------- 1 file changed, 120 insertions(+), 81 deletions(-) diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testin= g/selftests/kvm/memslot_perf_test.c index f0ea3f75b6e1..78a481501ec4 100644 --- a/tools/testing/selftests/kvm/memslot_perf_test.c +++ b/tools/testing/selftests/kvm/memslot_perf_test.c @@ -26,14 +26,11 @@ #include =20 #define MEM_SIZE ((512U << 20) + 4096) -#define MEM_SIZE_PAGES (MEM_SIZE / 4096) #define MEM_GPA 0x10000000UL #define MEM_AUX_GPA MEM_GPA #define MEM_SYNC_GPA MEM_AUX_GPA #define MEM_TEST_GPA (MEM_AUX_GPA + 4096) #define MEM_TEST_SIZE (MEM_SIZE - 4096) -static_assert(MEM_SIZE % 4096 =3D=3D 0, "invalid mem size"); -static_assert(MEM_TEST_SIZE % 4096 =3D=3D 0, "invalid mem test size"); =20 /* * 32 MiB is max size that gets well over 100 iterations on 509 slots. @@ -42,43 +39,28 @@ static_assert(MEM_TEST_SIZE % 4096 =3D=3D 0, "invalid m= em test size"); * limited resolution). */ #define MEM_SIZE_MAP ((32U << 20) + 4096) -#define MEM_SIZE_MAP_PAGES (MEM_SIZE_MAP / 4096) #define MEM_TEST_MAP_SIZE (MEM_SIZE_MAP - 4096) -#define MEM_TEST_MAP_SIZE_PAGES (MEM_TEST_MAP_SIZE / 4096) -static_assert(MEM_SIZE_MAP % 4096 =3D=3D 0, "invalid map test region size"= ); -static_assert(MEM_TEST_MAP_SIZE % 4096 =3D=3D 0, "invalid map test region = size"); -static_assert(MEM_TEST_MAP_SIZE_PAGES % 2 =3D=3D 0, "invalid map test regi= on size"); -static_assert(MEM_TEST_MAP_SIZE_PAGES > 2, "invalid map test region size"); =20 /* * 128 MiB is min size that fills 32k slots with at least one page in each * while at the same time gets 100+ iterations in such test + * + * 2 MiB chunk size like a typical huge page */ #define MEM_TEST_UNMAP_SIZE (128U << 20) -#define MEM_TEST_UNMAP_SIZE_PAGES (MEM_TEST_UNMAP_SIZE / 4096) -/* 2 MiB chunk size like a typical huge page */ -#define MEM_TEST_UNMAP_CHUNK_PAGES (2U << (20 - 12)) -static_assert(MEM_TEST_UNMAP_SIZE <=3D MEM_TEST_SIZE, - "invalid unmap test region size"); -static_assert(MEM_TEST_UNMAP_SIZE % 4096 =3D=3D 0, - "invalid unmap test region size"); -static_assert(MEM_TEST_UNMAP_SIZE_PAGES % - (2 * MEM_TEST_UNMAP_CHUNK_PAGES) =3D=3D 0, - "invalid unmap test region size"); +#define MEM_TEST_UNMAP_CHUNK_SIZE (2U << 20) =20 /* * For the move active test the middle of the test area is placed on * a memslot boundary: half lies in the memslot being moved, half in * other memslot(s). * - * When running this test with 32k memslots (32764, really) each memslot - * contains 4 pages. - * The last one additionally contains the remaining 21 pages of memory, - * for the total size of 25 pages. - * Hence, the maximum size here is 50 pages. + * When running this test with 32k memslots, actually 32763 excluding + * the reserved memory slot 0, the memory for each slot is 16KB. The + * last slot contains 100KB memory with the remaining 84KB. Hence, + * the maximum size is double of that (200KB) */ -#define MEM_TEST_MOVE_SIZE_PAGES (50) -#define MEM_TEST_MOVE_SIZE (MEM_TEST_MOVE_SIZE_PAGES * 4096) +#define MEM_TEST_MOVE_SIZE 0x32000 #define MEM_TEST_MOVE_GPA_DEST (MEM_GPA + MEM_SIZE) static_assert(MEM_TEST_MOVE_SIZE <=3D MEM_TEST_SIZE, "invalid move test region size"); @@ -100,6 +82,7 @@ struct vm_data { }; =20 struct sync_area { + uint32_t guest_page_size; atomic_bool start_flag; atomic_bool exit_flag; atomic_bool sync_flag; @@ -192,14 +175,15 @@ static void *vm_gpa2hva(struct vm_data *data, uint64_= t gpa, uint64_t *rempages) uint64_t gpage, pgoffs; uint32_t slot, slotoffs; void *base; + uint32_t guest_page_size =3D data->vm->page_size; =20 TEST_ASSERT(gpa >=3D MEM_GPA, "Too low gpa to translate"); - TEST_ASSERT(gpa < MEM_GPA + data->npages * 4096, + TEST_ASSERT(gpa < MEM_GPA + data->npages * guest_page_size, "Too high gpa to translate"); gpa -=3D MEM_GPA; =20 - gpage =3D gpa / 4096; - pgoffs =3D gpa % 4096; + gpage =3D gpa / guest_page_size; + pgoffs =3D gpa % guest_page_size; slot =3D min(gpage / data->pages_per_slot, (uint64_t)data->nslots - 1); slotoffs =3D gpage - (slot * data->pages_per_slot); =20 @@ -217,14 +201,16 @@ static void *vm_gpa2hva(struct vm_data *data, uint64_= t gpa, uint64_t *rempages) } =20 base =3D data->hva_slots[slot]; - return (uint8_t *)base + slotoffs * 4096 + pgoffs; + return (uint8_t *)base + slotoffs * guest_page_size + pgoffs; } =20 static uint64_t vm_slot2gpa(struct vm_data *data, uint32_t slot) { + uint32_t guest_page_size =3D data->vm->page_size; + TEST_ASSERT(slot < data->nslots, "Too high slot number"); =20 - return MEM_GPA + slot * data->pages_per_slot * 4096; + return MEM_GPA + slot * data->pages_per_slot * guest_page_size; } =20 static struct vm_data *alloc_vm(void) @@ -242,33 +228,35 @@ static struct vm_data *alloc_vm(void) } =20 static bool prepare_vm(struct vm_data *data, int nslots, uint64_t *maxslot= s, - void *guest_code, uint64_t mempages, + void *guest_code, uint64_t mem_size, struct timespec *slot_runtime) { - uint64_t rempages; + uint64_t mempages, rempages; uint64_t guest_addr; - uint32_t slot; + uint32_t slot, guest_page_size; struct timespec tstart; struct sync_area *sync; =20 - TEST_ASSERT(mempages > 1, - "Can't test without any memory"); + guest_page_size =3D vm_guest_mode_params[VM_MODE_DEFAULT].page_size; + mempages =3D mem_size / guest_page_size; + + data->vm =3D __vm_create_with_one_vcpu(&data->vcpu, mempages, guest_code); + ucall_init(data->vm, NULL); + TEST_ASSERT(data->vm->page_size =3D=3D guest_page_size, "Invalid VM page = size"); =20 data->npages =3D mempages; + TEST_ASSERT(data->npages > 1, "Can't test without any memory"); data->nslots =3D nslots; - data->pages_per_slot =3D mempages / data->nslots; + data->pages_per_slot =3D data->npages / data->nslots; if (!data->pages_per_slot) { - *maxslots =3D mempages + 1; + *maxslots =3D data->npages + 1; return false; } =20 - rempages =3D mempages % data->nslots; + rempages =3D data->npages % data->nslots; data->hva_slots =3D malloc(sizeof(*data->hva_slots) * data->nslots); 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); - pr_info_v("Adding slots 1..%i, each slot with %"PRIu64" pages + %"PRIu64"= extra pages last\n", data->nslots, data->pages_per_slot, rempages); =20 @@ -283,7 +271,7 @@ static bool prepare_vm(struct vm_data *data, int nslots= , uint64_t *maxslots, vm_userspace_mem_region_add(data->vm, VM_MEM_SRC_ANONYMOUS, guest_addr, slot, npages, 0); - guest_addr +=3D npages * 4096; + guest_addr +=3D npages * guest_page_size; } *slot_runtime =3D timespec_elapsed(tstart); =20 @@ -300,12 +288,12 @@ static bool prepare_vm(struct vm_data *data, int nslo= ts, uint64_t *maxslots, "vm_phy_pages_alloc() failed\n"); =20 data->hva_slots[slot - 1] =3D addr_gpa2hva(data->vm, guest_addr); - memset(data->hva_slots[slot - 1], 0, npages * 4096); + memset(data->hva_slots[slot - 1], 0, npages * guest_page_size); =20 - guest_addr +=3D npages * 4096; + guest_addr +=3D npages * guest_page_size; } =20 - virt_map(data->vm, MEM_GPA, MEM_GPA, mempages); + virt_map(data->vm, MEM_GPA, MEM_GPA, data->npages); =20 sync =3D (typeof(sync))vm_gpa2hva(data, MEM_SYNC_GPA, NULL); atomic_init(&sync->start_flag, false); @@ -404,6 +392,7 @@ static bool guest_perform_sync(void) static void guest_code_test_memslot_move(void) { struct sync_area *sync =3D (typeof(sync))MEM_SYNC_GPA; + uint32_t page_size =3D (typeof(page_size))READ_ONCE(sync->guest_page_size= ); uintptr_t base =3D (typeof(base))READ_ONCE(sync->move_area_ptr); =20 GUEST_SYNC(0); @@ -414,7 +403,7 @@ static void guest_code_test_memslot_move(void) uintptr_t ptr; =20 for (ptr =3D base; ptr < base + MEM_TEST_MOVE_SIZE; - ptr +=3D 4096) + ptr +=3D page_size) *(uint64_t *)ptr =3D MEM_TEST_VAL_1; =20 /* @@ -432,6 +421,7 @@ static void guest_code_test_memslot_move(void) static void guest_code_test_memslot_map(void) { struct sync_area *sync =3D (typeof(sync))MEM_SYNC_GPA; + uint32_t page_size =3D (typeof(page_size))READ_ONCE(sync->guest_page_size= ); =20 GUEST_SYNC(0); =20 @@ -441,14 +431,16 @@ static void guest_code_test_memslot_map(void) uintptr_t ptr; =20 for (ptr =3D MEM_TEST_GPA; - ptr < MEM_TEST_GPA + MEM_TEST_MAP_SIZE / 2; ptr +=3D 4096) + ptr < MEM_TEST_GPA + MEM_TEST_MAP_SIZE / 2; + ptr +=3D page_size) *(uint64_t *)ptr =3D MEM_TEST_VAL_1; =20 if (!guest_perform_sync()) break; =20 for (ptr =3D MEM_TEST_GPA + MEM_TEST_MAP_SIZE / 2; - ptr < MEM_TEST_GPA + MEM_TEST_MAP_SIZE; ptr +=3D 4096) + ptr < MEM_TEST_GPA + MEM_TEST_MAP_SIZE; + ptr +=3D page_size) *(uint64_t *)ptr =3D MEM_TEST_VAL_2; =20 if (!guest_perform_sync()) @@ -495,6 +487,9 @@ static void guest_code_test_memslot_unmap(void) =20 static void guest_code_test_memslot_rw(void) { + struct sync_area *sync =3D (typeof(sync))MEM_SYNC_GPA; + uint32_t page_size =3D (typeof(page_size))READ_ONCE(sync->guest_page_size= ); + GUEST_SYNC(0); =20 guest_spin_until_start(); @@ -503,14 +498,14 @@ static void guest_code_test_memslot_rw(void) uintptr_t ptr; =20 for (ptr =3D MEM_TEST_GPA; - ptr < MEM_TEST_GPA + MEM_TEST_SIZE; ptr +=3D 4096) + ptr < MEM_TEST_GPA + MEM_TEST_SIZE; ptr +=3D page_size) *(uint64_t *)ptr =3D MEM_TEST_VAL_1; =20 if (!guest_perform_sync()) break; =20 - for (ptr =3D MEM_TEST_GPA + 4096 / 2; - ptr < MEM_TEST_GPA + MEM_TEST_SIZE; ptr +=3D 4096) { + for (ptr =3D MEM_TEST_GPA + page_size / 2; + ptr < MEM_TEST_GPA + MEM_TEST_SIZE; ptr +=3D page_size) { uint64_t val =3D *(uint64_t *)ptr; =20 GUEST_ASSERT_1(val =3D=3D MEM_TEST_VAL_2, val); @@ -528,6 +523,8 @@ static bool test_memslot_move_prepare(struct vm_data *d= ata, struct sync_area *sync, uint64_t *maxslots, bool isactive) { + uint32_t guest_page_size =3D data->vm->page_size; + uint64_t move_pages =3D MEM_TEST_MOVE_SIZE / guest_page_size; uint64_t movesrcgpa, movetestgpa; =20 movesrcgpa =3D vm_slot2gpa(data, data->nslots - 1); @@ -536,7 +533,7 @@ static bool test_memslot_move_prepare(struct vm_data *d= ata, uint64_t lastpages; =20 vm_gpa2hva(data, movesrcgpa, &lastpages); - if (lastpages < MEM_TEST_MOVE_SIZE_PAGES / 2) { + if (lastpages < move_pages / 2) { *maxslots =3D 0; return false; } @@ -582,8 +579,9 @@ static void test_memslot_do_unmap(struct vm_data *data, uint64_t offsp, uint64_t count) { uint64_t gpa, ctr; + uint32_t guest_page_size =3D data->vm->page_size; =20 - for (gpa =3D MEM_TEST_GPA + offsp * 4096, ctr =3D 0; ctr < count; ) { + for (gpa =3D MEM_TEST_GPA + offsp * guest_page_size, ctr =3D 0; ctr < cou= nt; ) { uint64_t npages; void *hva; int ret; @@ -591,12 +589,12 @@ static void test_memslot_do_unmap(struct vm_data *dat= a, hva =3D vm_gpa2hva(data, gpa, &npages); TEST_ASSERT(npages, "Empty memory slot at gptr 0x%"PRIx64, gpa); npages =3D min(npages, count - ctr); - ret =3D madvise(hva, npages * 4096, MADV_DONTNEED); + ret =3D madvise(hva, npages * guest_page_size, MADV_DONTNEED); TEST_ASSERT(!ret, "madvise(%p, MADV_DONTNEED) on VM memory should not fail for gptr 0= x%"PRIx64, hva, gpa); ctr +=3D npages; - gpa +=3D npages * 4096; + gpa +=3D npages * guest_page_size; } TEST_ASSERT(ctr =3D=3D count, "madvise(MADV_DONTNEED) should exactly cover all of the requested ar= ea"); @@ -607,11 +605,12 @@ static void test_memslot_map_unmap_check(struct vm_da= ta *data, { uint64_t gpa; uint64_t *val; + uint32_t guest_page_size =3D data->vm->page_size; =20 if (!map_unmap_verify) return; =20 - gpa =3D MEM_TEST_GPA + offsp * 4096; + gpa =3D MEM_TEST_GPA + offsp * guest_page_size; val =3D (typeof(val))vm_gpa2hva(data, gpa, NULL); TEST_ASSERT(*val =3D=3D valexp, "Guest written values should read back correctly before unmap (%"PRI= u64" vs %"PRIu64" @ %"PRIx64")", @@ -621,12 +620,14 @@ static void test_memslot_map_unmap_check(struct vm_da= ta *data, =20 static void test_memslot_map_loop(struct vm_data *data, struct sync_area *= sync) { + uint32_t guest_page_size =3D data->vm->page_size; + uint64_t guest_pages =3D MEM_TEST_MAP_SIZE / guest_page_size; + /* * Unmap the second half of the test area while guest writes to (maps) * the first half. */ - test_memslot_do_unmap(data, MEM_TEST_MAP_SIZE_PAGES / 2, - MEM_TEST_MAP_SIZE_PAGES / 2); + test_memslot_do_unmap(data, guest_pages / 2, guest_pages / 2); =20 /* * Wait for the guest to finish writing the first half of the test @@ -637,10 +638,8 @@ static void test_memslot_map_loop(struct vm_data *data= , struct sync_area *sync) */ host_perform_sync(sync); test_memslot_map_unmap_check(data, 0, MEM_TEST_VAL_1); - test_memslot_map_unmap_check(data, - MEM_TEST_MAP_SIZE_PAGES / 2 - 1, - MEM_TEST_VAL_1); - test_memslot_do_unmap(data, 0, MEM_TEST_MAP_SIZE_PAGES / 2); + test_memslot_map_unmap_check(data, guest_pages / 2 - 1, MEM_TEST_VAL_1); + test_memslot_do_unmap(data, 0, guest_pages / 2); =20 =20 /* @@ -653,16 +652,16 @@ static void test_memslot_map_loop(struct vm_data *dat= a, struct sync_area *sync) * the test area. */ host_perform_sync(sync); - test_memslot_map_unmap_check(data, MEM_TEST_MAP_SIZE_PAGES / 2, - MEM_TEST_VAL_2); - test_memslot_map_unmap_check(data, MEM_TEST_MAP_SIZE_PAGES - 1, - MEM_TEST_VAL_2); + test_memslot_map_unmap_check(data, guest_pages / 2, MEM_TEST_VAL_2); + test_memslot_map_unmap_check(data, guest_pages - 1, MEM_TEST_VAL_2); } =20 static void test_memslot_unmap_loop_common(struct vm_data *data, struct sync_area *sync, uint64_t chunk) { + uint32_t guest_page_size =3D data->vm->page_size; + uint64_t guest_pages =3D MEM_TEST_UNMAP_SIZE / guest_page_size; uint64_t ctr; =20 /* @@ -674,42 +673,49 @@ static void test_memslot_unmap_loop_common(struct vm_= data *data, */ host_perform_sync(sync); test_memslot_map_unmap_check(data, 0, MEM_TEST_VAL_1); - for (ctr =3D 0; ctr < MEM_TEST_UNMAP_SIZE_PAGES / 2; ctr +=3D chunk) + for (ctr =3D 0; ctr < guest_pages / 2; ctr +=3D chunk) test_memslot_do_unmap(data, ctr, chunk); =20 /* Likewise, but for the opposite host / guest areas */ host_perform_sync(sync); - test_memslot_map_unmap_check(data, MEM_TEST_UNMAP_SIZE_PAGES / 2, - MEM_TEST_VAL_2); - for (ctr =3D MEM_TEST_UNMAP_SIZE_PAGES / 2; - ctr < MEM_TEST_UNMAP_SIZE_PAGES; ctr +=3D chunk) + test_memslot_map_unmap_check(data, guest_pages / 2, MEM_TEST_VAL_2); + for (ctr =3D guest_pages / 2; ctr < guest_pages; ctr +=3D chunk) test_memslot_do_unmap(data, ctr, chunk); } =20 static void test_memslot_unmap_loop(struct vm_data *data, struct sync_area *sync) { - test_memslot_unmap_loop_common(data, sync, 1); + uint32_t host_page_size =3D getpagesize(); + uint32_t guest_page_size =3D data->vm->page_size; + uint64_t guest_chunk_pages =3D guest_page_size >=3D host_page_size ? + 1 : host_page_size / guest_page_size; + + test_memslot_unmap_loop_common(data, sync, guest_chunk_pages); } =20 static void test_memslot_unmap_loop_chunked(struct vm_data *data, struct sync_area *sync) { - test_memslot_unmap_loop_common(data, sync, MEM_TEST_UNMAP_CHUNK_PAGES); + uint32_t guest_page_size =3D data->vm->page_size; + uint64_t guest_chunk_pages =3D MEM_TEST_UNMAP_CHUNK_SIZE / guest_page_siz= e; + + test_memslot_unmap_loop_common(data, sync, guest_chunk_pages); } =20 static void test_memslot_rw_loop(struct vm_data *data, struct sync_area *s= ync) { uint64_t gptr; + uint32_t guest_page_size =3D data->vm->page_size; =20 - for (gptr =3D MEM_TEST_GPA + 4096 / 2; - gptr < MEM_TEST_GPA + MEM_TEST_SIZE; gptr +=3D 4096) + for (gptr =3D MEM_TEST_GPA + guest_page_size / 2; + gptr < MEM_TEST_GPA + MEM_TEST_SIZE; gptr +=3D guest_page_size) *(uint64_t *)vm_gpa2hva(data, gptr, NULL) =3D MEM_TEST_VAL_2; =20 host_perform_sync(sync); =20 for (gptr =3D MEM_TEST_GPA; - gptr < MEM_TEST_GPA + MEM_TEST_SIZE; gptr +=3D 4096) { + gptr < MEM_TEST_GPA + MEM_TEST_SIZE; gptr +=3D guest_page_size) { uint64_t *vptr =3D (typeof(vptr))vm_gpa2hva(data, gptr, NULL); uint64_t val =3D *vptr; =20 @@ -738,7 +744,7 @@ static bool test_execute(int nslots, uint64_t *maxslots, struct timespec *slot_runtime, struct timespec *guest_runtime) { - uint64_t mem_size =3D tdata->mem_size ? : MEM_SIZE_PAGES; + uint64_t mem_size =3D tdata->mem_size ? : MEM_SIZE; struct vm_data *data; struct sync_area *sync; struct timespec tstart; @@ -753,6 +759,7 @@ static bool test_execute(int nslots, uint64_t *maxslots, =20 sync =3D (typeof(sync))vm_gpa2hva(data, MEM_SYNC_GPA, NULL); =20 + sync->guest_page_size =3D data->vm->page_size; if (tdata->prepare && !tdata->prepare(data, sync, maxslots)) { ret =3D false; @@ -786,19 +793,19 @@ static bool test_execute(int nslots, uint64_t *maxslo= ts, static const struct test_data tests[] =3D { { .name =3D "map", - .mem_size =3D MEM_SIZE_MAP_PAGES, + .mem_size =3D MEM_SIZE_MAP, .guest_code =3D guest_code_test_memslot_map, .loop =3D test_memslot_map_loop, }, { .name =3D "unmap", - .mem_size =3D MEM_TEST_UNMAP_SIZE_PAGES + 1, + .mem_size =3D MEM_TEST_UNMAP_SIZE + 4096, .guest_code =3D guest_code_test_memslot_unmap, .loop =3D test_memslot_unmap_loop, }, { .name =3D "unmap chunked", - .mem_size =3D MEM_TEST_UNMAP_SIZE_PAGES + 1, + .mem_size =3D MEM_TEST_UNMAP_SIZE + 4096, .guest_code =3D guest_code_test_memslot_unmap, .loop =3D test_memslot_unmap_loop_chunked, }, @@ -856,6 +863,35 @@ static void help(char *name, struct test_args *targs) pr_info("%d: %s\n", ctr, tests[ctr].name); } =20 +static bool check_memory_sizes(void) +{ + uint32_t guest_page_size =3D vm_guest_mode_params[VM_MODE_DEFAULT].page_s= ize; + + if (MEM_SIZE % guest_page_size || + MEM_TEST_SIZE % guest_page_size) { + pr_info("invalid MEM_SIZE or MEM_TEST_SIZE\n"); + return false; + } + + if (MEM_SIZE_MAP % guest_page_size || + MEM_TEST_MAP_SIZE % guest_page_size || + (MEM_TEST_MAP_SIZE / guest_page_size) <=3D 2 || + (MEM_TEST_MAP_SIZE / guest_page_size) % 2) { + pr_info("invalid MEM_SIZE_MAP or MEM_TEST_MAP_SIZE\n"); + return false; + } + + if (MEM_TEST_UNMAP_SIZE > MEM_TEST_SIZE || + MEM_TEST_UNMAP_SIZE % guest_page_size || + (MEM_TEST_UNMAP_SIZE / guest_page_size) % + (2 * MEM_TEST_UNMAP_CHUNK_SIZE / guest_page_size)) { + pr_info("invalid MEM_TEST_UNMAP_SIZE or MEM_TEST_UNMAP_CHUNK_SIZE\n"); + return false; + } + + return true; +} + static bool parse_args(int argc, char *argv[], struct test_args *targs) { @@ -1015,6 +1051,9 @@ int main(int argc, char *argv[]) /* Tell stdout not to buffer its content */ setbuf(stdout, NULL); =20 + if (!check_memory_sizes()) + return -1; + if (!parse_args(argc, argv, &targs)) return -1; =20 --=20 2.23.0 From nobody Tue Apr 7 15:55:20 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 00C9BC4332F for ; Tue, 18 Oct 2022 04:06:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230394AbiJREGD (ORCPT ); Tue, 18 Oct 2022 00:06:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46086 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230384AbiJREFu (ORCPT ); Tue, 18 Oct 2022 00:05:50 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EAD2087FB4 for ; Mon, 17 Oct 2022 21:05:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1666065940; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2JseUvCnBtDKpXX2u+0xKEawSnwnBYCh4Pw+SGrWbXc=; b=OyKuXYsUkOszeEt9CFC1lrD/Mk83aqRBekVIgkv5ZkK212dbDHGa0O78pAyHHK8461PpbY gPCYQFDtGJ95fEObkokTO9eF0ieVHkBRXVKFI2BQ6TS+7McfeCZirXWtDrjPTesnyUTdQs tw/RrFgo1YpG/buzS8DhWlwTn7DOG0c= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-352-YA2M8vYJOtKYrLvyIt9skQ-1; Tue, 18 Oct 2022 00:05:37 -0400 X-MC-Unique: YA2M8vYJOtKYrLvyIt9skQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6EA953C3C964; Tue, 18 Oct 2022 04:05:36 +0000 (UTC) Received: from gshan.redhat.com (vpn2-54-70.bne.redhat.com [10.64.54.70]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7188B2166B41; Tue, 18 Oct 2022 04:05:30 +0000 (UTC) From: Gavin Shan To: kvmarm@lists.linux.dev Cc: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, ajones@ventanamicro.com, pbonzini@redhat.com, maz@kernel.org, shuah@kernel.org, oliver.upton@linux.dev, mail@maciej.szmigiero.name, maciej.szmigiero@oracle.com, seanjc@google.com, peterx@redhat.com, ricarkol@google.com, zhenyzha@redhat.com, shan.gavin@gmail.com Subject: [PATCH v2 5/6] KVM: selftests: memslot_perf_test: Consolidate memory sizes Date: Tue, 18 Oct 2022 12:04:53 +0800 Message-Id: <20221018040454.405719-6-gshan@redhat.com> In-Reply-To: <20221018040454.405719-1-gshan@redhat.com> References: <20221018040454.405719-1-gshan@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The addresses and sizes passed to vm_userspace_mem_region_add() and madvise() should be aligned to host page size, which can be 64KB on aarch64. So it's wrong by passing additional fixed 4KB memory area to various tests. Fix it by passing additional fixed 64KB memory area to various tests. We also add checks to ensure that none of host/guest page size exceeds 64KB. After it's applied, the following command works fine on 64KB-page-size-host and 4KB-page-size-guest. # ./memslot_perf_test -v -s 512 Signed-off-by: Gavin Shan --- .../selftests/kvm/include/kvm_util_base.h | 15 ++++++++++ .../testing/selftests/kvm/memslot_perf_test.c | 30 ++++++++++++------- 2 files changed, 34 insertions(+), 11 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..bd9a19b9054b 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -26,6 +26,21 @@ =20 #define NSEC_PER_SEC 1000000000L =20 +#define SIZE_KiB (1UL << 10) +#define SIZE_MiB (1UL << 20) +#define SIZE_GiB (1UL << 30) +#define SIZE_TiB (1UL << 40) + +/* Base and huge page size */ +#define SIZE_4KiB (4 * SIZE_KiB) +#define SIZE_16KiB (16 * SIZE_KiB) +#define SIZE_64KiB (64 * SIZE_KiB) +#define SIZE_2MiB (2 * SIZE_MiB) +#define SIZE_32MiB (32 * SIZE_MiB) +#define SIZE_512MiB (512 * SIZE_MiB) +#define SIZE_1GiB (1 * SIZE_GiB) +#define SIZE_16GiB (16 * SIZE_GiB) + typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */ typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ =20 diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testin= g/selftests/kvm/memslot_perf_test.c index 78a481501ec4..3ab385e40bc0 100644 --- a/tools/testing/selftests/kvm/memslot_perf_test.c +++ b/tools/testing/selftests/kvm/memslot_perf_test.c @@ -25,12 +25,14 @@ #include #include =20 -#define MEM_SIZE ((512U << 20) + 4096) -#define MEM_GPA 0x10000000UL +#define MEM_EXTRA_SIZE SIZE_64KiB + +#define MEM_SIZE (SIZE_512MiB + MEM_EXTRA_SIZE) +#define MEM_GPA (256 * SIZE_MiB) #define MEM_AUX_GPA MEM_GPA #define MEM_SYNC_GPA MEM_AUX_GPA -#define MEM_TEST_GPA (MEM_AUX_GPA + 4096) -#define MEM_TEST_SIZE (MEM_SIZE - 4096) +#define MEM_TEST_GPA (MEM_AUX_GPA + MEM_EXTRA_SIZE) +#define MEM_TEST_SIZE (MEM_SIZE - MEM_EXTRA_SIZE) =20 /* * 32 MiB is max size that gets well over 100 iterations on 509 slots. @@ -38,8 +40,8 @@ * 8194 slots in use can then be tested (although with slightly * limited resolution). */ -#define MEM_SIZE_MAP ((32U << 20) + 4096) -#define MEM_TEST_MAP_SIZE (MEM_SIZE_MAP - 4096) +#define MEM_SIZE_MAP (SIZE_32MiB + MEM_EXTRA_SIZE) +#define MEM_TEST_MAP_SIZE (MEM_SIZE_MAP - MEM_EXTRA_SIZE) =20 /* * 128 MiB is min size that fills 32k slots with at least one page in each @@ -47,8 +49,8 @@ * * 2 MiB chunk size like a typical huge page */ -#define MEM_TEST_UNMAP_SIZE (128U << 20) -#define MEM_TEST_UNMAP_CHUNK_SIZE (2U << 20) +#define MEM_TEST_UNMAP_SIZE (128 * SIZE_MiB) +#define MEM_TEST_UNMAP_CHUNK_SIZE SIZE_2MiB =20 /* * For the move active test the middle of the test area is placed on @@ -60,7 +62,7 @@ * last slot contains 100KB memory with the remaining 84KB. Hence, * the maximum size is double of that (200KB) */ -#define MEM_TEST_MOVE_SIZE 0x32000 +#define MEM_TEST_MOVE_SIZE (200 * SIZE_KiB) #define MEM_TEST_MOVE_GPA_DEST (MEM_GPA + MEM_SIZE) static_assert(MEM_TEST_MOVE_SIZE <=3D MEM_TEST_SIZE, "invalid move test region size"); @@ -799,13 +801,13 @@ static const struct test_data tests[] =3D { }, { .name =3D "unmap", - .mem_size =3D MEM_TEST_UNMAP_SIZE + 4096, + .mem_size =3D MEM_TEST_UNMAP_SIZE + MEM_EXTRA_SIZE, .guest_code =3D guest_code_test_memslot_unmap, .loop =3D test_memslot_unmap_loop, }, { .name =3D "unmap chunked", - .mem_size =3D MEM_TEST_UNMAP_SIZE + 4096, + .mem_size =3D MEM_TEST_UNMAP_SIZE + MEM_EXTRA_SIZE, .guest_code =3D guest_code_test_memslot_unmap, .loop =3D test_memslot_unmap_loop_chunked, }, @@ -865,8 +867,14 @@ static void help(char *name, struct test_args *targs) =20 static bool check_memory_sizes(void) { + uint32_t host_page_size =3D getpagesize(); uint32_t guest_page_size =3D vm_guest_mode_params[VM_MODE_DEFAULT].page_s= ize; =20 + if (host_page_size > SIZE_64KiB || guest_page_size > SIZE_64KiB) { + pr_info("Unsupported page size on host (0x%x) or guest (0x%x)\n", + host_page_size, guest_page_size); + } + if (MEM_SIZE % guest_page_size || MEM_TEST_SIZE % guest_page_size) { pr_info("invalid MEM_SIZE or MEM_TEST_SIZE\n"); --=20 2.23.0 From nobody Tue Apr 7 15:55:20 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 468B5C4332F for ; Tue, 18 Oct 2022 04:06:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231149AbiJREGY (ORCPT ); Tue, 18 Oct 2022 00:06:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45666 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230427AbiJREF7 (ORCPT ); Tue, 18 Oct 2022 00:05:59 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1BD9692F66 for ; Mon, 17 Oct 2022 21:05:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1666065946; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/RCLmwcdRRHc5iUwT+6ibxZ6InHRbOkdgeEhTg+vaBw=; b=APHHVZ4yJk1zqsgx8iVh6G5dAcLXNJ9P26fqcpI2jPcPgsYUYaiDUh4BPYVkwlmol7RgcE G44v5Ig4pG7b6+XyyBciSXXgDH+llbcef1x9cHrSQ1iQZ+yXUb7NpbSbTx7BeLD1ei8akH hCAAHfnw/l8U6D+O6+ge1mGQAkqkJ4E= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-62-2lhYu8McORSGNCmBrHRyQw-1; Tue, 18 Oct 2022 00:05:42 -0400 X-MC-Unique: 2lhYu8McORSGNCmBrHRyQw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 36C663C3C968; Tue, 18 Oct 2022 04:05:42 +0000 (UTC) Received: from gshan.redhat.com (vpn2-54-70.bne.redhat.com [10.64.54.70]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0BF7C2166B41; Tue, 18 Oct 2022 04:05:36 +0000 (UTC) From: Gavin Shan To: kvmarm@lists.linux.dev Cc: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, ajones@ventanamicro.com, pbonzini@redhat.com, maz@kernel.org, shuah@kernel.org, oliver.upton@linux.dev, mail@maciej.szmigiero.name, maciej.szmigiero@oracle.com, seanjc@google.com, peterx@redhat.com, ricarkol@google.com, zhenyzha@redhat.com, shan.gavin@gmail.com Subject: [PATCH v2 6/6] KVM: selftests: memslot_perf_test: Report optimal memory slots Date: Tue, 18 Oct 2022 12:04:54 +0800 Message-Id: <20221018040454.405719-7-gshan@redhat.com> In-Reply-To: <20221018040454.405719-1-gshan@redhat.com> References: <20221018040454.405719-1-gshan@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The memory area in each slot should be aligned to host page size. Otherwise, the test will fail. For example, the following command fails with the following messages with 64KB-page-size-host and 4KB-pae-size-guest. It's not user friendly to abort the test. Lets do something to report the optimal memory slots, instead of failing the test. # ./memslot_perf_test -v -s 1000 Number of memory slots: 999 Testing map performance with 1 runs, 5 seconds each Adding slots 1..999, each slot with 8 pages + 216 extra pages last =3D=3D=3D=3D Test Assertion Failure =3D=3D=3D=3D lib/kvm_util.c:824: vm_adjust_num_guest_pages(vm->mode, npages) =3D=3D = npages pid=3D19872 tid=3D19872 errno=3D0 - Success 1 0x00000000004065b3: vm_userspace_mem_region_add at kvm_util.c:822 2 0x0000000000401d6b: prepare_vm at memslot_perf_test.c:273 3 (inlined by) test_execute at memslot_perf_test.c:756 4 (inlined by) test_loop at memslot_perf_test.c:994 5 (inlined by) main at memslot_perf_test.c:1073 6 0x0000ffff7ebb4383: ?? ??:0 7 0x00000000004021ff: _start at :? Number of guest pages is not compatible with the host. Try npages=3D16 Report the optimal memory slots instead of failing the test when the memory area in each slot isn't aligned to host page size. With this applied, the optimal memory slots is reported. # ./memslot_perf_test -v -s 1000 Number of memory slots: 999 Testing map performance with 1 runs, 5 seconds each Memslot count too high for this test, decrease the cap (max is 514) Signed-off-by: Gavin Shan --- .../testing/selftests/kvm/memslot_perf_test.c | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testin= g/selftests/kvm/memslot_perf_test.c index 3ab385e40bc0..e0f3d9bd5297 100644 --- a/tools/testing/selftests/kvm/memslot_perf_test.c +++ b/tools/testing/selftests/kvm/memslot_perf_test.c @@ -229,16 +229,52 @@ static struct vm_data *alloc_vm(void) return data; } =20 +static bool check_slot_pages(uint32_t host_page_size, uint32_t guest_page_= size, + uint64_t pages_per_slot, uint64_t rempages) +{ + if (!pages_per_slot) + return false; + + if ((pages_per_slot * guest_page_size) % host_page_size) + return false; + + if ((rempages * guest_page_size) % host_page_size) + return false; + + return true; +} + + +static uint64_t get_max_slots(struct vm_data *data, uint32_t host_page_siz= e) +{ + uint32_t guest_page_size =3D data->vm->page_size; + uint64_t mempages, pages_per_slot, rempages; + uint64_t slots; + + mempages =3D data->npages; + slots =3D data->nslots; + while (--slots > 1) { + pages_per_slot =3D mempages / slots; + rempages =3D mempages % pages_per_slot; + if (check_slot_pages(host_page_size, guest_page_size, + pages_per_slot, rempages)) + return slots + 1; /* slot 0 is reserved */ + } + + return 0; +} + static bool prepare_vm(struct vm_data *data, int nslots, uint64_t *maxslot= s, void *guest_code, uint64_t mem_size, struct timespec *slot_runtime) { uint64_t mempages, rempages; uint64_t guest_addr; - uint32_t slot, guest_page_size; + uint32_t slot, host_page_size, guest_page_size; struct timespec tstart; struct sync_area *sync; =20 + host_page_size =3D getpagesize(); guest_page_size =3D vm_guest_mode_params[VM_MODE_DEFAULT].page_size; mempages =3D mem_size / guest_page_size; =20 @@ -250,12 +286,13 @@ static bool prepare_vm(struct vm_data *data, int nslo= ts, uint64_t *maxslots, TEST_ASSERT(data->npages > 1, "Can't test without any memory"); data->nslots =3D nslots; data->pages_per_slot =3D data->npages / data->nslots; - if (!data->pages_per_slot) { - *maxslots =3D data->npages + 1; + rempages =3D data->npages % data->nslots; + if (!check_slot_pages(host_page_size, guest_page_size, + data->pages_per_slot, rempages)) { + *maxslots =3D get_max_slots(data, host_page_size); return false; } =20 - rempages =3D data->npages % data->nslots; data->hva_slots =3D malloc(sizeof(*data->hva_slots) * data->nslots); TEST_ASSERT(data->hva_slots, "malloc() fail"); =20 --=20 2.23.0