mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>,
	lst@pengutronix.de, rcz@pengutronix.de
Subject: [PATCH 10/11] test: self: add MMU remapping self test
Date: Mon, 22 May 2023 07:28:34 +0200	[thread overview]
Message-ID: <20230522052835.1039143-11-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20230522052835.1039143-1-a.fatoum@pengutronix.de>

ARM mmu code in barebox has recently seen some changes to enhance
remapping. Add a self test that exercises this a bit.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 test/self/Kconfig  |   6 ++
 test/self/Makefile |   1 +
 test/self/mmu.c    | 233 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 240 insertions(+)
 create mode 100644 test/self/mmu.c

diff --git a/test/self/Kconfig b/test/self/Kconfig
index ce5048c70ec9..c130209748aa 100644
--- a/test/self/Kconfig
+++ b/test/self/Kconfig
@@ -36,6 +36,7 @@ config SELFTEST_ENABLE_ALL
 	imply SELFTEST_FS_RAMFS
 	imply SELFTEST_TFTP
 	imply SELFTEST_JSON
+	imply SELFTEST_MMU
 	help
 	  Selects all self-tests compatible with current configuration
 
@@ -69,4 +70,9 @@ config SELFTEST_JSON
 	bool "JSON selftest"
 	depends on JSMN
 
+config SELFTEST_MMU
+	bool "MMU remapping selftest"
+	select MEMTEST
+	depends on MMU
+
 endif
diff --git a/test/self/Makefile b/test/self/Makefile
index 98ebd1fd66c1..8c816c4299f6 100644
--- a/test/self/Makefile
+++ b/test/self/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_SELFTEST_OF_MANIPULATION) += of_manipulation.o of_manipulation.dtb.
 obj-$(CONFIG_SELFTEST_ENVIRONMENT_VARIABLES) += envvar.o
 obj-$(CONFIG_SELFTEST_FS_RAMFS) += ramfs.o
 obj-$(CONFIG_SELFTEST_JSON) += json.o
+obj-$(CONFIG_SELFTEST_MMU) += mmu.o
 
 clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.z
 clean-files += *.dtbo *.dtbo.S .*.dtso
diff --git a/test/self/mmu.c b/test/self/mmu.c
new file mode 100644
index 000000000000..ee6c1cd45e7e
--- /dev/null
+++ b/test/self/mmu.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0-onl
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <common.h>
+#include <bselftest.h>
+#include <mmu.h>
+#include <memtest.h>
+#include <abort.h>
+#include <zero_page.h>
+#include <linux/sizes.h>
+
+BSELFTEST_GLOBALS();
+
+#define __expect(ret, cond, fmt, ...) do { \
+	bool __cond = (cond); \
+	int __ret = (ret); \
+	total_tests++; \
+	\
+	if (!__cond) { \
+		failed_tests++; \
+		printf("%s:%d error %pe: " fmt "\n", \
+		       __func__, __LINE__, ERR_PTR(__ret), ##__VA_ARGS__); \
+	} \
+} while (0)
+
+#define expect_success(ret, ...) __expect((ret), ((ret) >= 0), __VA_ARGS__)
+
+static void memtest(void __iomem *start, size_t size, const char *desc)
+{
+	int ret;
+
+	ret = mem_test_bus_integrity((resource_size_t)start,
+				     (resource_size_t)start + size - 1, 0);
+	expect_success(ret, "%s bus test", desc);
+
+	ret = mem_test_moving_inversions((resource_size_t)start,
+					 (resource_size_t)start + size - 1, 0);
+	expect_success(ret, "%s moving inverstions test", desc);
+}
+
+static inline int __check_mirroring(void __iomem *a, void __iomem *b, bool is_mirror,
+				    const char *func, int line)
+{
+	if ((readl(a) == readl(b)) == (is_mirror))
+		return 0;
+
+	printf("%s:%d: mirroring unexpectedly %s: (*%p = 0x%x) %s (*%p = 0x%x)\n", func, line,
+	       is_mirror ? "failed" : "succeeded",
+	       a, readl(a), is_mirror ? "!=" : "==", b, readl(b));
+
+	mmuinfo(a);
+	mmuinfo(b);
+
+	return -EILSEQ;
+}
+
+#define check_mirroring(a, b, is_mirror) \
+	__check_mirroring((a), (b), (is_mirror), __func__, __LINE__)
+
+static void test_remap(void)
+{
+	u8 __iomem *buffer = NULL, *mirror = NULL;
+	phys_addr_t buffer_phys;
+	int i, ret;
+
+	buffer = memalign(SZ_2M, SZ_8M);
+	if (WARN_ON(!buffer))
+		goto out;
+
+	buffer_phys = virt_to_phys(buffer);
+
+	mirror = memalign(SZ_2M, SZ_8M);
+	if (WARN_ON(!mirror))
+		goto out;
+
+	pr_debug("allocated buffer = 0x%p, mirror = 0x%p\n", buffer, mirror);
+
+	memtest(buffer, SZ_8M, "cached buffer");
+	memtest(mirror, SZ_8M, "cached mirror");
+
+	if (__is_defined(ARCH_HAS_REMAP)) {
+		skipped_tests += 10;
+		goto out;
+	}
+
+	ret = remap_range(buffer, SZ_8M, MAP_UNCACHED);
+	memtest(buffer, SZ_8M, "uncached buffer");
+
+	ret = remap_range(mirror, SZ_8M, MAP_UNCACHED);
+	memtest(mirror, SZ_8M, "uncached mirror");
+
+	for (i = 0; i < SZ_8M; i += sizeof(u32)) {
+		int m = i, b = i;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], false);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting no mirror before remap");
+
+	ret = arch_remap_range(mirror, buffer_phys, SZ_8M, MAP_UNCACHED);
+	expect_success(ret, "remapping with mirroring");
+
+	for (i = 0; i < SZ_8M; i += sizeof(u32)) {
+		int m = i, b = i;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], true);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting mirroring after remap");
+
+	ret = arch_remap_range(mirror, buffer_phys + SZ_4K, SZ_4M, MAP_UNCACHED);
+	expect_success(ret, "remapping with mirroring (phys += 4K)");
+
+	for (i = 0; i < SZ_4M; i += sizeof(u32)) {
+		int m = i, b = i + SZ_4K;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], true);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting mirroring after remap (phys += 4K)");
+
+	ret = arch_remap_range(mirror + SZ_4K, buffer_phys, SZ_4M, MAP_UNCACHED);
+	expect_success(ret, "remapping with mirroring (virt += 4K)");
+
+	for (i = 0; i < SZ_4M; i += sizeof(u32)) {
+		int m = i + SZ_4K, b = i;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], true);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting mirroring after remap (virt += 4K)");
+	return;
+
+	ret = remap_range(buffer, SZ_8M, MAP_DEFAULT);
+	expect_success(ret, "remapping buffer with default attrs");
+	memtest(buffer, SZ_8M, "newly cached buffer");
+
+	ret = remap_range(mirror, SZ_8M, MAP_DEFAULT);
+	expect_success(ret, "remapping mirror with default attrs");
+	memtest(mirror, SZ_8M, "newly cached mirror");
+
+	for (i = 0; i < SZ_8M; i += sizeof(u32)) {
+		int m = i, b = i;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], false);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting no mirror after remap restore");
+out:
+	free(buffer);
+	free(mirror);
+}
+
+static void test_zero_page(void)
+{
+	void __iomem *null = NULL;
+
+	total_tests += 3;
+
+	if (!IS_ENABLED(CONFIG_ARCH_HAS_DATA_ABORT_MASK)) {
+		pr_info("skipping %s because %s=n\n",
+			"CONFIG_ARCH_HAS_DATA_ABORT_MASK", __func__);
+		skipped_tests += 3;
+		return;
+	}
+
+	OPTIMIZER_HIDE_VAR(null);
+
+	/* Check if *NULL traps and data_abort_mask works */
+
+	data_abort_mask();
+
+	(void)readl(null);
+
+	if (!data_abort_unmask()) {
+		printf("%s: NULL pointer access did not trap\n", __func__);
+		failed_tests++;
+	}
+
+	if (!IS_ENABLED(CONFIG_ARCH_HAS_ZERO_PAGE)) {
+		pr_info("skipping %s because %s=n\n",
+			"CONFIG_ARCH_HAS_ZERO_PAGE", __func__);
+		skipped_tests += 2;
+		return;
+	}
+
+	/* Check if zero_page_access() works */
+
+	data_abort_mask();
+
+	zero_page_access();
+	(void)readl(null);
+	zero_page_faulting();
+
+	if (data_abort_unmask()) {
+		printf("%s: unexpected fault on zero page access\n", __func__);
+		failed_tests++;
+	}
+
+	/* Check if zero_page_faulting() works */
+
+	data_abort_mask();
+
+	(void)readl(null);
+
+	if (!data_abort_unmask()) {
+		printf("%s NULL pointer access did not trap\n", __func__);
+		failed_tests++;
+	}
+}
+
+static void test_mmu(void)
+{
+	test_zero_page();
+	test_remap();
+}
+bselftest(core, test_mmu);
-- 
2.39.2




  parent reply	other threads:[~2023-05-22  5:30 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 01/11] treewide: use remap_range instead of arch_remap_range Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 02/11] mmu: add physical address parameter to arch_remap_range Ahmad Fatoum
2023-05-23  7:17   ` Sascha Hauer
2023-05-23  7:21     ` Ahmad Fatoum
2023-05-23  7:27       ` Sascha Hauer
2023-05-22  5:28 ` [PATCH 03/11] ARM: mmu32: support non-1:1 mappings in arch_remap_range Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 04/11] ARM: mmu64: " Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 05/11] of: platform: remap memory when encountering virtual-reg property Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 06/11] common: boards: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 07/11] ARM: prepare extending mmuinfo beyond ARMv7 Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 08/11] ARM64: mmu: implement ARMv8 mmuinfo command Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 09/11] common: memtest: prepare for reuse in self test Ahmad Fatoum
2023-05-22  5:28 ` Ahmad Fatoum [this message]
2023-05-22  5:28 ` [PATCH 11/11] ARM: mmuinfo: add options for enabling/disabling zero page trapping Ahmad Fatoum
2023-05-23  7:21 ` [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230522052835.1039143-11-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=lst@pengutronix.de \
    --cc=rcz@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox