Run some PCI commands to call the COPY_AREA() macro in sm501_2d_operation(), and verify that there is no more overflow as reported in BZ#1786026 [*].
The SM501 is used by the R2D-PLUS and aCube Sam460ex machines, but since it is a PCI card and we already have an easy way to test PCI daughter cards on the sPAPR machine, test it there. [*] https://bugzilla.redhat.com/show_bug.cgi?id=1786026 Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org> --- tests/qtest/sm501-test.c | 106 +++++++++++++++++++++++++++++++++++ tests/qtest/Makefile.include | 2 + 2 files changed, 108 insertions(+) create mode 100644 tests/qtest/sm501-test.c diff --git a/tests/qtest/sm501-test.c b/tests/qtest/sm501-test.c new file mode 100644 index 0000000000..79bf7c2c21 --- /dev/null +++ b/tests/qtest/sm501-test.c @@ -0,0 +1,106 @@ +/* + * QEMU test for the SM501 companion + * + * SPDX-FileCopyrightText: 2020 Philippe Mathieu-Daudé <f4...@amsat.org> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu-common.h" +#include "libqtest.h" +#include "libqos/libqos-spapr.h" +#include "hw/pci/pci_ids.h" + +typedef struct { + QOSState *qs; + QPCIDevice *dev; + QPCIBar bar; +} PciSm501State; + +static void save_fn(QPCIDevice *dev, int devfn, void *data) +{ + *((QPCIDevice **)data) = dev; +} + +static void sm501_init(PciSm501State *s) +{ + uint64_t barsize; + + s->dev = NULL; + qpci_device_foreach(s->qs->pcibus, PCI_VENDOR_ID_SILICON_MOTION, + PCI_DEVICE_ID_SM501, save_fn, &s->dev); + g_assert(s->dev != NULL); + + qpci_device_enable(s->dev); + + /* BAR#0: VRAM, BAR#1: MMIO registers */ + s->bar = qpci_iomap(s->dev, 1, &barsize); + g_assert_cmpuint(barsize, ==, 2 * MiB); +} + +static void sm501_deinit(PciSm501State *s) +{ + g_free(s->dev); +} + +static uint32_t sm501_read(PciSm501State *s, uint64_t off) +{ + uint32_t val; + + s->dev->bus->memread(s->dev->bus, s->bar.addr + off, &val, sizeof(val)); + + return val; +} + +static void sm501_write(PciSm501State *s, uint64_t off, uint32_t val) +{ + s->dev->bus->memwrite(s->dev->bus, s->bar.addr + off, &val, sizeof(val)); +} + +static void sm501_check_device_id(PciSm501State *s) +{ + g_assert_cmphex(sm501_read(s, 0x60) >> 16, ==, 0x501); /* DEVICEID reg */ +} + +/* + * Try to reproduce the heap overflow reported in + * https://bugzilla.redhat.com/show_bug.cgi?id=1786026 + */ +static void test_sm501_2d_drawing_engine_op(void) +{ + PciSm501State s; + + s.qs = qtest_spapr_boot("-machine pseries -device sm501"); + + sm501_init(&s); + sm501_check_device_id(&s); + + /* + * Commands listed in BZ#1786026 to access + * COPY_AREA() in sm501_2d_operation(). + */ + sm501_write(&s, 0x100000, 0x0); /* src: (x, y) = (0, 0) */ + sm501_write(&s, 0x100004, 0x0); /* dst: (x, y) = (0, 0) */ + sm501_write(&s, 0x100008, 0x00100010); /* dim: height = width = 16 */ + sm501_write(&s, 0x100010, 0x00100010); /* pitch: height = width = 16 */ + sm501_write(&s, 0x10000c, 0xcc000088); /* ctrl: op = copy area, RTL */ + + /* If the overflow occured, the next call will fail. */ + sm501_check_device_id(&s); + + sm501_deinit(&s); + + qtest_shutdown(s.qs); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + + if (!strcmp(qtest_get_arch(), "ppc64")) { + qtest_add_func("spapr/sm501_2d_op", test_sm501_2d_drawing_engine_op); + } + + return g_test_run(); +} diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include index 9e5a51d033..7ec894a7a9 100644 --- a/tests/qtest/Makefile.include +++ b/tests/qtest/Makefile.include @@ -109,6 +109,7 @@ check-qtest-ppc64-$(CONFIG_VGA) += display-vga-test check-qtest-ppc64-y += numa-test check-qtest-ppc64-$(CONFIG_IVSHMEM_DEVICE) += ivshmem-test check-qtest-ppc64-y += cpu-plug-test +check-qtest-ppc64-$(CONFIG_SM501) += sm501-test check-qtest-sh4-$(CONFIG_ISA_TESTDEV) = endianness-test @@ -253,6 +254,7 @@ tests/qtest/pflash-cfi02$(EXESUF): tests/qtest/pflash-cfi02-test.o tests/qtest/endianness-test$(EXESUF): tests/qtest/endianness-test.o tests/qtest/prom-env-test$(EXESUF): tests/qtest/prom-env-test.o $(libqos-obj-y) tests/qtest/rtas-test$(EXESUF): tests/qtest/rtas-test.o $(libqos-spapr-obj-y) +tests/qtest/sm501-test$(EXESUF): tests/qtest/sm501-test.o $(libqos-spapr-obj-y) tests/qtest/fdc-test$(EXESUF): tests/qtest/fdc-test.o tests/qtest/ide-test$(EXESUF): tests/qtest/ide-test.o $(libqos-pc-obj-y) tests/qtest/ahci-test$(EXESUF): tests/qtest/ahci-test.o $(libqos-pc-obj-y) qemu-img$(EXESUF) -- 2.21.1