1becf8873SEric Auger /* 2becf8873SEric Auger * libqos driver virtio-iommu-pci framework 3becf8873SEric Auger * 4becf8873SEric Auger * Copyright (c) 2021 Red Hat, Inc. 5becf8873SEric Auger * 6becf8873SEric Auger * Authors: 7becf8873SEric Auger * Eric Auger <eric.auger@redhat.com> 8becf8873SEric Auger * 9becf8873SEric Auger * This work is licensed under the terms of the GNU GPL, version 2 or (at your 10becf8873SEric Auger * option) any later version. See the COPYING file in the top-level directory. 11becf8873SEric Auger * 12becf8873SEric Auger */ 13becf8873SEric Auger 14becf8873SEric Auger #include "qemu/osdep.h" 15*907b5105SMarc-André Lureau #include "../libqtest.h" 16becf8873SEric Auger #include "qemu/module.h" 17becf8873SEric Auger #include "qgraph.h" 18becf8873SEric Auger #include "virtio-iommu.h" 19becf8873SEric Auger #include "hw/virtio/virtio-iommu.h" 20becf8873SEric Auger 21becf8873SEric Auger static QGuestAllocator *alloc; 22becf8873SEric Auger 23becf8873SEric Auger /* virtio-iommu-device */ 24becf8873SEric Auger static void *qvirtio_iommu_get_driver(QVirtioIOMMU *v_iommu, 25becf8873SEric Auger const char *interface) 26becf8873SEric Auger { 27becf8873SEric Auger if (!g_strcmp0(interface, "virtio-iommu")) { 28becf8873SEric Auger return v_iommu; 29becf8873SEric Auger } 30becf8873SEric Auger if (!g_strcmp0(interface, "virtio")) { 31becf8873SEric Auger return v_iommu->vdev; 32becf8873SEric Auger } 33becf8873SEric Auger 34becf8873SEric Auger fprintf(stderr, "%s not present in virtio-iommu-device\n", interface); 35becf8873SEric Auger g_assert_not_reached(); 36becf8873SEric Auger } 37becf8873SEric Auger 38becf8873SEric Auger static void virtio_iommu_cleanup(QVirtioIOMMU *interface) 39becf8873SEric Auger { 40becf8873SEric Auger qvirtqueue_cleanup(interface->vdev->bus, interface->vq, alloc); 41becf8873SEric Auger } 42becf8873SEric Auger 43becf8873SEric Auger static void virtio_iommu_setup(QVirtioIOMMU *interface) 44becf8873SEric Auger { 45becf8873SEric Auger QVirtioDevice *vdev = interface->vdev; 46becf8873SEric Auger uint64_t features; 47becf8873SEric Auger 48becf8873SEric Auger features = qvirtio_get_features(vdev); 49becf8873SEric Auger features &= ~(QVIRTIO_F_BAD_FEATURE | 50becf8873SEric Auger (1ull << VIRTIO_RING_F_INDIRECT_DESC) | 51becf8873SEric Auger (1ull << VIRTIO_RING_F_EVENT_IDX) | 52becf8873SEric Auger (1ull << VIRTIO_IOMMU_F_BYPASS)); 53becf8873SEric Auger qvirtio_set_features(vdev, features); 54becf8873SEric Auger interface->vq = qvirtqueue_setup(interface->vdev, alloc, 0); 55becf8873SEric Auger qvirtio_set_driver_ok(interface->vdev); 56becf8873SEric Auger } 57becf8873SEric Auger 58becf8873SEric Auger /* virtio-iommu-pci */ 59becf8873SEric Auger static void *qvirtio_iommu_pci_get_driver(void *object, const char *interface) 60becf8873SEric Auger { 61becf8873SEric Auger QVirtioIOMMUPCI *v_iommu = object; 62becf8873SEric Auger if (!g_strcmp0(interface, "pci-device")) { 63becf8873SEric Auger return v_iommu->pci_vdev.pdev; 64becf8873SEric Auger } 65becf8873SEric Auger return qvirtio_iommu_get_driver(&v_iommu->iommu, interface); 66becf8873SEric Auger } 67becf8873SEric Auger 68becf8873SEric Auger static void qvirtio_iommu_pci_destructor(QOSGraphObject *obj) 69becf8873SEric Auger { 70becf8873SEric Auger QVirtioIOMMUPCI *iommu_pci = (QVirtioIOMMUPCI *) obj; 71becf8873SEric Auger QVirtioIOMMU *interface = &iommu_pci->iommu; 72becf8873SEric Auger QOSGraphObject *pci_vobj = &iommu_pci->pci_vdev.obj; 73becf8873SEric Auger 74becf8873SEric Auger virtio_iommu_cleanup(interface); 75becf8873SEric Auger qvirtio_pci_destructor(pci_vobj); 76becf8873SEric Auger } 77becf8873SEric Auger 78becf8873SEric Auger static void qvirtio_iommu_pci_start_hw(QOSGraphObject *obj) 79becf8873SEric Auger { 80becf8873SEric Auger QVirtioIOMMUPCI *iommu_pci = (QVirtioIOMMUPCI *) obj; 81becf8873SEric Auger QVirtioIOMMU *interface = &iommu_pci->iommu; 82becf8873SEric Auger QOSGraphObject *pci_vobj = &iommu_pci->pci_vdev.obj; 83becf8873SEric Auger 84becf8873SEric Auger qvirtio_pci_start_hw(pci_vobj); 85becf8873SEric Auger virtio_iommu_setup(interface); 86becf8873SEric Auger } 87becf8873SEric Auger 88becf8873SEric Auger 89becf8873SEric Auger static void *virtio_iommu_pci_create(void *pci_bus, QGuestAllocator *t_alloc, 90becf8873SEric Auger void *addr) 91becf8873SEric Auger { 92becf8873SEric Auger QVirtioIOMMUPCI *virtio_rpci = g_new0(QVirtioIOMMUPCI, 1); 93becf8873SEric Auger QVirtioIOMMU *interface = &virtio_rpci->iommu; 94becf8873SEric Auger QOSGraphObject *obj = &virtio_rpci->pci_vdev.obj; 95becf8873SEric Auger 96becf8873SEric Auger virtio_pci_init(&virtio_rpci->pci_vdev, pci_bus, addr); 97becf8873SEric Auger interface->vdev = &virtio_rpci->pci_vdev.vdev; 98becf8873SEric Auger alloc = t_alloc; 99becf8873SEric Auger 100becf8873SEric Auger obj->get_driver = qvirtio_iommu_pci_get_driver; 101becf8873SEric Auger obj->start_hw = qvirtio_iommu_pci_start_hw; 102becf8873SEric Auger obj->destructor = qvirtio_iommu_pci_destructor; 103becf8873SEric Auger 104becf8873SEric Auger return obj; 105becf8873SEric Auger } 106becf8873SEric Auger 107becf8873SEric Auger static void virtio_iommu_register_nodes(void) 108becf8873SEric Auger { 109becf8873SEric Auger QPCIAddress addr = { 110becf8873SEric Auger .devfn = QPCI_DEVFN(4, 0), 111becf8873SEric Auger }; 112becf8873SEric Auger 113becf8873SEric Auger QOSGraphEdgeOptions opts = { 114becf8873SEric Auger .extra_device_opts = "addr=04.0", 115becf8873SEric Auger }; 116becf8873SEric Auger 117becf8873SEric Auger /* virtio-iommu-pci */ 118becf8873SEric Auger add_qpci_address(&opts, &addr); 119becf8873SEric Auger qos_node_create_driver("virtio-iommu-pci", virtio_iommu_pci_create); 120becf8873SEric Auger qos_node_consumes("virtio-iommu-pci", "pci-bus", &opts); 121becf8873SEric Auger qos_node_produces("virtio-iommu-pci", "pci-device"); 122becf8873SEric Auger qos_node_produces("virtio-iommu-pci", "virtio"); 123becf8873SEric Auger qos_node_produces("virtio-iommu-pci", "virtio-iommu"); 124becf8873SEric Auger } 125becf8873SEric Auger 126becf8873SEric Auger libqos_init(virtio_iommu_register_nodes); 127