new file mode 100644
@@ -0,0 +1,598 @@
+/*
+ * QEMU memory region access test
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (c) 2024 IGEL Co., Ltd.
+ * Author: Tomoyuki HIROSE <tomoyuki.hirose@igel.co.jp>
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+#include "hw/misc/memaccess-testdev.h"
+
+static const char *arch = "";
+static const hwaddr base = 0x200000000;
+
+struct arch2cpu {
+ const char *arch;
+ const char *cpu_model;
+};
+
+static struct arch2cpu cpus_map[] = {
+ /* tested targets list */
+ { "arm", "cortex-a15" },
+ { "aarch64", "cortex-a57" },
+ { "avr", "avr6-avr-cpu" },
+ { "x86_64", "qemu64,apic-id=0" },
+ { "i386", "qemu32,apic-id=0" },
+ { "alpha", "ev67" },
+ { "cris", "crisv32" },
+ { "m68k", "m5206" },
+ { "microblaze", "any" },
+ { "microblazeel", "any" },
+ { "mips", "4Kc" },
+ { "mipsel", "I7200" },
+ { "mips64", "20Kc" },
+ { "mips64el", "I6500" },
+ { "or1k", "or1200" },
+ { "ppc", "604" },
+ { "ppc64", "power8e_v2.1" },
+ { "s390x", "qemu" },
+ { "sh4", "sh7750r" },
+ { "sh4eb", "sh7751r" },
+ { "sparc", "LEON2" },
+ { "sparc64", "Fujitsu Sparc64" },
+ { "tricore", "tc1796" },
+ { "xtensa", "dc233c" },
+ { "xtensaeb", "fsf" },
+ { "hppa", "hppa" },
+ { "riscv64", "rv64" },
+ { "riscv32", "rv32" },
+ { "rx", "rx62n" },
+ { "loongarch64", "la464" },
+};
+
+static const char *get_cpu_model_by_arch(const char *arch)
+{
+ for (int i = 0; i < ARRAY_SIZE(cpus_map); i++) {
+ if (!strcmp(arch, cpus_map[i].arch)) {
+ return cpus_map[i].cpu_model;
+ }
+ }
+ return NULL;
+}
+
+static QTestState *create_memaccess_qtest(void)
+{
+ QTestState *qts;
+
+ qts = qtest_initf("-machine none -cpu \"%s\" "
+ "-device memaccess-testdev,address=0x%" PRIx64,
+ get_cpu_model_by_arch(arch), base);
+ return qts;
+}
+
+static void little_b_valid(QTestState *qts, uint64_t offset)
+{
+ qtest_writeb(qts, base + offset + 0, 0x00);
+ qtest_writeb(qts, base + offset + 1, 0x11);
+ qtest_writeb(qts, base + offset + 2, 0x22);
+ qtest_writeb(qts, base + offset + 3, 0x33);
+ qtest_writeb(qts, base + offset + 4, 0x44);
+ qtest_writeb(qts, base + offset + 5, 0x55);
+ qtest_writeb(qts, base + offset + 6, 0x66);
+ qtest_writeb(qts, base + offset + 7, 0x77);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 0), ==, 0x00);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 1), ==, 0x11);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 2), ==, 0x22);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 3), ==, 0x33);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 4), ==, 0x44);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 5), ==, 0x55);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 6), ==, 0x66);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 7), ==, 0x77);
+}
+
+static void little_b_invalid(QTestState *qts, uint64_t offset)
+{
+ qtest_writeb(qts, base + offset + 0, 0x00);
+ qtest_writeb(qts, base + offset + 1, 0x11);
+ qtest_writeb(qts, base + offset + 2, 0x22);
+ qtest_writeb(qts, base + offset + 3, 0x33);
+ qtest_writeb(qts, base + offset + 4, 0x44);
+ qtest_writeb(qts, base + offset + 5, 0x55);
+ qtest_writeb(qts, base + offset + 6, 0x66);
+ qtest_writeb(qts, base + offset + 7, 0x77);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 0), ==, 0x00);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 1), ==, 0x11);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 2), ==, 0x22);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 3), ==, 0x33);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 4), ==, 0x44);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 5), ==, 0x55);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 6), ==, 0x66);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 7), ==, 0x77);
+}
+
+static void little_w_valid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writew(qts, base + offset + 0, 0x1100);
+ qtest_writew(qts, base + offset + 1, 0x3322);
+ qtest_writew(qts, base + offset + 2, 0x5544);
+ qtest_writew(qts, base + offset + 3, 0x7766);
+ qtest_writew(qts, base + offset + 4, 0x9988);
+ qtest_writew(qts, base + offset + 5, 0xbbaa);
+ qtest_writew(qts, base + offset + 6, 0xddcc);
+ qtest_writew(qts, base + offset + 7, 0xffee);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 0), ==, 0x1133);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 1), ==, 0x3355);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 2), ==, 0x5577);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 3), ==, 0x7799);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 4), ==, 0x99bb);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 5), ==, 0xbbdd);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 6), ==, 0xddff);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 7), ==, 0xffee);
+ } else {
+ qtest_writew(qts, base + offset + 0, 0x1100);
+ qtest_writew(qts, base + offset + 1, 0x3322);
+ qtest_writew(qts, base + offset + 2, 0x5544);
+ qtest_writew(qts, base + offset + 3, 0x7766);
+ qtest_writew(qts, base + offset + 4, 0x9988);
+ qtest_writew(qts, base + offset + 5, 0xbbaa);
+ qtest_writew(qts, base + offset + 6, 0xddcc);
+ qtest_writew(qts, base + offset + 7, 0xffee);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 0), ==, 0x2200);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 1), ==, 0x4422);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 2), ==, 0x6644);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 3), ==, 0x8866);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 4), ==, 0xaa88);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 5), ==, 0xccaa);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 6), ==, 0xeecc);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 7), ==, 0xffee);
+ }
+}
+
+static void little_w_invalid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writew(qts, base + offset + 0, 0x1100);
+ qtest_writew(qts, base + offset + 2, 0x3322);
+ qtest_writew(qts, base + offset + 4, 0x5544);
+ qtest_writew(qts, base + offset + 6, 0x7766);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 0), ==, 0x1100);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 2), ==, 0x3322);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 4), ==, 0x5544);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 6), ==, 0x7766);
+ } else {
+ qtest_writew(qts, base + offset + 0, 0x1100);
+ qtest_writew(qts, base + offset + 2, 0x3322);
+ qtest_writew(qts, base + offset + 4, 0x5544);
+ qtest_writew(qts, base + offset + 6, 0x7766);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 0), ==, 0x1100);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 2), ==, 0x3322);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 4), ==, 0x5544);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 6), ==, 0x7766);
+ }
+}
+
+static void little_l_valid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writel(qts, base + offset + 0, 0x33221100);
+ qtest_writel(qts, base + offset + 1, 0x77665544);
+ qtest_writel(qts, base + offset + 2, 0xbbaa9988);
+ qtest_writel(qts, base + offset + 3, 0xffeeddcc);
+ qtest_writel(qts, base + offset + 4, 0x01234567);
+ qtest_writel(qts, base + offset + 5, 0x89abcdef);
+ qtest_writel(qts, base + offset + 6, 0xfedcba98);
+ qtest_writel(qts, base + offset + 7, 0x76543210);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 0), ==, 0x3377bbff);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 1), ==, 0x77bbff01);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 2), ==, 0xbbff0189);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 3), ==, 0xff0189fe);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 4), ==, 0x0189fe76);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 5), ==, 0x89fe7654);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 6), ==, 0xfe765432);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 7), ==, 0x76543210);
+ } else {
+ qtest_writel(qts, base + offset + 0, 0x33221100);
+ qtest_writel(qts, base + offset + 1, 0x77665544);
+ qtest_writel(qts, base + offset + 2, 0xbbaa9988);
+ qtest_writel(qts, base + offset + 3, 0xffeeddcc);
+ qtest_writel(qts, base + offset + 4, 0x01234567);
+ qtest_writel(qts, base + offset + 5, 0x89abcdef);
+ qtest_writel(qts, base + offset + 6, 0xfedcba98);
+ qtest_writel(qts, base + offset + 7, 0x76543210);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 0), ==, 0xcc884400);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 1), ==, 0x67cc8844);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 2), ==, 0xef67cc88);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 3), ==, 0x98ef67cc);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 4), ==, 0x1098ef67);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 5), ==, 0x321098ef);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 6), ==, 0x54321098);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 7), ==, 0x76543210);
+ }
+}
+
+static void little_l_invalid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writel(qts, base + offset + 0, 0x33221100);
+ qtest_writel(qts, base + offset + 4, 0x77665544);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 0), ==, 0x33221100);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 4), ==, 0x77665544);
+ } else {
+ qtest_writel(qts, base + offset + 0, 0x33221100);
+ qtest_writel(qts, base + offset + 4, 0x77665544);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 0), ==, 0x33221100);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 4), ==, 0x77665544);
+ }
+}
+
+static void little_q_valid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writeq(qts, base + offset + 0, 0x7766554433221100);
+ qtest_writeq(qts, base + offset + 1, 0xffeeddccbbaa9988);
+ qtest_writeq(qts, base + offset + 2, 0xfedcba9876543210);
+ qtest_writeq(qts, base + offset + 3, 0x0123456789abcdef);
+ qtest_writeq(qts, base + offset + 4, 0xdeadbeefdeadbeef);
+ qtest_writeq(qts, base + offset + 5, 0xcafebabecafebabe);
+ qtest_writeq(qts, base + offset + 6, 0xbeefcafebeefcafe);
+ qtest_writeq(qts, base + offset + 7, 0xfacefeedfacefeed);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 0), ==,
+ 0x77fffe01decabefa);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 1), ==,
+ 0xfffe01decabeface);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 2), ==,
+ 0xfe01decabefacefe);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 3), ==,
+ 0x01decabefacefeed);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 4), ==,
+ 0xdecabefacefeedfa);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 5), ==,
+ 0xcabefacefeedface);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 6), ==,
+ 0xbefacefeedfacefe);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 7), ==,
+ 0xfacefeedfacefeed);
+ } else {
+ qtest_writeq(qts, base + offset + 0, 0x7766554433221100);
+ qtest_writeq(qts, base + offset + 1, 0xffeeddccbbaa9988);
+ qtest_writeq(qts, base + offset + 2, 0xfedcba9876543210);
+ qtest_writeq(qts, base + offset + 3, 0x0123456789abcdef);
+ qtest_writeq(qts, base + offset + 4, 0xdeadbeefdeadbeef);
+ qtest_writeq(qts, base + offset + 5, 0xcafebabecafebabe);
+ qtest_writeq(qts, base + offset + 6, 0xbeefcafebeefcafe);
+ qtest_writeq(qts, base + offset + 7, 0xfacefeedfacefeed);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 0), ==,
+ 0xedfebeefef108800);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 1), ==,
+ 0xfeedfebeefef1088);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 2), ==,
+ 0xcefeedfebeefef10);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 3), ==,
+ 0xfacefeedfebeefef);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 4), ==,
+ 0xedfacefeedfebeef);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 5), ==,
+ 0xfeedfacefeedfebe);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 6), ==,
+ 0xcefeedfacefeedfe);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 7), ==,
+ 0xfacefeedfacefeed);
+ }
+}
+
+static void little_q_invalid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writeq(qts, base + offset + 0, 0x7766554433221100);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 0), ==,
+ 0x7766554433221100);
+ } else {
+ qtest_writeq(qts, base + offset + 0, 0x7766554433221100);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 0), ==,
+ 0x7766554433221100);
+ }
+}
+
+static void big_b_valid(QTestState *qts, uint64_t offset)
+{
+ qtest_writeb(qts, base + offset + 0, 0x00);
+ qtest_writeb(qts, base + offset + 1, 0x11);
+ qtest_writeb(qts, base + offset + 2, 0x22);
+ qtest_writeb(qts, base + offset + 3, 0x33);
+ qtest_writeb(qts, base + offset + 4, 0x44);
+ qtest_writeb(qts, base + offset + 5, 0x55);
+ qtest_writeb(qts, base + offset + 6, 0x66);
+ qtest_writeb(qts, base + offset + 7, 0x77);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 0), ==, 0x00);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 1), ==, 0x11);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 2), ==, 0x22);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 3), ==, 0x33);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 4), ==, 0x44);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 5), ==, 0x55);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 6), ==, 0x66);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 7), ==, 0x77);
+}
+
+static void big_b_invalid(QTestState *qts, uint64_t offset)
+{
+ qtest_writeb(qts, base + offset + 0, 0x00);
+ qtest_writeb(qts, base + offset + 1, 0x11);
+ qtest_writeb(qts, base + offset + 2, 0x22);
+ qtest_writeb(qts, base + offset + 3, 0x33);
+ qtest_writeb(qts, base + offset + 4, 0x44);
+ qtest_writeb(qts, base + offset + 5, 0x55);
+ qtest_writeb(qts, base + offset + 6, 0x66);
+ qtest_writeb(qts, base + offset + 7, 0x77);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 0), ==, 0x00);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 1), ==, 0x11);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 2), ==, 0x22);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 3), ==, 0x33);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 4), ==, 0x44);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 5), ==, 0x55);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 6), ==, 0x66);
+ g_assert_cmphex(qtest_readb(qts, base + offset + 7), ==, 0x77);
+}
+
+static void big_w_valid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writew(qts, base + offset + 0, 0x1100);
+ qtest_writew(qts, base + offset + 1, 0x3322);
+ qtest_writew(qts, base + offset + 2, 0x5544);
+ qtest_writew(qts, base + offset + 3, 0x7766);
+ qtest_writew(qts, base + offset + 4, 0x9988);
+ qtest_writew(qts, base + offset + 5, 0xbbaa);
+ qtest_writew(qts, base + offset + 6, 0xddcc);
+ qtest_writew(qts, base + offset + 7, 0xffee);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 0), ==, 0x1133);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 1), ==, 0x3355);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 2), ==, 0x5577);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 3), ==, 0x7799);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 4), ==, 0x99bb);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 5), ==, 0xbbdd);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 6), ==, 0xddff);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 7), ==, 0xffee);
+ } else {
+ qtest_writew(qts, base + offset + 0, 0x1100);
+ qtest_writew(qts, base + offset + 1, 0x3322);
+ qtest_writew(qts, base + offset + 2, 0x5544);
+ qtest_writew(qts, base + offset + 3, 0x7766);
+ qtest_writew(qts, base + offset + 4, 0x9988);
+ qtest_writew(qts, base + offset + 5, 0xbbaa);
+ qtest_writew(qts, base + offset + 6, 0xddcc);
+ qtest_writew(qts, base + offset + 7, 0xffee);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 0), ==, 0x2200);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 1), ==, 0x4422);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 2), ==, 0x6644);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 3), ==, 0x8866);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 4), ==, 0xaa88);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 5), ==, 0xccaa);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 6), ==, 0xeecc);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 7), ==, 0xffee);
+ }
+}
+
+static void big_w_invalid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writew(qts, base + offset + 0, 0x1100);
+ qtest_writew(qts, base + offset + 2, 0x3322);
+ qtest_writew(qts, base + offset + 4, 0x5544);
+ qtest_writew(qts, base + offset + 6, 0x7766);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 0), ==, 0x1100);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 2), ==, 0x3322);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 4), ==, 0x5544);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 6), ==, 0x7766);
+ } else {
+ qtest_writew(qts, base + offset + 0, 0x1100);
+ qtest_writew(qts, base + offset + 2, 0x3322);
+ qtest_writew(qts, base + offset + 4, 0x5544);
+ qtest_writew(qts, base + offset + 6, 0x7766);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 0), ==, 0x1100);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 2), ==, 0x3322);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 4), ==, 0x5544);
+ g_assert_cmphex(qtest_readw(qts, base + offset + 6), ==, 0x7766);
+ }
+}
+
+static void big_l_valid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writel(qts, base + offset + 0, 0x33221100);
+ qtest_writel(qts, base + offset + 1, 0x77665544);
+ qtest_writel(qts, base + offset + 2, 0xbbaa9988);
+ qtest_writel(qts, base + offset + 3, 0xffeeddcc);
+ qtest_writel(qts, base + offset + 4, 0x01234567);
+ qtest_writel(qts, base + offset + 5, 0x89abcdef);
+ qtest_writel(qts, base + offset + 6, 0xfedcba98);
+ qtest_writel(qts, base + offset + 7, 0x76543210);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 0), ==, 0x3377bbff);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 1), ==, 0x77bbff01);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 2), ==, 0xbbff0189);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 3), ==, 0xff0189fe);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 4), ==, 0x0189fe76);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 5), ==, 0x89fe7654);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 6), ==, 0xfe765432);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 7), ==, 0x76543210);
+ } else {
+ qtest_writel(qts, base + offset + 0, 0x33221100);
+ qtest_writel(qts, base + offset + 1, 0x77665544);
+ qtest_writel(qts, base + offset + 2, 0xbbaa9988);
+ qtest_writel(qts, base + offset + 3, 0xffeeddcc);
+ qtest_writel(qts, base + offset + 4, 0x01234567);
+ qtest_writel(qts, base + offset + 5, 0x89abcdef);
+ qtest_writel(qts, base + offset + 6, 0xfedcba98);
+ qtest_writel(qts, base + offset + 7, 0x76543210);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 0), ==, 0xcc884400);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 1), ==, 0x67cc8844);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 2), ==, 0xef67cc88);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 3), ==, 0x98ef67cc);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 4), ==, 0x1098ef67);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 5), ==, 0x321098ef);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 6), ==, 0x54321098);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 7), ==, 0x76543210);
+ }
+}
+
+static void big_l_invalid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writel(qts, base + offset + 0, 0x33221100);
+ qtest_writel(qts, base + offset + 4, 0x77665544);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 0), ==, 0x33221100);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 4), ==, 0x77665544);
+ } else {
+ qtest_writel(qts, base + offset + 0, 0x33221100);
+ qtest_writel(qts, base + offset + 4, 0x77665544);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 0), ==, 0x33221100);
+ g_assert_cmphex(qtest_readl(qts, base + offset + 4), ==, 0x77665544);
+ }
+}
+
+static void big_q_valid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writeq(qts, base + offset + 0, 0x7766554433221100);
+ qtest_writeq(qts, base + offset + 1, 0xffeeddccbbaa9988);
+ qtest_writeq(qts, base + offset + 2, 0xfedcba9876543210);
+ qtest_writeq(qts, base + offset + 3, 0x0123456789abcdef);
+ qtest_writeq(qts, base + offset + 4, 0xdeadbeefdeadbeef);
+ qtest_writeq(qts, base + offset + 5, 0xcafebabecafebabe);
+ qtest_writeq(qts, base + offset + 6, 0xbeefcafebeefcafe);
+ qtest_writeq(qts, base + offset + 7, 0xfacefeedfacefeed);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 0), ==,
+ 0x77fffe01decabefa);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 1), ==,
+ 0xfffe01decabeface);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 2), ==,
+ 0xfe01decabefacefe);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 3), ==,
+ 0x01decabefacefeed);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 4), ==,
+ 0xdecabefacefeedfa);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 5), ==,
+ 0xcabefacefeedface);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 6), ==,
+ 0xbefacefeedfacefe);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 7), ==,
+ 0xfacefeedfacefeed);
+ } else {
+ qtest_writeq(qts, base + offset + 0, 0x7766554433221100);
+ qtest_writeq(qts, base + offset + 1, 0xffeeddccbbaa9988);
+ qtest_writeq(qts, base + offset + 2, 0xfedcba9876543210);
+ qtest_writeq(qts, base + offset + 3, 0x0123456789abcdef);
+ qtest_writeq(qts, base + offset + 4, 0xdeadbeefdeadbeef);
+ qtest_writeq(qts, base + offset + 5, 0xcafebabecafebabe);
+ qtest_writeq(qts, base + offset + 6, 0xbeefcafebeefcafe);
+ qtest_writeq(qts, base + offset + 7, 0xfacefeedfacefeed);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 0), ==,
+ 0xedfebeefef108800);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 1), ==,
+ 0xfeedfebeefef1088);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 2), ==,
+ 0xcefeedfebeefef10);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 3), ==,
+ 0xfacefeedfebeefef);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 4), ==,
+ 0xedfacefeedfebeef);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 5), ==,
+ 0xfeedfacefeedfebe);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 6), ==,
+ 0xcefeedfacefeedfe);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 7), ==,
+ 0xfacefeedfacefeed);
+ }
+}
+
+static void big_q_invalid(QTestState *qts, hwaddr offset)
+{
+ if (qtest_big_endian(qts)) {
+ qtest_writeq(qts, base + offset + 0, 0x7766554433221100);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 0), ==,
+ 0x7766554433221100);
+ } else {
+ qtest_writeq(qts, base + offset + 0, 0x7766554433221100);
+ g_assert_cmphex(qtest_readq(qts, base + offset + 0), ==,
+ 0x7766554433221100);
+ }
+}
+
+#define DEFINE_test_memaccess(e, e_u, w, w_u, v, v_u) \
+ static void \
+ test_memaccess_##e##_##w##_##v(void) \
+ { \
+ QTestState *qts; \
+ qts = create_memaccess_qtest(); \
+ if (!qts) { \
+ return; \
+ } \
+ \
+ for (size_t i = OFF_IDX_OPS_LIST_##e_u##_##w_u##_##v_u; \
+ i < OFF_IDX_OPS_LIST_##e_u##_##w_u##_##v_u + \
+ N_OPS_LIST_##e_u##_##w_u##_##v_u; \
+ i++) { \
+ e##_##w##_##v(qts, MEMACCESS_TESTDEV_REGION_SIZE * i); \
+ } \
+ \
+ qtest_quit(qts); \
+ }
+
+DEFINE_test_memaccess(little, LITTLE, b, B, valid, VALID)
+DEFINE_test_memaccess(little, LITTLE, w, W, valid, VALID)
+DEFINE_test_memaccess(little, LITTLE, l, L, valid, VALID)
+DEFINE_test_memaccess(little, LITTLE, q, Q, valid, VALID)
+DEFINE_test_memaccess(little, LITTLE, b, B, invalid, INVALID)
+DEFINE_test_memaccess(little, LITTLE, w, W, invalid, INVALID)
+DEFINE_test_memaccess(little, LITTLE, l, L, invalid, INVALID)
+DEFINE_test_memaccess(little, LITTLE, q, Q, invalid, INVALID)
+DEFINE_test_memaccess(big, BIG, b, B, valid, VALID)
+DEFINE_test_memaccess(big, BIG, w, W, valid, VALID)
+DEFINE_test_memaccess(big, BIG, l, L, valid, VALID)
+DEFINE_test_memaccess(big, BIG, q, Q, valid, VALID)
+DEFINE_test_memaccess(big, BIG, b, B, invalid, INVALID)
+DEFINE_test_memaccess(big, BIG, w, W, invalid, INVALID)
+DEFINE_test_memaccess(big, BIG, l, L, invalid, INVALID)
+DEFINE_test_memaccess(big, BIG, q, Q, invalid, INVALID)
+
+#undef DEFINE_test_memaccess
+
+static struct {
+ const char *name;
+ void (*test)(void);
+} tests[] = {
+ {"little_b_valid", test_memaccess_little_b_valid},
+ {"little_w_valid", test_memaccess_little_w_valid},
+ {"little_l_valid", test_memaccess_little_l_valid},
+ {"little_q_valid", test_memaccess_little_q_valid},
+ {"little_b_invalid", test_memaccess_little_b_invalid},
+ {"little_w_invalid", test_memaccess_little_w_invalid},
+ {"little_l_invalid", test_memaccess_little_l_invalid},
+ {"little_q_invalid", test_memaccess_little_q_invalid},
+ {"big_b_valid", test_memaccess_big_b_valid},
+ {"big_w_valid", test_memaccess_big_w_valid},
+ {"big_l_valid", test_memaccess_big_l_valid},
+ {"big_q_valid", test_memaccess_big_q_valid},
+ {"big_b_invalid", test_memaccess_big_b_invalid},
+ {"big_w_invalid", test_memaccess_big_w_invalid},
+ {"big_l_invalid", test_memaccess_big_l_invalid},
+ {"big_q_invalid", test_memaccess_big_q_invalid},
+};
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ arch = qtest_get_arch();
+
+ for (int i = 0; i < ARRAY_SIZE(tests); i++) {
+ g_autofree gchar *path = g_strdup_printf("memaccess/%s", tests[i].name);
+ qtest_add_func(path, tests[i].test);
+ }
+
+ return g_test_run();
+}
@@ -93,6 +93,7 @@ qtests_i386 = \
(config_all_devices.has_key('CONFIG_SB16') ? ['fuzz-sb16-test'] : []) + \
(config_all_devices.has_key('CONFIG_SDHCI_PCI') ? ['fuzz-sdcard-test'] : []) + \
(config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) + \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
(host_os != 'windows' and \
config_all_devices.has_key('CONFIG_ACPI_ERST') ? ['erst-test'] : []) + \
(config_all_devices.has_key('CONFIG_PCIE_PORT') and \
@@ -136,6 +137,7 @@ qtests_x86_64 = qtests_i386
qtests_alpha = ['boot-serial-test'] + \
qtests_filter + \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
(config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : [])
qtests_avr = [ 'boot-serial-test' ]
@@ -158,6 +160,7 @@ qtests_microblazeel = qtests_microblaze
qtests_mips = \
qtests_filter + \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
(config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \
(config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : [])
@@ -169,6 +172,7 @@ qtests_ppc = \
qtests_filter + \
(config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \
(config_all_devices.has_key('CONFIG_M48T59') ? ['m48t59-test'] : []) + \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
(config_all_accel.has_key('CONFIG_TCG') ? ['prom-env-test'] : []) + \
(config_all_accel.has_key('CONFIG_TCG') ? ['boot-serial-test'] : []) + \
['boot-order-test']
@@ -195,6 +199,7 @@ qtests_sparc = ['prom-env-test', 'm48t59-test', 'boot-serial-test'] + \
qtests_sparc64 = \
(config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
qtests_filter + \
['prom-env-test', 'boot-serial-test']
@@ -240,6 +245,7 @@ qtests_arm = \
(config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['aspeed_fsi-test'] : []) + \
(config_all_devices.has_key('CONFIG_STM32L4X5_SOC') and
config_all_devices.has_key('CONFIG_DM163')? ['dm163-test'] : []) + \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
['arm-cpu-features',
'boot-serial-test']
@@ -254,6 +260,7 @@ qtests_aarch64 = \
(config_all_accel.has_key('CONFIG_TCG') and \
config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
(config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed64 : []) + \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
['arm-cpu-features',
'numa-test',
'boot-serial-test',
@@ -269,9 +276,11 @@ qtests_s390x = \
'migration-test']
qtests_riscv32 = \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
(config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? ['sifive-e-aon-watchdog-test'] : [])
qtests_riscv64 = \
+ (config_all_devices.has_key('CONFIG_MEMACCESS_TESTDEV') ? ['memaccess-test'] : []) + \
(unpack_edk2_blobs ? ['bios-tables-test'] : [])
qos_test_ss = ss.source_set()
This commit adds a qtest for accessing various memory regions. The qtest checks the correctness of handling the access to memory regions by using 'memaccess-testdev'. Signed-off-by: Tomoyuki HIROSE <tomoyuki.hirose@igel.co.jp> --- tests/qtest/memaccess-test.c | 598 +++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 9 + 2 files changed, 607 insertions(+) create mode 100644 tests/qtest/memaccess-test.c