2 * libqos driver virtio-iommu-pci framework
4 * Copyright (c) 2021 Red Hat, Inc.
7 * Eric Auger <eric.auger@redhat.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
10 * option) any later version. See the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
15 #include "../libqtest.h"
16 #include "qemu/module.h"
18 #include "virtio-iommu.h"
19 #include "hw/virtio/virtio-iommu.h"
21 static QGuestAllocator
*alloc
;
23 /* virtio-iommu-device */
24 static void *qvirtio_iommu_get_driver(QVirtioIOMMU
*v_iommu
,
25 const char *interface
)
27 if (!g_strcmp0(interface
, "virtio-iommu")) {
30 if (!g_strcmp0(interface
, "virtio")) {
34 fprintf(stderr
, "%s not present in virtio-iommu-device\n", interface
);
35 g_assert_not_reached();
38 static void virtio_iommu_cleanup(QVirtioIOMMU
*interface
)
40 qvirtqueue_cleanup(interface
->vdev
->bus
, interface
->vq
, alloc
);
43 static void virtio_iommu_setup(QVirtioIOMMU
*interface
)
45 QVirtioDevice
*vdev
= interface
->vdev
;
48 features
= qvirtio_get_features(vdev
);
49 features
&= ~(QVIRTIO_F_BAD_FEATURE
|
50 (1ull << VIRTIO_RING_F_INDIRECT_DESC
) |
51 (1ull << VIRTIO_RING_F_EVENT_IDX
) |
52 (1ull << VIRTIO_IOMMU_F_BYPASS
));
53 qvirtio_set_features(vdev
, features
);
54 interface
->vq
= qvirtqueue_setup(interface
->vdev
, alloc
, 0);
55 qvirtio_set_driver_ok(interface
->vdev
);
58 /* virtio-iommu-pci */
59 static void *qvirtio_iommu_pci_get_driver(void *object
, const char *interface
)
61 QVirtioIOMMUPCI
*v_iommu
= object
;
62 if (!g_strcmp0(interface
, "pci-device")) {
63 return v_iommu
->pci_vdev
.pdev
;
65 return qvirtio_iommu_get_driver(&v_iommu
->iommu
, interface
);
68 static void qvirtio_iommu_pci_destructor(QOSGraphObject
*obj
)
70 QVirtioIOMMUPCI
*iommu_pci
= (QVirtioIOMMUPCI
*) obj
;
71 QVirtioIOMMU
*interface
= &iommu_pci
->iommu
;
72 QOSGraphObject
*pci_vobj
= &iommu_pci
->pci_vdev
.obj
;
74 virtio_iommu_cleanup(interface
);
75 qvirtio_pci_destructor(pci_vobj
);
78 static void qvirtio_iommu_pci_start_hw(QOSGraphObject
*obj
)
80 QVirtioIOMMUPCI
*iommu_pci
= (QVirtioIOMMUPCI
*) obj
;
81 QVirtioIOMMU
*interface
= &iommu_pci
->iommu
;
82 QOSGraphObject
*pci_vobj
= &iommu_pci
->pci_vdev
.obj
;
84 qvirtio_pci_start_hw(pci_vobj
);
85 virtio_iommu_setup(interface
);
89 static void *virtio_iommu_pci_create(void *pci_bus
, QGuestAllocator
*t_alloc
,
92 QVirtioIOMMUPCI
*virtio_rpci
= g_new0(QVirtioIOMMUPCI
, 1);
93 QVirtioIOMMU
*interface
= &virtio_rpci
->iommu
;
94 QOSGraphObject
*obj
= &virtio_rpci
->pci_vdev
.obj
;
96 virtio_pci_init(&virtio_rpci
->pci_vdev
, pci_bus
, addr
);
97 interface
->vdev
= &virtio_rpci
->pci_vdev
.vdev
;
100 obj
->get_driver
= qvirtio_iommu_pci_get_driver
;
101 obj
->start_hw
= qvirtio_iommu_pci_start_hw
;
102 obj
->destructor
= qvirtio_iommu_pci_destructor
;
107 static void virtio_iommu_register_nodes(void)
110 .devfn
= QPCI_DEVFN(4, 0),
113 QOSGraphEdgeOptions opts
= {
114 .extra_device_opts
= "addr=04.0",
117 /* virtio-iommu-pci */
118 add_qpci_address(&opts
, &addr
);
119 qos_node_create_driver("virtio-iommu-pci", virtio_iommu_pci_create
);
120 qos_node_consumes("virtio-iommu-pci", "pci-bus", &opts
);
121 qos_node_produces("virtio-iommu-pci", "pci-device");
122 qos_node_produces("virtio-iommu-pci", "virtio");
123 qos_node_produces("virtio-iommu-pci", "virtio-iommu");
126 libqos_init(virtio_iommu_register_nodes
);