xref: /openbmc/qemu/tests/qtest/libqos/virtio-gpio.c (revision 96420a30)
18fcfc823SAlex Bennée /*
28fcfc823SAlex Bennée  * virtio-gpio nodes for testing
38fcfc823SAlex Bennée  *
48fcfc823SAlex Bennée  * Copyright (c) 2022 Linaro Ltd
58fcfc823SAlex Bennée  *
68fcfc823SAlex Bennée  * SPDX-License-Identifier: GPL-2.0-or-later
78fcfc823SAlex Bennée  */
88fcfc823SAlex Bennée 
98fcfc823SAlex Bennée #include "qemu/osdep.h"
108fcfc823SAlex Bennée #include "standard-headers/linux/virtio_config.h"
118fcfc823SAlex Bennée #include "../libqtest.h"
128fcfc823SAlex Bennée #include "qemu/module.h"
138fcfc823SAlex Bennée #include "qgraph.h"
148fcfc823SAlex Bennée #include "virtio-gpio.h"
158fcfc823SAlex Bennée 
168fcfc823SAlex Bennée static QGuestAllocator *alloc;
178fcfc823SAlex Bennée 
virtio_gpio_cleanup(QVhostUserGPIO * gpio)188fcfc823SAlex Bennée static void virtio_gpio_cleanup(QVhostUserGPIO *gpio)
198fcfc823SAlex Bennée {
208fcfc823SAlex Bennée     QVirtioDevice *vdev = gpio->vdev;
218fcfc823SAlex Bennée     int i;
228fcfc823SAlex Bennée 
238fcfc823SAlex Bennée     for (i = 0; i < 2; i++) {
248fcfc823SAlex Bennée         qvirtqueue_cleanup(vdev->bus, gpio->queues[i], alloc);
258fcfc823SAlex Bennée     }
268fcfc823SAlex Bennée     g_free(gpio->queues);
278fcfc823SAlex Bennée }
288fcfc823SAlex Bennée 
298fcfc823SAlex Bennée /*
308fcfc823SAlex Bennée  * This handles the VirtIO setup from the point of view of the driver
31*96420a30SMichael Tokarev  * frontend and therefore doesn't present any vhost specific features
328fcfc823SAlex Bennée  * and in fact masks of the re-used bit.
338fcfc823SAlex Bennée  */
virtio_gpio_setup(QVhostUserGPIO * gpio)348fcfc823SAlex Bennée static void virtio_gpio_setup(QVhostUserGPIO *gpio)
358fcfc823SAlex Bennée {
368fcfc823SAlex Bennée     QVirtioDevice *vdev = gpio->vdev;
378fcfc823SAlex Bennée     uint64_t features;
388fcfc823SAlex Bennée     int i;
398fcfc823SAlex Bennée 
408fcfc823SAlex Bennée     features = qvirtio_get_features(vdev);
418fcfc823SAlex Bennée     features &= ~QVIRTIO_F_BAD_FEATURE;
428fcfc823SAlex Bennée     qvirtio_set_features(vdev, features);
438fcfc823SAlex Bennée 
448fcfc823SAlex Bennée     gpio->queues = g_new(QVirtQueue *, 2);
458fcfc823SAlex Bennée     for (i = 0; i < 2; i++) {
468fcfc823SAlex Bennée         gpio->queues[i] = qvirtqueue_setup(vdev, alloc, i);
478fcfc823SAlex Bennée     }
488fcfc823SAlex Bennée     qvirtio_set_driver_ok(vdev);
498fcfc823SAlex Bennée }
508fcfc823SAlex Bennée 
qvirtio_gpio_get_driver(QVhostUserGPIO * v_gpio,const char * interface)518fcfc823SAlex Bennée static void *qvirtio_gpio_get_driver(QVhostUserGPIO *v_gpio,
528fcfc823SAlex Bennée                                      const char *interface)
538fcfc823SAlex Bennée {
548fcfc823SAlex Bennée     if (!g_strcmp0(interface, "vhost-user-gpio")) {
558fcfc823SAlex Bennée         return v_gpio;
568fcfc823SAlex Bennée     }
578fcfc823SAlex Bennée     if (!g_strcmp0(interface, "virtio")) {
588fcfc823SAlex Bennée         return v_gpio->vdev;
598fcfc823SAlex Bennée     }
608fcfc823SAlex Bennée 
618fcfc823SAlex Bennée     g_assert_not_reached();
628fcfc823SAlex Bennée }
638fcfc823SAlex Bennée 
qvirtio_gpio_device_get_driver(void * object,const char * interface)648fcfc823SAlex Bennée static void *qvirtio_gpio_device_get_driver(void *object,
658fcfc823SAlex Bennée                                             const char *interface)
668fcfc823SAlex Bennée {
678fcfc823SAlex Bennée     QVhostUserGPIODevice *v_gpio = object;
688fcfc823SAlex Bennée     return qvirtio_gpio_get_driver(&v_gpio->gpio, interface);
698fcfc823SAlex Bennée }
708fcfc823SAlex Bennée 
718fcfc823SAlex Bennée /* virtio-gpio (mmio) */
qvirtio_gpio_device_destructor(QOSGraphObject * obj)728fcfc823SAlex Bennée static void qvirtio_gpio_device_destructor(QOSGraphObject *obj)
738fcfc823SAlex Bennée {
748fcfc823SAlex Bennée     QVhostUserGPIODevice *gpio_dev = (QVhostUserGPIODevice *) obj;
758fcfc823SAlex Bennée     virtio_gpio_cleanup(&gpio_dev->gpio);
768fcfc823SAlex Bennée }
778fcfc823SAlex Bennée 
qvirtio_gpio_device_start_hw(QOSGraphObject * obj)788fcfc823SAlex Bennée static void qvirtio_gpio_device_start_hw(QOSGraphObject *obj)
798fcfc823SAlex Bennée {
808fcfc823SAlex Bennée     QVhostUserGPIODevice *gpio_dev = (QVhostUserGPIODevice *) obj;
818fcfc823SAlex Bennée     virtio_gpio_setup(&gpio_dev->gpio);
828fcfc823SAlex Bennée }
838fcfc823SAlex Bennée 
virtio_gpio_device_create(void * virtio_dev,QGuestAllocator * t_alloc,void * addr)848fcfc823SAlex Bennée static void *virtio_gpio_device_create(void *virtio_dev,
858fcfc823SAlex Bennée                                        QGuestAllocator *t_alloc,
868fcfc823SAlex Bennée                                        void *addr)
878fcfc823SAlex Bennée {
888fcfc823SAlex Bennée     QVhostUserGPIODevice *virtio_device = g_new0(QVhostUserGPIODevice, 1);
898fcfc823SAlex Bennée     QVhostUserGPIO *interface = &virtio_device->gpio;
908fcfc823SAlex Bennée 
918fcfc823SAlex Bennée     interface->vdev = virtio_dev;
928fcfc823SAlex Bennée     alloc = t_alloc;
938fcfc823SAlex Bennée 
948fcfc823SAlex Bennée     virtio_device->obj.get_driver = qvirtio_gpio_device_get_driver;
958fcfc823SAlex Bennée     virtio_device->obj.start_hw = qvirtio_gpio_device_start_hw;
968fcfc823SAlex Bennée     virtio_device->obj.destructor = qvirtio_gpio_device_destructor;
978fcfc823SAlex Bennée 
988fcfc823SAlex Bennée     return &virtio_device->obj;
998fcfc823SAlex Bennée }
1008fcfc823SAlex Bennée 
1018fcfc823SAlex Bennée /* virtio-gpio-pci */
qvirtio_gpio_pci_destructor(QOSGraphObject * obj)1028fcfc823SAlex Bennée static void qvirtio_gpio_pci_destructor(QOSGraphObject *obj)
1038fcfc823SAlex Bennée {
1048fcfc823SAlex Bennée     QVhostUserGPIOPCI *gpio_pci = (QVhostUserGPIOPCI *) obj;
1058fcfc823SAlex Bennée     QOSGraphObject *pci_vobj =  &gpio_pci->pci_vdev.obj;
1068fcfc823SAlex Bennée 
1078fcfc823SAlex Bennée     virtio_gpio_cleanup(&gpio_pci->gpio);
1088fcfc823SAlex Bennée     qvirtio_pci_destructor(pci_vobj);
1098fcfc823SAlex Bennée }
1108fcfc823SAlex Bennée 
qvirtio_gpio_pci_start_hw(QOSGraphObject * obj)1118fcfc823SAlex Bennée static void qvirtio_gpio_pci_start_hw(QOSGraphObject *obj)
1128fcfc823SAlex Bennée {
1138fcfc823SAlex Bennée     QVhostUserGPIOPCI *gpio_pci = (QVhostUserGPIOPCI *) obj;
1148fcfc823SAlex Bennée     QOSGraphObject *pci_vobj =  &gpio_pci->pci_vdev.obj;
1158fcfc823SAlex Bennée 
1168fcfc823SAlex Bennée     qvirtio_pci_start_hw(pci_vobj);
1178fcfc823SAlex Bennée     virtio_gpio_setup(&gpio_pci->gpio);
1188fcfc823SAlex Bennée }
1198fcfc823SAlex Bennée 
qvirtio_gpio_pci_get_driver(void * object,const char * interface)1208fcfc823SAlex Bennée static void *qvirtio_gpio_pci_get_driver(void *object, const char *interface)
1218fcfc823SAlex Bennée {
1228fcfc823SAlex Bennée     QVhostUserGPIOPCI *v_gpio = object;
1238fcfc823SAlex Bennée 
1248fcfc823SAlex Bennée     if (!g_strcmp0(interface, "pci-device")) {
1258fcfc823SAlex Bennée         return v_gpio->pci_vdev.pdev;
1268fcfc823SAlex Bennée     }
1278fcfc823SAlex Bennée     return qvirtio_gpio_get_driver(&v_gpio->gpio, interface);
1288fcfc823SAlex Bennée }
1298fcfc823SAlex Bennée 
virtio_gpio_pci_create(void * pci_bus,QGuestAllocator * t_alloc,void * addr)1308fcfc823SAlex Bennée static void *virtio_gpio_pci_create(void *pci_bus, QGuestAllocator *t_alloc,
1318fcfc823SAlex Bennée                                     void *addr)
1328fcfc823SAlex Bennée {
1338fcfc823SAlex Bennée     QVhostUserGPIOPCI *virtio_spci = g_new0(QVhostUserGPIOPCI, 1);
1348fcfc823SAlex Bennée     QVhostUserGPIO *interface = &virtio_spci->gpio;
1358fcfc823SAlex Bennée     QOSGraphObject *obj = &virtio_spci->pci_vdev.obj;
1368fcfc823SAlex Bennée 
1378fcfc823SAlex Bennée     virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr);
1388fcfc823SAlex Bennée     interface->vdev = &virtio_spci->pci_vdev.vdev;
1398fcfc823SAlex Bennée     alloc = t_alloc;
1408fcfc823SAlex Bennée 
1418fcfc823SAlex Bennée     obj->get_driver = qvirtio_gpio_pci_get_driver;
1428fcfc823SAlex Bennée     obj->start_hw = qvirtio_gpio_pci_start_hw;
1438fcfc823SAlex Bennée     obj->destructor = qvirtio_gpio_pci_destructor;
1448fcfc823SAlex Bennée 
1458fcfc823SAlex Bennée     return obj;
1468fcfc823SAlex Bennée }
1478fcfc823SAlex Bennée 
virtio_gpio_register_nodes(void)1488fcfc823SAlex Bennée static void virtio_gpio_register_nodes(void)
1498fcfc823SAlex Bennée {
1508fcfc823SAlex Bennée     QPCIAddress addr = {
1518fcfc823SAlex Bennée         .devfn = QPCI_DEVFN(4, 0),
1528fcfc823SAlex Bennée     };
1538fcfc823SAlex Bennée 
1548fcfc823SAlex Bennée     QOSGraphEdgeOptions edge_opts = { };
1558fcfc823SAlex Bennée 
1568fcfc823SAlex Bennée     /* vhost-user-gpio-device */
157523e4002SAlex Bennée     edge_opts.extra_device_opts = "id=gpio0,chardev=chr-vhost-user-test "
158523e4002SAlex Bennée         "-global virtio-mmio.force-legacy=false";
1598fcfc823SAlex Bennée     qos_node_create_driver("vhost-user-gpio-device",
1608fcfc823SAlex Bennée                             virtio_gpio_device_create);
1618fcfc823SAlex Bennée     qos_node_consumes("vhost-user-gpio-device", "virtio-bus", &edge_opts);
1628fcfc823SAlex Bennée     qos_node_produces("vhost-user-gpio-device", "vhost-user-gpio");
1638fcfc823SAlex Bennée 
1648fcfc823SAlex Bennée     /* virtio-gpio-pci */
1658fcfc823SAlex Bennée     edge_opts.extra_device_opts = "id=gpio0,addr=04.0,chardev=chr-vhost-user-test";
1668fcfc823SAlex Bennée     add_qpci_address(&edge_opts, &addr);
1678fcfc823SAlex Bennée     qos_node_create_driver("vhost-user-gpio-pci", virtio_gpio_pci_create);
1688fcfc823SAlex Bennée     qos_node_consumes("vhost-user-gpio-pci", "pci-bus", &edge_opts);
1698fcfc823SAlex Bennée     qos_node_produces("vhost-user-gpio-pci", "vhost-user-gpio");
1708fcfc823SAlex Bennée }
1718fcfc823SAlex Bennée 
1728fcfc823SAlex Bennée libqos_init(virtio_gpio_register_nodes);
173