xref: /openbmc/qemu/tests/qtest/megasas-test.c (revision 2e3408b3cc7de4e87a9adafc8c19bfce3abec947)
11e8a1faeSThomas Huth /*
21e8a1faeSThomas Huth  * QTest testcase for LSI MegaRAID
31e8a1faeSThomas Huth  *
41e8a1faeSThomas Huth  * Copyright (c) 2017 Red Hat Inc.
51e8a1faeSThomas Huth  *
61e8a1faeSThomas Huth  * This work is licensed under the terms of the GNU GPL, version 2 or later.
71e8a1faeSThomas Huth  * See the COPYING file in the top-level directory.
81e8a1faeSThomas Huth  */
91e8a1faeSThomas Huth 
101e8a1faeSThomas Huth #include "qemu/osdep.h"
11*907b5105SMarc-André Lureau #include "libqtest.h"
121e8a1faeSThomas Huth #include "qemu/bswap.h"
131e8a1faeSThomas Huth #include "qemu/module.h"
141e8a1faeSThomas Huth #include "libqos/qgraph.h"
151e8a1faeSThomas Huth #include "libqos/pci.h"
161e8a1faeSThomas Huth 
171e8a1faeSThomas Huth typedef struct QMegasas QMegasas;
181e8a1faeSThomas Huth 
191e8a1faeSThomas Huth struct QMegasas {
201e8a1faeSThomas Huth     QOSGraphObject obj;
211e8a1faeSThomas Huth     QPCIDevice dev;
221e8a1faeSThomas Huth };
231e8a1faeSThomas Huth 
megasas_get_driver(void * obj,const char * interface)241e8a1faeSThomas Huth static void *megasas_get_driver(void *obj, const char *interface)
251e8a1faeSThomas Huth {
261e8a1faeSThomas Huth     QMegasas *megasas = obj;
271e8a1faeSThomas Huth 
281e8a1faeSThomas Huth     if (!g_strcmp0(interface, "pci-device")) {
291e8a1faeSThomas Huth         return &megasas->dev;
301e8a1faeSThomas Huth     }
311e8a1faeSThomas Huth 
321e8a1faeSThomas Huth     fprintf(stderr, "%s not present in megasas\n", interface);
331e8a1faeSThomas Huth     g_assert_not_reached();
341e8a1faeSThomas Huth }
351e8a1faeSThomas Huth 
megasas_create(void * pci_bus,QGuestAllocator * alloc,void * addr)361e8a1faeSThomas Huth static void *megasas_create(void *pci_bus, QGuestAllocator *alloc, void *addr)
371e8a1faeSThomas Huth {
381e8a1faeSThomas Huth     QMegasas *megasas = g_new0(QMegasas, 1);
391e8a1faeSThomas Huth     QPCIBus *bus = pci_bus;
401e8a1faeSThomas Huth 
411e8a1faeSThomas Huth     qpci_device_init(&megasas->dev, bus, addr);
421e8a1faeSThomas Huth     megasas->obj.get_driver = megasas_get_driver;
431e8a1faeSThomas Huth 
441e8a1faeSThomas Huth     return &megasas->obj;
451e8a1faeSThomas Huth }
461e8a1faeSThomas Huth 
471e8a1faeSThomas Huth /* This used to cause a NULL pointer dereference.  */
megasas_pd_get_info_fuzz(void * obj,void * data,QGuestAllocator * alloc)481e8a1faeSThomas Huth static void megasas_pd_get_info_fuzz(void *obj, void *data, QGuestAllocator *alloc)
491e8a1faeSThomas Huth {
501e8a1faeSThomas Huth     QMegasas *megasas = obj;
511e8a1faeSThomas Huth     QPCIDevice *dev = &megasas->dev;
521e8a1faeSThomas Huth     QPCIBar bar;
531e8a1faeSThomas Huth     uint32_t context[256];
541e8a1faeSThomas Huth     uint64_t context_pa;
551e8a1faeSThomas Huth     int i;
561e8a1faeSThomas Huth 
571e8a1faeSThomas Huth     qpci_device_enable(dev);
581e8a1faeSThomas Huth     bar = qpci_iomap(dev, 0, NULL);
591e8a1faeSThomas Huth 
601e8a1faeSThomas Huth     memset(context, 0, sizeof(context));
611e8a1faeSThomas Huth     context[0] = cpu_to_le32(0x05050505);
621e8a1faeSThomas Huth     context[1] = cpu_to_le32(0x01010101);
631e8a1faeSThomas Huth     for (i = 2; i < ARRAY_SIZE(context); i++) {
641e8a1faeSThomas Huth         context[i] = cpu_to_le32(0x41414141);
651e8a1faeSThomas Huth     }
661e8a1faeSThomas Huth     context[6] = cpu_to_le32(0x02020000);
671e8a1faeSThomas Huth     context[7] = cpu_to_le32(0);
681e8a1faeSThomas Huth 
691e8a1faeSThomas Huth     context_pa = guest_alloc(alloc, sizeof(context));
701e8a1faeSThomas Huth     qtest_memwrite(dev->bus->qts, context_pa, context, sizeof(context));
711e8a1faeSThomas Huth     qpci_io_writel(dev, bar, 0x40, context_pa);
721e8a1faeSThomas Huth }
731e8a1faeSThomas Huth 
megasas_register_nodes(void)741e8a1faeSThomas Huth static void megasas_register_nodes(void)
751e8a1faeSThomas Huth {
761e8a1faeSThomas Huth     QOSGraphEdgeOptions opts = {
771e8a1faeSThomas Huth         .extra_device_opts = "addr=04.0,id=scsi0",
781e8a1faeSThomas Huth         .before_cmd_line = "-drive id=drv0,if=none,file=null-co://,"
791e8a1faeSThomas Huth                            "file.read-zeroes=on,format=raw",
801e8a1faeSThomas Huth         .after_cmd_line = "-device scsi-hd,bus=scsi0.0,drive=drv0",
811e8a1faeSThomas Huth     };
821e8a1faeSThomas Huth 
831e8a1faeSThomas Huth     add_qpci_address(&opts, &(QPCIAddress) { .devfn = QPCI_DEVFN(4, 0) });
841e8a1faeSThomas Huth 
851e8a1faeSThomas Huth     qos_node_create_driver("megasas", megasas_create);
861e8a1faeSThomas Huth     qos_node_consumes("megasas", "pci-bus", &opts);
871e8a1faeSThomas Huth     qos_node_produces("megasas", "pci-device");
881e8a1faeSThomas Huth 
891e8a1faeSThomas Huth     qos_add_test("dcmd/pd-get-info/fuzz", "megasas", megasas_pd_get_info_fuzz, NULL);
901e8a1faeSThomas Huth }
911e8a1faeSThomas Huth libqos_init(megasas_register_nodes);
92