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
next prev 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