1*b6f53ae0SMilan Zamazal /*
2*b6f53ae0SMilan Zamazal * virtio-scmi nodes for testing
3*b6f53ae0SMilan Zamazal *
4*b6f53ae0SMilan Zamazal * SPDX-FileCopyrightText: Linaro Ltd
5*b6f53ae0SMilan Zamazal * SPDX-FileCopyrightText: Red Hat, Inc.
6*b6f53ae0SMilan Zamazal * SPDX-License-Identifier: GPL-2.0-or-later
7*b6f53ae0SMilan Zamazal *
8*b6f53ae0SMilan Zamazal * Based on virtio-gpio.c, doing basically the same thing.
9*b6f53ae0SMilan Zamazal */
10*b6f53ae0SMilan Zamazal
11*b6f53ae0SMilan Zamazal #include "qemu/osdep.h"
12*b6f53ae0SMilan Zamazal #include "standard-headers/linux/virtio_config.h"
13*b6f53ae0SMilan Zamazal #include "../libqtest.h"
14*b6f53ae0SMilan Zamazal #include "qemu/module.h"
15*b6f53ae0SMilan Zamazal #include "qgraph.h"
16*b6f53ae0SMilan Zamazal #include "virtio-scmi.h"
17*b6f53ae0SMilan Zamazal
18*b6f53ae0SMilan Zamazal static QGuestAllocator *alloc;
19*b6f53ae0SMilan Zamazal
virtio_scmi_cleanup(QVhostUserSCMI * scmi)20*b6f53ae0SMilan Zamazal static void virtio_scmi_cleanup(QVhostUserSCMI *scmi)
21*b6f53ae0SMilan Zamazal {
22*b6f53ae0SMilan Zamazal QVirtioDevice *vdev = scmi->vdev;
23*b6f53ae0SMilan Zamazal int i;
24*b6f53ae0SMilan Zamazal
25*b6f53ae0SMilan Zamazal for (i = 0; i < 2; i++) {
26*b6f53ae0SMilan Zamazal qvirtqueue_cleanup(vdev->bus, scmi->queues[i], alloc);
27*b6f53ae0SMilan Zamazal }
28*b6f53ae0SMilan Zamazal g_free(scmi->queues);
29*b6f53ae0SMilan Zamazal }
30*b6f53ae0SMilan Zamazal
31*b6f53ae0SMilan Zamazal /*
32*b6f53ae0SMilan Zamazal * This handles the VirtIO setup from the point of view of the driver
33*b6f53ae0SMilan Zamazal * frontend and therefore doesn't present any vhost specific features
34*b6f53ae0SMilan Zamazal * and in fact masks of the re-used bit.
35*b6f53ae0SMilan Zamazal */
virtio_scmi_setup(QVhostUserSCMI * scmi)36*b6f53ae0SMilan Zamazal static void virtio_scmi_setup(QVhostUserSCMI *scmi)
37*b6f53ae0SMilan Zamazal {
38*b6f53ae0SMilan Zamazal QVirtioDevice *vdev = scmi->vdev;
39*b6f53ae0SMilan Zamazal uint64_t features;
40*b6f53ae0SMilan Zamazal int i;
41*b6f53ae0SMilan Zamazal
42*b6f53ae0SMilan Zamazal features = qvirtio_get_features(vdev);
43*b6f53ae0SMilan Zamazal features &= ~QVIRTIO_F_BAD_FEATURE;
44*b6f53ae0SMilan Zamazal qvirtio_set_features(vdev, features);
45*b6f53ae0SMilan Zamazal
46*b6f53ae0SMilan Zamazal scmi->queues = g_new(QVirtQueue *, 2);
47*b6f53ae0SMilan Zamazal for (i = 0; i < 2; i++) {
48*b6f53ae0SMilan Zamazal scmi->queues[i] = qvirtqueue_setup(vdev, alloc, i);
49*b6f53ae0SMilan Zamazal }
50*b6f53ae0SMilan Zamazal qvirtio_set_driver_ok(vdev);
51*b6f53ae0SMilan Zamazal }
52*b6f53ae0SMilan Zamazal
qvirtio_scmi_get_driver(QVhostUserSCMI * v_scmi,const char * interface)53*b6f53ae0SMilan Zamazal static void *qvirtio_scmi_get_driver(QVhostUserSCMI *v_scmi,
54*b6f53ae0SMilan Zamazal const char *interface)
55*b6f53ae0SMilan Zamazal {
56*b6f53ae0SMilan Zamazal if (!g_strcmp0(interface, "vhost-user-scmi")) {
57*b6f53ae0SMilan Zamazal return v_scmi;
58*b6f53ae0SMilan Zamazal }
59*b6f53ae0SMilan Zamazal if (!g_strcmp0(interface, "virtio")) {
60*b6f53ae0SMilan Zamazal return v_scmi->vdev;
61*b6f53ae0SMilan Zamazal }
62*b6f53ae0SMilan Zamazal
63*b6f53ae0SMilan Zamazal g_assert_not_reached();
64*b6f53ae0SMilan Zamazal }
65*b6f53ae0SMilan Zamazal
qvirtio_scmi_device_get_driver(void * object,const char * interface)66*b6f53ae0SMilan Zamazal static void *qvirtio_scmi_device_get_driver(void *object,
67*b6f53ae0SMilan Zamazal const char *interface)
68*b6f53ae0SMilan Zamazal {
69*b6f53ae0SMilan Zamazal QVhostUserSCMIDevice *v_scmi = object;
70*b6f53ae0SMilan Zamazal return qvirtio_scmi_get_driver(&v_scmi->scmi, interface);
71*b6f53ae0SMilan Zamazal }
72*b6f53ae0SMilan Zamazal
73*b6f53ae0SMilan Zamazal /* virtio-scmi (mmio) */
qvirtio_scmi_device_destructor(QOSGraphObject * obj)74*b6f53ae0SMilan Zamazal static void qvirtio_scmi_device_destructor(QOSGraphObject *obj)
75*b6f53ae0SMilan Zamazal {
76*b6f53ae0SMilan Zamazal QVhostUserSCMIDevice *scmi_dev = (QVhostUserSCMIDevice *) obj;
77*b6f53ae0SMilan Zamazal virtio_scmi_cleanup(&scmi_dev->scmi);
78*b6f53ae0SMilan Zamazal }
79*b6f53ae0SMilan Zamazal
qvirtio_scmi_device_start_hw(QOSGraphObject * obj)80*b6f53ae0SMilan Zamazal static void qvirtio_scmi_device_start_hw(QOSGraphObject *obj)
81*b6f53ae0SMilan Zamazal {
82*b6f53ae0SMilan Zamazal QVhostUserSCMIDevice *scmi_dev = (QVhostUserSCMIDevice *) obj;
83*b6f53ae0SMilan Zamazal virtio_scmi_setup(&scmi_dev->scmi);
84*b6f53ae0SMilan Zamazal }
85*b6f53ae0SMilan Zamazal
virtio_scmi_device_create(void * virtio_dev,QGuestAllocator * t_alloc,void * addr)86*b6f53ae0SMilan Zamazal static void *virtio_scmi_device_create(void *virtio_dev,
87*b6f53ae0SMilan Zamazal QGuestAllocator *t_alloc,
88*b6f53ae0SMilan Zamazal void *addr)
89*b6f53ae0SMilan Zamazal {
90*b6f53ae0SMilan Zamazal QVhostUserSCMIDevice *virtio_device = g_new0(QVhostUserSCMIDevice, 1);
91*b6f53ae0SMilan Zamazal QVhostUserSCMI *interface = &virtio_device->scmi;
92*b6f53ae0SMilan Zamazal
93*b6f53ae0SMilan Zamazal interface->vdev = virtio_dev;
94*b6f53ae0SMilan Zamazal alloc = t_alloc;
95*b6f53ae0SMilan Zamazal
96*b6f53ae0SMilan Zamazal virtio_device->obj.get_driver = qvirtio_scmi_device_get_driver;
97*b6f53ae0SMilan Zamazal virtio_device->obj.start_hw = qvirtio_scmi_device_start_hw;
98*b6f53ae0SMilan Zamazal virtio_device->obj.destructor = qvirtio_scmi_device_destructor;
99*b6f53ae0SMilan Zamazal
100*b6f53ae0SMilan Zamazal return &virtio_device->obj;
101*b6f53ae0SMilan Zamazal }
102*b6f53ae0SMilan Zamazal
103*b6f53ae0SMilan Zamazal /* virtio-scmi-pci */
qvirtio_scmi_pci_destructor(QOSGraphObject * obj)104*b6f53ae0SMilan Zamazal static void qvirtio_scmi_pci_destructor(QOSGraphObject *obj)
105*b6f53ae0SMilan Zamazal {
106*b6f53ae0SMilan Zamazal QVhostUserSCMIPCI *scmi_pci = (QVhostUserSCMIPCI *) obj;
107*b6f53ae0SMilan Zamazal QOSGraphObject *pci_vobj = &scmi_pci->pci_vdev.obj;
108*b6f53ae0SMilan Zamazal
109*b6f53ae0SMilan Zamazal virtio_scmi_cleanup(&scmi_pci->scmi);
110*b6f53ae0SMilan Zamazal qvirtio_pci_destructor(pci_vobj);
111*b6f53ae0SMilan Zamazal }
112*b6f53ae0SMilan Zamazal
qvirtio_scmi_pci_start_hw(QOSGraphObject * obj)113*b6f53ae0SMilan Zamazal static void qvirtio_scmi_pci_start_hw(QOSGraphObject *obj)
114*b6f53ae0SMilan Zamazal {
115*b6f53ae0SMilan Zamazal QVhostUserSCMIPCI *scmi_pci = (QVhostUserSCMIPCI *) obj;
116*b6f53ae0SMilan Zamazal QOSGraphObject *pci_vobj = &scmi_pci->pci_vdev.obj;
117*b6f53ae0SMilan Zamazal
118*b6f53ae0SMilan Zamazal qvirtio_pci_start_hw(pci_vobj);
119*b6f53ae0SMilan Zamazal virtio_scmi_setup(&scmi_pci->scmi);
120*b6f53ae0SMilan Zamazal }
121*b6f53ae0SMilan Zamazal
qvirtio_scmi_pci_get_driver(void * object,const char * interface)122*b6f53ae0SMilan Zamazal static void *qvirtio_scmi_pci_get_driver(void *object, const char *interface)
123*b6f53ae0SMilan Zamazal {
124*b6f53ae0SMilan Zamazal QVhostUserSCMIPCI *v_scmi = object;
125*b6f53ae0SMilan Zamazal
126*b6f53ae0SMilan Zamazal if (!g_strcmp0(interface, "pci-device")) {
127*b6f53ae0SMilan Zamazal return v_scmi->pci_vdev.pdev;
128*b6f53ae0SMilan Zamazal }
129*b6f53ae0SMilan Zamazal return qvirtio_scmi_get_driver(&v_scmi->scmi, interface);
130*b6f53ae0SMilan Zamazal }
131*b6f53ae0SMilan Zamazal
virtio_scmi_pci_create(void * pci_bus,QGuestAllocator * t_alloc,void * addr)132*b6f53ae0SMilan Zamazal static void *virtio_scmi_pci_create(void *pci_bus, QGuestAllocator *t_alloc,
133*b6f53ae0SMilan Zamazal void *addr)
134*b6f53ae0SMilan Zamazal {
135*b6f53ae0SMilan Zamazal QVhostUserSCMIPCI *virtio_spci = g_new0(QVhostUserSCMIPCI, 1);
136*b6f53ae0SMilan Zamazal QVhostUserSCMI *interface = &virtio_spci->scmi;
137*b6f53ae0SMilan Zamazal QOSGraphObject *obj = &virtio_spci->pci_vdev.obj;
138*b6f53ae0SMilan Zamazal
139*b6f53ae0SMilan Zamazal virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr);
140*b6f53ae0SMilan Zamazal interface->vdev = &virtio_spci->pci_vdev.vdev;
141*b6f53ae0SMilan Zamazal alloc = t_alloc;
142*b6f53ae0SMilan Zamazal
143*b6f53ae0SMilan Zamazal obj->get_driver = qvirtio_scmi_pci_get_driver;
144*b6f53ae0SMilan Zamazal obj->start_hw = qvirtio_scmi_pci_start_hw;
145*b6f53ae0SMilan Zamazal obj->destructor = qvirtio_scmi_pci_destructor;
146*b6f53ae0SMilan Zamazal
147*b6f53ae0SMilan Zamazal return obj;
148*b6f53ae0SMilan Zamazal }
149*b6f53ae0SMilan Zamazal
virtio_scmi_register_nodes(void)150*b6f53ae0SMilan Zamazal static void virtio_scmi_register_nodes(void)
151*b6f53ae0SMilan Zamazal {
152*b6f53ae0SMilan Zamazal QPCIAddress addr = {
153*b6f53ae0SMilan Zamazal .devfn = QPCI_DEVFN(4, 0),
154*b6f53ae0SMilan Zamazal };
155*b6f53ae0SMilan Zamazal
156*b6f53ae0SMilan Zamazal QOSGraphEdgeOptions edge_opts = { };
157*b6f53ae0SMilan Zamazal
158*b6f53ae0SMilan Zamazal /* vhost-user-scmi-device */
159*b6f53ae0SMilan Zamazal edge_opts.extra_device_opts = "id=scmi,chardev=chr-vhost-user-test "
160*b6f53ae0SMilan Zamazal "-global virtio-mmio.force-legacy=false";
161*b6f53ae0SMilan Zamazal qos_node_create_driver("vhost-user-scmi-device",
162*b6f53ae0SMilan Zamazal virtio_scmi_device_create);
163*b6f53ae0SMilan Zamazal qos_node_consumes("vhost-user-scmi-device", "virtio-bus", &edge_opts);
164*b6f53ae0SMilan Zamazal qos_node_produces("vhost-user-scmi-device", "vhost-user-scmi");
165*b6f53ae0SMilan Zamazal
166*b6f53ae0SMilan Zamazal /* virtio-scmi-pci */
167*b6f53ae0SMilan Zamazal edge_opts.extra_device_opts = "id=scmi,addr=04.0,chardev=chr-vhost-user-test";
168*b6f53ae0SMilan Zamazal add_qpci_address(&edge_opts, &addr);
169*b6f53ae0SMilan Zamazal qos_node_create_driver("vhost-user-scmi-pci", virtio_scmi_pci_create);
170*b6f53ae0SMilan Zamazal qos_node_consumes("vhost-user-scmi-pci", "pci-bus", &edge_opts);
171*b6f53ae0SMilan Zamazal qos_node_produces("vhost-user-scmi-pci", "vhost-user-scmi");
172*b6f53ae0SMilan Zamazal }
173*b6f53ae0SMilan Zamazal
174*b6f53ae0SMilan Zamazal libqos_init(virtio_scmi_register_nodes);
175