From patchwork Fri Apr 12 10:34:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627605 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2A8E3C00A94 for ; Fri, 12 Apr 2024 10:39:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=uMJ5rhIHkD6qMRSA8L+ZacEa6LXO3K0xetmI2b2ERuE=; b=EJC59hsbqpl242 EIU9avKaHMmQPBI3PN8cXgX9a9bqWfbN7ri3opTu/am8S8KlQwDTElv4mv8vk7FgVtL1hi7XtJZ80 fglDjAqjbIOHinEZeWq9/maDkhF53+ZY+IORRWKNEa/tkCaBF8tViCuGDHPw5OxHtl/IEA4U3aO5d a1o16vZR1rqjv1MWzY5mN5XE3Ke6PfeoBEGTQu8ys5PScuJgPawoq6mBCM/gciYvP6snOdHOO4U8Q bSyHuBKw6O25Onnij9YBXb1uAA1CG5bdiJbPdiE+VV/l1/UpkMjUDpXzBOyhL4yBxIf2u5mBEwMnO eHy6XTc/BVGvYiA+nISw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rvEJ9-0000000GjEq-1YZf; Fri, 12 Apr 2024 10:38:59 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rvEFf-0000000Gh4L-3oo3 for linux-arm-kernel@lists.infradead.org; Fri, 12 Apr 2024 10:35:33 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B00A91655; Fri, 12 Apr 2024 03:35:52 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id B1CCB3F64C; Fri, 12 Apr 2024 03:35:21 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 32/33] arm: Add memtest support Date: Fri, 12 Apr 2024 11:34:07 +0100 Message-Id: <20240412103408.2706058-33-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240412_033524_440059_29723435 X-CRM114-Status: GOOD ( 20.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Joey Gouly Add a test to touch all memory allocated to the guest. Provides options to allocate in block, shared mode etc. Also adds a "memstress" variant which would test all the combinations in order. PS: The memory allocator fragments the available memory on page allocation and doesn't allow merging them for a higher order allocation. Hence, all the block alloc tests are run one after the other, before any page allocation tests are run Signed-off-by: Joey Gouly Co-developed-by: Suzuki K Poulose Signed-off-by: Suzuki K Poulose --- arm/selftest.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/arm/selftest.c b/arm/selftest.c index 7bc5fb76..d9fd9750 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -435,6 +436,123 @@ static void cpu_report(void *data __unused) report_info("CPU%3d: MPIDR=%010" PRIx64, cpu, mpidr); } + +/* + * do_memtest: Accepts the following paramters. + * + * shared[=0/1] - Use shared page for the memtests. + * block[=0/1] - Use SZ_2M allocation/free. + * nofree - Do not free the pages after the test. + */ +static void do_memtest(int argc, char *argv[]) +{ + int i; + int npages = 0; + bool result = true; + const char pattern = 0xFB; + void *prev_page = NULL; + uintptr_t *page_to_free = NULL; + int size; + void* (*alloc_order_fn)(unsigned int); + void (*free_order_fn)(void *, unsigned int); + bool shared = false; + bool block = false; + bool nofree = false; + int order = 0; + + for (i = 2; i < argc; i++) { + long val, len; + + len = parse_keyval(argv[i], &val); + if (len == -1) { + if (!strcmp(argv[i], "shared")) { + shared = true; + continue; + } else if (!strcmp(argv[i], "nofree")) { + nofree = true; + continue; + } else if (!strcmp(argv[i], "block")) { + block = true; + } else { + printf("Unknown options %s\n", argv[i]); + abort(); + } + } else if (!strncmp(argv[i], "block", len)) { + block = !!val; + } else if (!strncmp(argv[i], "shared", len)) { + shared = !!val; + } + } + + /* Block mapping is 2MB */ + if (block) + order = (21 - PAGE_SHIFT); + + size = (1 << order) * PAGE_SIZE; + if (shared) { + alloc_order_fn = &alloc_pages_shared; + free_order_fn = &free_pages_shared_by_order; + } else { + alloc_order_fn = &alloc_pages; + free_order_fn = &free_pages_by_order; + } + + report_info("Running %smemtest with size %dK%s, order=%d", + shared ? "shared " : "", + size >> 10, + nofree ? " with no freeing" :"", + order); + + while (1) { + void *page = alloc_order_fn(order); + + if (!page) + break; + npages += 1; + + memset(page, pattern, size); + + for (i = 0; i < size; i += 1) { + if (((char *)page)[i] != pattern) { + result = false; + report(false, "Failed to find the pattern in page %p, expected: %d, got: %d\n", + page, pattern, ((char *)page)[i]); + goto exit; + } + } + + /* + * Save a pointer to the allocated page so that it can be + * free'd at the end of the test. + */ + *(uintptr_t *)page = (uintptr_t)prev_page; + prev_page = page; + } + + page_to_free = prev_page; + while (!nofree && page_to_free) { + prev_page = (uintptr_t *)(*page_to_free); + free_order_fn(page_to_free, order); + page_to_free = prev_page; + } + +exit: + report(result, "Tested with %dKB", (npages * size) >> 10); +} + +static void do_memstress(void) +{ + char shared[16] = "shared"; + char block[16] = "block"; + char nofree[16] = "nofree"; + char null[4] = ""; + + do_memtest(4, &((char *[]){ null, null, shared, block })[0]); + do_memtest(3, &((char *[]){ null, null, block })[0]); + do_memtest(3, &((char *[]){ null, null, shared })[0]); + do_memtest(3, &((char *[]){ null, null, nofree })[0]); +} + int main(int argc, char **argv) { report_prefix_push("selftest"); @@ -466,7 +584,10 @@ int main(int argc, char **argv) smp_rmb(); /* Paired with wmb in cpu_report(). */ report(cpumask_full(&valid), "MPIDR test on all CPUs"); report_info("%d CPUs reported back", nr_cpus); - + } else if (strcmp(argv[1], "memtest") == 0) { + do_memtest(argc, argv); + } else if (strcmp(argv[1], "memstress") == 0) { + do_memstress(); } else { printf("Unknown subtest\n"); abort();