Add generic MMIO tests (which don't need any particular knowledge about the architecture) and can be run without any CPU (using the 'none' machine).
Start testing the interleaved memory accesses. Cross-endianess is not tested (host and target must have the same endianess). Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org> --- tests/qtest/mmio-test.c | 146 +++++++++++++++++++++++++++++++++++ MAINTAINERS | 1 + tests/qtest/Makefile.include | 1 + 3 files changed, 148 insertions(+) create mode 100644 tests/qtest/mmio-test.c diff --git a/tests/qtest/mmio-test.c b/tests/qtest/mmio-test.c new file mode 100644 index 0000000000..7a31eb8e9d --- /dev/null +++ b/tests/qtest/mmio-test.c @@ -0,0 +1,146 @@ +/* + * QTest testcases for generic MMIO accesses + * + * Copyright (C) 2020 Philippe Mathieu-Daudé <f4...@amsat.org> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "libqtest.h" +#include "qemu/bswap.h" + +/* Must fit in arch address space */ +static const uint64_t base = 0x20000000ul; + +static bool is_cross_endian(QTestState *qts) +{ + bool te = qtest_big_endian(qts); +#ifdef HOST_WORDS_BIGENDIAN + te = !te; +#endif + return te; +} + +static QTestState *create_interleaver_qtest(void) +{ + QTestState *qts; + + qts = qtest_initf("-M none -device mmio-testdev,address=0x%" PRIx64, base); + if (is_cross_endian(qts)) { + g_test_skip("Skipping on cross-endian targets"); + qtest_quit(qts); + return NULL; + } + return qts; +} + +static void test_interleaver_rd32x8a(void) +{ + QTestState *qts = create_interleaver_qtest(); + + if (!qts) { + return; + } + + /* write sram directly */ + qtest_writeb(qts, base + 0x000, 0x10); + qtest_writeb(qts, base + 0x100, 0x32); + qtest_writeb(qts, base + 0x200, 0x54); + qtest_writeb(qts, base + 0x300, 0x76); + /* read via interleaver */ + g_assert_cmphex(qtest_readl(qts, base + 0x13208000 + 0x00), ==, 0x76543210); + qtest_quit(qts); +} + +static void test_interleaver_rd32x8b(void) +{ + QTestState *qts = create_interleaver_qtest(); + + if (!qts) { + return; + } + + /* write sram directly */ + qtest_writeb(qts, base + 0x003, 0x10); + qtest_writeb(qts, base + 0x103, 0x32); + qtest_writeb(qts, base + 0x203, 0x54); + qtest_writeb(qts, base + 0x303, 0x76); + /* read via interleaver */ + g_assert_cmphex(qtest_readl(qts, base + 0x13208000 + 0x0c), ==, 0x76543210); + qtest_quit(qts); +} + +static void test_interleaver_rd32x16(void) +{ + QTestState *qts = create_interleaver_qtest(); + + if (!qts) { + return; + } + + /* write sram directly */ + qtest_writew(qts, base + 0x002, 0x3210); + qtest_writew(qts, base + 0x102, 0x7654); + /* read via interleaver */ + g_assert_cmphex(qtest_readl(qts, base + 0x13216000 + 0x04), ==, 0x76543210); + qtest_quit(qts); +} + +static void test_interleaver_wr32x16(void) +{ + QTestState *qts = create_interleaver_qtest(); + + if (!qts) { + return; + } + + /* write via interleaver */ + qtest_writel(qts, base + 0x13216000 + 0x04, 0x76543210); + /* read sram directly */ + g_assert_cmphex(qtest_readw(qts, base + 0x002), ==, 0x3210); + g_assert_cmphex(qtest_readw(qts, base + 0x102), ==, 0x7654); + qtest_quit(qts); +} + +static void test_interleaver_wr64x8(void) +{ + QTestState *qts = create_interleaver_qtest(); + + if (!qts) { + return; + } + + /* write via interleaver */ + qtest_writeq(qts, base + 0x16408000 + 0x08, 0x9876543210); + /* read sram directly */ + g_assert_cmphex(qtest_readb(qts, base + 0x001), ==, 0x10); + g_assert_cmphex(qtest_readb(qts, base + 0x101), ==, 0x32); + g_assert_cmphex(qtest_readb(qts, base + 0x401), ==, 0x98); + qtest_quit(qts); +} + +static struct { + const char *name; + void (*test)(void); +} tests[] = { + {"interleaver/rd32x8a", test_interleaver_rd32x8a}, + {"interleaver/rd32x8b", test_interleaver_rd32x8b}, + {"interleaver/rd32x16", test_interleaver_rd32x16}, + {"interleaver/wr32x16", test_interleaver_wr32x16}, + {"interleaver/wr64x8", test_interleaver_wr64x8}, +}; + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + for (size_t i = 0; i < ARRAY_SIZE(tests); i++) { + g_autofree gchar *path = g_strdup_printf("mmio/%s", + tests[i].name); + qtest_add_func(path, tests[i].test); + } + + return g_test_run(); +} diff --git a/MAINTAINERS b/MAINTAINERS index f75b8c984a..93efef1b87 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1968,6 +1968,7 @@ F: include/hw/misc/interleaver.h F: hw/misc/interleaver.c F: hw/misc/mmio-testdev.c F: include/hw/misc/testdev.h +F: tests/qtest/mmio-test.c Standard VGA M: Gerd Hoffmann <kra...@redhat.com> diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include index b0204e44f2..29dbeb5d05 100644 --- a/tests/qtest/Makefile.include +++ b/tests/qtest/Makefile.include @@ -9,6 +9,7 @@ check-qtest-generic-y += qmp-cmd-test check-qtest-generic-y += qom-test check-qtest-generic-$(CONFIG_MODULES) += modules-test check-qtest-generic-y += test-hmp +check-qtest-generic-$(CONFIG_MMIO_TESTDEV) += mmio-test check-qtest-pci-$(CONFIG_RTL8139_PCI) += rtl8139-test check-qtest-pci-$(CONFIG_VGA) += display-vga-test -- 2.26.2