1222455efSEmanuele Giuseppe Esposito.. _qgraph: 2222455efSEmanuele Giuseppe Esposito 3222455efSEmanuele Giuseppe EspositoQtest Driver Framework 4768f14f9SPaolo Bonzini====================== 5222455efSEmanuele Giuseppe Esposito 6afdbd382SEmanuele Giuseppe EspositoIn order to test a specific driver, plain libqos tests need to 7afdbd382SEmanuele Giuseppe Espositotake care of booting QEMU with the right machine and devices. 8afdbd382SEmanuele Giuseppe EspositoThis makes each test "hardcoded" for a specific configuration, reducing 9afdbd382SEmanuele Giuseppe Espositothe possible coverage that it can reach. 10222455efSEmanuele Giuseppe Esposito 11afdbd382SEmanuele Giuseppe EspositoFor example, the sdhci device is supported on both x86_64 and ARM boards, 12afdbd382SEmanuele Giuseppe Espositotherefore a generic sdhci test should test all machines and drivers that 13afdbd382SEmanuele Giuseppe Espositosupport that device. 14afdbd382SEmanuele Giuseppe EspositoUsing only libqos APIs, the test has to manually take care of 15afdbd382SEmanuele Giuseppe Espositocovering all the setups, and build the correct command line. 16afdbd382SEmanuele Giuseppe Esposito 17*b980c1aeSStefan WeilThis also introduces backward compatibility issues: if a device/driver command 18afdbd382SEmanuele Giuseppe Espositoline name is changed, all tests that use that will not work 19afdbd382SEmanuele Giuseppe Espositoproperly anymore and need to be adjusted. 20afdbd382SEmanuele Giuseppe Esposito 21afdbd382SEmanuele Giuseppe EspositoThe aim of qgraph is to create a graph of drivers, machines and tests such that 22afdbd382SEmanuele Giuseppe Espositoa test aimed to a certain driver does not have to care of 23afdbd382SEmanuele Giuseppe Espositobooting the right QEMU machine, pick the right device, build the command line 24afdbd382SEmanuele Giuseppe Espositoand so on. Instead, it only defines what type of device it is testing 25afdbd382SEmanuele Giuseppe Esposito(interface in qgraph terms) and the framework takes care of 26afdbd382SEmanuele Giuseppe Espositocovering all supported types of devices and machine architectures. 27afdbd382SEmanuele Giuseppe Esposito 28afdbd382SEmanuele Giuseppe EspositoFollowing the above example, an interface would be ``sdhci``, 29afdbd382SEmanuele Giuseppe Espositoso the sdhci-test should only care of linking its qgraph node with 30afdbd382SEmanuele Giuseppe Espositothat interface. In this way, if the command line of a sdhci driver 31afdbd382SEmanuele Giuseppe Espositois changed, only the respective qgraph driver node has to be adjusted. 32afdbd382SEmanuele Giuseppe Esposito 33768f14f9SPaolo BonziniQGraph concepts 34768f14f9SPaolo Bonzini--------------- 35768f14f9SPaolo Bonzini 36afdbd382SEmanuele Giuseppe EspositoThe graph is composed by nodes that represent machines, drivers, tests 37afdbd382SEmanuele Giuseppe Espositoand edges that define the relationships between them (``CONSUMES``, ``PRODUCES``, and 38afdbd382SEmanuele Giuseppe Esposito``CONTAINS``). 39afdbd382SEmanuele Giuseppe Esposito 40222455efSEmanuele Giuseppe EspositoNodes 41768f14f9SPaolo Bonzini~~~~~ 42222455efSEmanuele Giuseppe Esposito 43222455efSEmanuele Giuseppe EspositoA node can be of four types: 44222455efSEmanuele Giuseppe Esposito 45cd066eeaSPhilippe Mathieu-Daudé- **QNODE_MACHINE**: for example ``arm/raspi2b`` 46222455efSEmanuele Giuseppe Esposito- **QNODE_DRIVER**: for example ``generic-sdhci`` 47222455efSEmanuele Giuseppe Esposito- **QNODE_INTERFACE**: for example ``sdhci`` (interface for all ``-sdhci`` 48222455efSEmanuele Giuseppe Esposito drivers). 49222455efSEmanuele Giuseppe Esposito An interface is not explicitly created, it will be automatically 50222455efSEmanuele Giuseppe Esposito instantiated when a node consumes or produces it. 51afdbd382SEmanuele Giuseppe Esposito An interface is simply a struct that abstracts the various drivers 52afdbd382SEmanuele Giuseppe Esposito for the same type of device, and offers an API to the nodes that 53afdbd382SEmanuele Giuseppe Esposito use it ("consume" relation in qgraph terms) that is implemented/backed up by the drivers that implement it ("produce" relation in qgraph terms). 54afdbd382SEmanuele Giuseppe Esposito- **QNODE_TEST**: for example ``sdhci-test``. A test consumes an interface 55afdbd382SEmanuele Giuseppe Esposito and tests the functions provided by it. 56222455efSEmanuele Giuseppe Esposito 57222455efSEmanuele Giuseppe EspositoNotes for the nodes: 58222455efSEmanuele Giuseppe Esposito 59222455efSEmanuele Giuseppe Esposito- QNODE_MACHINE: each machine struct must have a ``QGuestAllocator`` and 60222455efSEmanuele Giuseppe Esposito implement ``get_driver()`` to return the allocator mapped to the interface 61222455efSEmanuele Giuseppe Esposito "memory". The function can also return ``NULL`` if the allocator 62222455efSEmanuele Giuseppe Esposito is not set. 63222455efSEmanuele Giuseppe Esposito- QNODE_DRIVER: driver names must be unique, and machines and nodes 64222455efSEmanuele Giuseppe Esposito planned to be "consumed" by other nodes must match QEMU 65222455efSEmanuele Giuseppe Esposito drivers name, otherwise they won't be discovered 66222455efSEmanuele Giuseppe Esposito 67222455efSEmanuele Giuseppe EspositoEdges 68768f14f9SPaolo Bonzini~~~~~ 69222455efSEmanuele Giuseppe Esposito 701e235edaSPeter MaydellAn edge relation between two nodes (drivers or machines) ``X`` and ``Y`` can be: 71222455efSEmanuele Giuseppe Esposito 721e235edaSPeter Maydell- ``X CONSUMES Y``: ``Y`` can be plugged into ``X`` 731e235edaSPeter Maydell- ``X PRODUCES Y``: ``X`` provides the interface ``Y`` 741e235edaSPeter Maydell- ``X CONTAINS Y``: ``Y`` is part of ``X`` component 75222455efSEmanuele Giuseppe Esposito 76222455efSEmanuele Giuseppe EspositoExecution steps 77768f14f9SPaolo Bonzini~~~~~~~~~~~~~~~ 78222455efSEmanuele Giuseppe Esposito 79222455efSEmanuele Giuseppe EspositoThe basic framework steps are the following: 80222455efSEmanuele Giuseppe Esposito 81222455efSEmanuele Giuseppe Esposito- All nodes and edges are created in their respective 82222455efSEmanuele Giuseppe Esposito machine/driver/test files 83222455efSEmanuele Giuseppe Esposito- The framework starts QEMU and asks for a list of available devices 84222455efSEmanuele Giuseppe Esposito and machines (note that only machines and "consumed" nodes are mapped 85222455efSEmanuele Giuseppe Esposito 1:1 with QEMU devices) 86222455efSEmanuele Giuseppe Esposito- The framework walks the graph starting from the available machines and 87222455efSEmanuele Giuseppe Esposito performs a Depth First Search for tests 88222455efSEmanuele Giuseppe Esposito- Once a test is found, the path is walked again and all drivers are 89222455efSEmanuele Giuseppe Esposito allocated accordingly and the final interface is passed to the test 90222455efSEmanuele Giuseppe Esposito- The test is executed 91222455efSEmanuele Giuseppe Esposito- Unused objects are cleaned and the path discovery is continued 92222455efSEmanuele Giuseppe Esposito 93222455efSEmanuele Giuseppe EspositoDepending on the QEMU binary used, only some drivers/machines will be 94222455efSEmanuele Giuseppe Espositoavailable and only test that are reached by them will be executed. 95222455efSEmanuele Giuseppe Esposito 96768f14f9SPaolo BonziniCommand line 97768f14f9SPaolo Bonzini~~~~~~~~~~~~ 98768f14f9SPaolo Bonzini 99768f14f9SPaolo BonziniCommand line is built by using node names and optional arguments 100768f14f9SPaolo Bonzinipassed by the user when building the edges. 101768f14f9SPaolo Bonzini 102768f14f9SPaolo BonziniThere are three types of command line arguments: 103768f14f9SPaolo Bonzini 104768f14f9SPaolo Bonzini- ``in node`` : created from the node name. For example, machines will 105768f14f9SPaolo Bonzini have ``-M <machine>`` to its command line, while devices 106768f14f9SPaolo Bonzini ``-device <device>``. It is automatically done by the framework. 107768f14f9SPaolo Bonzini- ``after node`` : added as additional argument to the node name. 108768f14f9SPaolo Bonzini This argument is added optionally when creating edges, 109768f14f9SPaolo Bonzini by setting the parameter ``after_cmd_line`` and 110768f14f9SPaolo Bonzini ``extra_edge_opts`` in ``QOSGraphEdgeOptions``. 111768f14f9SPaolo Bonzini The framework automatically adds 112768f14f9SPaolo Bonzini a comma before ``extra_edge_opts``, 113768f14f9SPaolo Bonzini because it is going to add attributes 114768f14f9SPaolo Bonzini after the destination node pointed by 115768f14f9SPaolo Bonzini the edge containing these options, and automatically 116768f14f9SPaolo Bonzini adds a space before ``after_cmd_line``, because it 117768f14f9SPaolo Bonzini adds an additional device, not an attribute. 118768f14f9SPaolo Bonzini- ``before node`` : added as additional argument to the node name. 119768f14f9SPaolo Bonzini This argument is added optionally when creating edges, 120768f14f9SPaolo Bonzini by setting the parameter ``before_cmd_line`` in 121768f14f9SPaolo Bonzini ``QOSGraphEdgeOptions``. This attribute 122768f14f9SPaolo Bonzini is going to add attributes before the destination node 123768f14f9SPaolo Bonzini pointed by the edge containing these options. It is 124768f14f9SPaolo Bonzini helpful to commands that are not node-representable, 125768f14f9SPaolo Bonzini such as ``-fdsev`` or ``-netdev``. 126768f14f9SPaolo Bonzini 127768f14f9SPaolo BonziniWhile adding command line in edges is always used, not all nodes names are 128768f14f9SPaolo Bonziniused in every path walk: this is because the contained or produced ones 129768f14f9SPaolo Bonziniare already added by QEMU, so only nodes that "consumes" will be used to 130768f14f9SPaolo Bonzinibuild the command line. Also, nodes that will have ``{ "abstract" : true }`` 131768f14f9SPaolo Bonzinias QMP attribute will loose their command line, since they are not proper 132768f14f9SPaolo Bonzinidevices to be added in QEMU. 133768f14f9SPaolo Bonzini 134768f14f9SPaolo BonziniExample:: 135768f14f9SPaolo Bonzini 136768f14f9SPaolo Bonzini QOSGraphEdgeOptions opts = { 137768f14f9SPaolo Bonzini .before_cmd_line = "-drive id=drv0,if=none,file=null-co://," 138768f14f9SPaolo Bonzini "file.read-zeroes=on,format=raw", 139768f14f9SPaolo Bonzini .after_cmd_line = "-device scsi-hd,bus=vs0.0,drive=drv0", 140768f14f9SPaolo Bonzini 141768f14f9SPaolo Bonzini opts.extra_device_opts = "id=vs0"; 142768f14f9SPaolo Bonzini }; 143768f14f9SPaolo Bonzini 144768f14f9SPaolo Bonzini qos_node_create_driver("virtio-scsi-device", 145768f14f9SPaolo Bonzini virtio_scsi_device_create); 146768f14f9SPaolo Bonzini qos_node_consumes("virtio-scsi-device", "virtio-bus", &opts); 147768f14f9SPaolo Bonzini 148768f14f9SPaolo BonziniWill produce the following command line: 149768f14f9SPaolo Bonzini``-drive id=drv0,if=none,file=null-co://, -device virtio-scsi-device,id=vs0 -device scsi-hd,bus=vs0.0,drive=drv0`` 150768f14f9SPaolo Bonzini 151ce508a3cSStefan HajnocziTroubleshooting unavailable tests 152768f14f9SPaolo Bonzini~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 153768f14f9SPaolo Bonzini 154ce508a3cSStefan HajnocziIf there is no path from an available machine to a test then that test will be 155ce508a3cSStefan Hajnocziunavailable and won't execute. This can happen if a test or driver did not set 156ce508a3cSStefan Hajnocziup its qgraph node correctly. It can also happen if the necessary machine type 157ce508a3cSStefan Hajnoczior device is missing from the QEMU binary because it was compiled out or 158ce508a3cSStefan Hajnocziotherwise. 159ce508a3cSStefan Hajnoczi 160ce508a3cSStefan HajnocziIt is possible to troubleshoot unavailable tests by running:: 161ce508a3cSStefan Hajnoczi 162ce508a3cSStefan Hajnoczi $ QTEST_QEMU_BINARY=build/qemu-system-x86_64 build/tests/qtest/qos-test --verbose 163ce508a3cSStefan Hajnoczi # ALL QGRAPH EDGES: { 164ce508a3cSStefan Hajnoczi # src='virtio-net' 165ce508a3cSStefan Hajnoczi # |-> dest='virtio-net-tests/vhost-user/multiqueue' type=2 (node=0x559142109e30) 166ce508a3cSStefan Hajnoczi # |-> dest='virtio-net-tests/vhost-user/migrate' type=2 (node=0x559142109d00) 167ce508a3cSStefan Hajnoczi # src='virtio-net-pci' 168ce508a3cSStefan Hajnoczi # |-> dest='virtio-net' type=1 (node=0x55914210d740) 169ce508a3cSStefan Hajnoczi # src='pci-bus' 170ce508a3cSStefan Hajnoczi # |-> dest='virtio-net-pci' type=2 (node=0x55914210d880) 171ce508a3cSStefan Hajnoczi # src='pci-bus-pc' 172ce508a3cSStefan Hajnoczi # |-> dest='pci-bus' type=1 (node=0x559142103f40) 173ce508a3cSStefan Hajnoczi # src='i440FX-pcihost' 174ce508a3cSStefan Hajnoczi # |-> dest='pci-bus-pc' type=0 (node=0x55914210ac70) 175ce508a3cSStefan Hajnoczi # src='x86_64/pc' 176ce508a3cSStefan Hajnoczi # |-> dest='i440FX-pcihost' type=0 (node=0x5591421117f0) 177ce508a3cSStefan Hajnoczi # src='' 178ce508a3cSStefan Hajnoczi # |-> dest='x86_64/pc' type=0 (node=0x559142111600) 179cd066eeaSPhilippe Mathieu-Daudé # |-> dest='arm/raspi2b' type=0 (node=0x559142110740) 180ce508a3cSStefan Hajnoczi ... 181ce508a3cSStefan Hajnoczi # } 182ce508a3cSStefan Hajnoczi # ALL QGRAPH NODES: { 183ce508a3cSStefan Hajnoczi # name='virtio-net-tests/announce-self' type=3 cmd_line='(null)' [available] 184cd066eeaSPhilippe Mathieu-Daudé # name='arm/raspi2b' type=0 cmd_line='-M raspi2b ' [UNAVAILABLE] 185ce508a3cSStefan Hajnoczi ... 186ce508a3cSStefan Hajnoczi # } 187ce508a3cSStefan Hajnoczi 188ce508a3cSStefan HajnocziThe ``virtio-net-tests/announce-self`` test is listed as "available" in the 189ce508a3cSStefan Hajnoczi"ALL QGRAPH NODES" output. This means the test will execute. We can follow the 190ce508a3cSStefan Hajnocziqgraph path in the "ALL QGRAPH EDGES" output as follows: '' -> 'x86_64/pc' -> 191ce508a3cSStefan Hajnoczi'i440FX-pcihost' -> 'pci-bus-pc' -> 'pci-bus' -> 'virtio-net-pci' -> 192ce508a3cSStefan Hajnoczi'virtio-net'. The root of the qgraph is '' and the depth first search begins 193ce508a3cSStefan Hajnoczithere. 194ce508a3cSStefan Hajnoczi 195cd066eeaSPhilippe Mathieu-DaudéThe ``arm/raspi2b`` machine node is listed as "UNAVAILABLE". Although it is 196cd066eeaSPhilippe Mathieu-Daudéreachable from the root via '' -> 'arm/raspi2b' the node is unavailable because 197ce508a3cSStefan Hajnoczithe QEMU binary did not list it when queried by the framework. This is expected 198ce508a3cSStefan Hajnoczibecause we used the ``qemu-system-x86_64`` binary which does not support ARM 199ce508a3cSStefan Hajnoczimachine types. 200ce508a3cSStefan Hajnoczi 201ce508a3cSStefan HajnocziIf a test is unexpectedly listed as "UNAVAILABLE", first check that the "ALL 202ce508a3cSStefan HajnocziQGRAPH EDGES" output reports edge connectivity from the root ('') to the test. 203ce508a3cSStefan HajnocziIf there is no connectivity then the qgraph nodes were not set up correctly and 204ce508a3cSStefan Hajnoczithe driver or test code is incorrect. If there is connectivity, check the 205ce508a3cSStefan Hajnocziavailability of each node in the path in the "ALL QGRAPH NODES" output. The 206ce508a3cSStefan Hajnoczifirst unavailable node in the path is the reason why the test is unavailable. 207ce508a3cSStefan HajnocziTypically this is because the QEMU binary lacks support for the necessary 208ce508a3cSStefan Hajnoczimachine type or device. 209ce508a3cSStefan Hajnoczi 210222455efSEmanuele Giuseppe EspositoCreating a new driver and its interface 211768f14f9SPaolo Bonzini--------------------------------------- 212222455efSEmanuele Giuseppe Esposito 213afdbd382SEmanuele Giuseppe EspositoHere we continue the ``sdhci`` use case, with the following scenario: 214afdbd382SEmanuele Giuseppe Esposito 215afdbd382SEmanuele Giuseppe Esposito- ``sdhci-test`` aims to test the ``read[q,w], writeq`` functions 216afdbd382SEmanuele Giuseppe Esposito offered by the ``sdhci`` drivers. 217afdbd382SEmanuele Giuseppe Esposito- The current ``sdhci`` device is supported by both ``x86_64/pc`` and ``ARM`` 218cd066eeaSPhilippe Mathieu-Daudé (in this example we focus on the ``arm-raspi2b``) machines. 219afdbd382SEmanuele Giuseppe Esposito- QEMU offers 2 types of drivers: ``QSDHCI_MemoryMapped`` for ``ARM`` and 220afdbd382SEmanuele Giuseppe Esposito ``QSDHCI_PCI`` for ``x86_64/pc``. Both implement the 221afdbd382SEmanuele Giuseppe Esposito ``read[q,w], writeq`` functions. 222afdbd382SEmanuele Giuseppe Esposito 223afdbd382SEmanuele Giuseppe EspositoIn order to implement such scenario in qgraph, the test developer needs to: 224afdbd382SEmanuele Giuseppe Esposito 225afdbd382SEmanuele Giuseppe Esposito- Create the ``x86_64/pc`` machine node. This machine uses the 226afdbd382SEmanuele Giuseppe Esposito ``pci-bus`` architecture so it ``contains`` a PCI driver, 227afdbd382SEmanuele Giuseppe Esposito ``pci-bus-pc``. The actual path is 228afdbd382SEmanuele Giuseppe Esposito 229afdbd382SEmanuele Giuseppe Esposito ``x86_64/pc --contains--> 1440FX-pcihost --contains--> 230afdbd382SEmanuele Giuseppe Esposito pci-bus-pc --produces--> pci-bus``. 231afdbd382SEmanuele Giuseppe Esposito 232afdbd382SEmanuele Giuseppe Esposito For the sake of this example, 233afdbd382SEmanuele Giuseppe Esposito we do not focus on the PCI interface implementation. 234afdbd382SEmanuele Giuseppe Esposito- Create the ``sdhci-pci`` driver node, representing ``QSDHCI_PCI``. 235afdbd382SEmanuele Giuseppe Esposito The driver uses the PCI bus (and its API), 236afdbd382SEmanuele Giuseppe Esposito so it must ``consume`` the ``pci-bus`` generic interface (which abstracts 237afdbd382SEmanuele Giuseppe Esposito all the pci drivers available) 238afdbd382SEmanuele Giuseppe Esposito 239afdbd382SEmanuele Giuseppe Esposito ``sdhci-pci --consumes--> pci-bus`` 240cd066eeaSPhilippe Mathieu-Daudé- Create an ``arm/raspi2b`` machine node. This machine ``contains`` 241afdbd382SEmanuele Giuseppe Esposito a ``generic-sdhci`` memory mapped ``sdhci`` driver node, representing 242afdbd382SEmanuele Giuseppe Esposito ``QSDHCI_MemoryMapped``. 243afdbd382SEmanuele Giuseppe Esposito 244cd066eeaSPhilippe Mathieu-Daudé ``arm/raspi2b --contains--> generic-sdhci`` 245afdbd382SEmanuele Giuseppe Esposito- Create the ``sdhci`` interface node. This interface offers the 246afdbd382SEmanuele Giuseppe Esposito functions that are shared by all ``sdhci`` devices. 247afdbd382SEmanuele Giuseppe Esposito The interface is produced by ``sdhci-pci`` and ``generic-sdhci``, 248afdbd382SEmanuele Giuseppe Esposito the available architecture-specific drivers. 249afdbd382SEmanuele Giuseppe Esposito 250afdbd382SEmanuele Giuseppe Esposito ``sdhci-pci --produces--> sdhci`` 251afdbd382SEmanuele Giuseppe Esposito 252afdbd382SEmanuele Giuseppe Esposito ``generic-sdhci --produces--> sdhci`` 253afdbd382SEmanuele Giuseppe Esposito- Create the ``sdhci-test`` test node. The test ``consumes`` the 254afdbd382SEmanuele Giuseppe Esposito ``sdhci`` interface, using its API. It doesn't need to look at 255afdbd382SEmanuele Giuseppe Esposito the supported machines or drivers. 256afdbd382SEmanuele Giuseppe Esposito 257afdbd382SEmanuele Giuseppe Esposito ``sdhci-test --consumes--> sdhci`` 258afdbd382SEmanuele Giuseppe Esposito 259cd066eeaSPhilippe Mathieu-Daudé``arm-raspi2b`` machine, simplified from 260afdbd382SEmanuele Giuseppe Esposito``tests/qtest/libqos/arm-raspi2-machine.c``:: 261222455efSEmanuele Giuseppe Esposito 262222455efSEmanuele Giuseppe Esposito #include "qgraph.h" 263222455efSEmanuele Giuseppe Esposito 264afdbd382SEmanuele Giuseppe Esposito struct QRaspi2Machine { 265222455efSEmanuele Giuseppe Esposito QOSGraphObject obj; 266afdbd382SEmanuele Giuseppe Esposito QGuestAllocator alloc; 267afdbd382SEmanuele Giuseppe Esposito QSDHCI_MemoryMapped sdhci; 268afdbd382SEmanuele Giuseppe Esposito }; 269222455efSEmanuele Giuseppe Esposito 270afdbd382SEmanuele Giuseppe Esposito static void *raspi2_get_driver(void *object, const char *interface) 271222455efSEmanuele Giuseppe Esposito { 272afdbd382SEmanuele Giuseppe Esposito QRaspi2Machine *machine = object; 273afdbd382SEmanuele Giuseppe Esposito if (!g_strcmp0(interface, "memory")) { 274afdbd382SEmanuele Giuseppe Esposito return &machine->alloc; 275222455efSEmanuele Giuseppe Esposito } 276222455efSEmanuele Giuseppe Esposito 277cd066eeaSPhilippe Mathieu-Daudé fprintf(stderr, "%s not present in arm/raspi2b\n", interface); 278afdbd382SEmanuele Giuseppe Esposito g_assert_not_reached(); 279222455efSEmanuele Giuseppe Esposito } 280222455efSEmanuele Giuseppe Esposito 281afdbd382SEmanuele Giuseppe Esposito static QOSGraphObject *raspi2_get_device(void *obj, 282afdbd382SEmanuele Giuseppe Esposito const char *device) 283222455efSEmanuele Giuseppe Esposito { 284afdbd382SEmanuele Giuseppe Esposito QRaspi2Machine *machine = obj; 285afdbd382SEmanuele Giuseppe Esposito if (!g_strcmp0(device, "generic-sdhci")) { 286afdbd382SEmanuele Giuseppe Esposito return &machine->sdhci.obj; 287222455efSEmanuele Giuseppe Esposito } 288222455efSEmanuele Giuseppe Esposito 289cd066eeaSPhilippe Mathieu-Daudé fprintf(stderr, "%s not present in arm/raspi2b\n", device); 290afdbd382SEmanuele Giuseppe Esposito g_assert_not_reached(); 291afdbd382SEmanuele Giuseppe Esposito } 292afdbd382SEmanuele Giuseppe Esposito 293afdbd382SEmanuele Giuseppe Esposito static void *qos_create_machine_arm_raspi2(QTestState *qts) 294222455efSEmanuele Giuseppe Esposito { 295afdbd382SEmanuele Giuseppe Esposito QRaspi2Machine *machine = g_new0(QRaspi2Machine, 1); 296222455efSEmanuele Giuseppe Esposito 297afdbd382SEmanuele Giuseppe Esposito alloc_init(&machine->alloc, ...); 298222455efSEmanuele Giuseppe Esposito 299afdbd382SEmanuele Giuseppe Esposito /* Get node(s) contained inside (CONTAINS) */ 300afdbd382SEmanuele Giuseppe Esposito machine->obj.get_device = raspi2_get_device; 301afdbd382SEmanuele Giuseppe Esposito 302afdbd382SEmanuele Giuseppe Esposito /* Get node(s) produced (PRODUCES) */ 303afdbd382SEmanuele Giuseppe Esposito machine->obj.get_driver = raspi2_get_driver; 304afdbd382SEmanuele Giuseppe Esposito 305afdbd382SEmanuele Giuseppe Esposito /* free the object */ 306afdbd382SEmanuele Giuseppe Esposito machine->obj.destructor = raspi2_destructor; 307afdbd382SEmanuele Giuseppe Esposito qos_init_sdhci_mm(&machine->sdhci, ...); 308afdbd382SEmanuele Giuseppe Esposito return &machine->obj; 309222455efSEmanuele Giuseppe Esposito } 310222455efSEmanuele Giuseppe Esposito 311afdbd382SEmanuele Giuseppe Esposito static void raspi2_register_nodes(void) 312afdbd382SEmanuele Giuseppe Esposito { 313cd066eeaSPhilippe Mathieu-Daudé /* arm/raspi2b --contains--> generic-sdhci */ 314cd066eeaSPhilippe Mathieu-Daudé qos_node_create_machine("arm/raspi2b", 315afdbd382SEmanuele Giuseppe Esposito qos_create_machine_arm_raspi2); 316cd066eeaSPhilippe Mathieu-Daudé qos_node_contains("arm/raspi2b", "generic-sdhci", NULL); 317afdbd382SEmanuele Giuseppe Esposito } 318222455efSEmanuele Giuseppe Esposito 319afdbd382SEmanuele Giuseppe Esposito libqos_init(raspi2_register_nodes); 320afdbd382SEmanuele Giuseppe Esposito 321afdbd382SEmanuele Giuseppe Esposito``x86_64/pc`` machine, simplified from 322afdbd382SEmanuele Giuseppe Esposito``tests/qtest/libqos/x86_64_pc-machine.c``:: 323afdbd382SEmanuele Giuseppe Esposito 324afdbd382SEmanuele Giuseppe Esposito #include "qgraph.h" 325afdbd382SEmanuele Giuseppe Esposito 326afdbd382SEmanuele Giuseppe Esposito struct i440FX_pcihost { 327afdbd382SEmanuele Giuseppe Esposito QOSGraphObject obj; 328afdbd382SEmanuele Giuseppe Esposito QPCIBusPC pci; 329afdbd382SEmanuele Giuseppe Esposito }; 330afdbd382SEmanuele Giuseppe Esposito 331afdbd382SEmanuele Giuseppe Esposito struct QX86PCMachine { 332afdbd382SEmanuele Giuseppe Esposito QOSGraphObject obj; 333afdbd382SEmanuele Giuseppe Esposito QGuestAllocator alloc; 334afdbd382SEmanuele Giuseppe Esposito i440FX_pcihost bridge; 335afdbd382SEmanuele Giuseppe Esposito }; 336afdbd382SEmanuele Giuseppe Esposito 337afdbd382SEmanuele Giuseppe Esposito /* i440FX_pcihost */ 338afdbd382SEmanuele Giuseppe Esposito 339afdbd382SEmanuele Giuseppe Esposito static QOSGraphObject *i440FX_host_get_device(void *obj, 340afdbd382SEmanuele Giuseppe Esposito const char *device) 341afdbd382SEmanuele Giuseppe Esposito { 342afdbd382SEmanuele Giuseppe Esposito i440FX_pcihost *host = obj; 343afdbd382SEmanuele Giuseppe Esposito if (!g_strcmp0(device, "pci-bus-pc")) { 344afdbd382SEmanuele Giuseppe Esposito return &host->pci.obj; 345afdbd382SEmanuele Giuseppe Esposito } 346afdbd382SEmanuele Giuseppe Esposito fprintf(stderr, "%s not present in i440FX-pcihost\n", device); 347afdbd382SEmanuele Giuseppe Esposito g_assert_not_reached(); 348afdbd382SEmanuele Giuseppe Esposito } 349afdbd382SEmanuele Giuseppe Esposito 350afdbd382SEmanuele Giuseppe Esposito /* x86_64/pc machine */ 351afdbd382SEmanuele Giuseppe Esposito 352afdbd382SEmanuele Giuseppe Esposito static void *pc_get_driver(void *object, const char *interface) 353afdbd382SEmanuele Giuseppe Esposito { 354afdbd382SEmanuele Giuseppe Esposito QX86PCMachine *machine = object; 355afdbd382SEmanuele Giuseppe Esposito if (!g_strcmp0(interface, "memory")) { 356afdbd382SEmanuele Giuseppe Esposito return &machine->alloc; 357afdbd382SEmanuele Giuseppe Esposito } 358afdbd382SEmanuele Giuseppe Esposito 359afdbd382SEmanuele Giuseppe Esposito fprintf(stderr, "%s not present in x86_64/pc\n", interface); 360afdbd382SEmanuele Giuseppe Esposito g_assert_not_reached(); 361afdbd382SEmanuele Giuseppe Esposito } 362afdbd382SEmanuele Giuseppe Esposito 363afdbd382SEmanuele Giuseppe Esposito static QOSGraphObject *pc_get_device(void *obj, const char *device) 364afdbd382SEmanuele Giuseppe Esposito { 365afdbd382SEmanuele Giuseppe Esposito QX86PCMachine *machine = obj; 366afdbd382SEmanuele Giuseppe Esposito if (!g_strcmp0(device, "i440FX-pcihost")) { 367afdbd382SEmanuele Giuseppe Esposito return &machine->bridge.obj; 368afdbd382SEmanuele Giuseppe Esposito } 369afdbd382SEmanuele Giuseppe Esposito 370afdbd382SEmanuele Giuseppe Esposito fprintf(stderr, "%s not present in x86_64/pc\n", device); 371afdbd382SEmanuele Giuseppe Esposito g_assert_not_reached(); 372afdbd382SEmanuele Giuseppe Esposito } 373afdbd382SEmanuele Giuseppe Esposito 374afdbd382SEmanuele Giuseppe Esposito static void *qos_create_machine_pc(QTestState *qts) 375afdbd382SEmanuele Giuseppe Esposito { 376afdbd382SEmanuele Giuseppe Esposito QX86PCMachine *machine = g_new0(QX86PCMachine, 1); 377afdbd382SEmanuele Giuseppe Esposito 378afdbd382SEmanuele Giuseppe Esposito /* Get node(s) contained inside (CONTAINS) */ 379afdbd382SEmanuele Giuseppe Esposito machine->obj.get_device = pc_get_device; 380afdbd382SEmanuele Giuseppe Esposito 381afdbd382SEmanuele Giuseppe Esposito /* Get node(s) produced (PRODUCES) */ 382afdbd382SEmanuele Giuseppe Esposito machine->obj.get_driver = pc_get_driver; 383afdbd382SEmanuele Giuseppe Esposito 384afdbd382SEmanuele Giuseppe Esposito /* free the object */ 385afdbd382SEmanuele Giuseppe Esposito machine->obj.destructor = pc_destructor; 386afdbd382SEmanuele Giuseppe Esposito pc_alloc_init(&machine->alloc, qts, ALLOC_NO_FLAGS); 387afdbd382SEmanuele Giuseppe Esposito 388afdbd382SEmanuele Giuseppe Esposito /* Get node(s) contained inside (CONTAINS) */ 389afdbd382SEmanuele Giuseppe Esposito machine->bridge.obj.get_device = i440FX_host_get_device; 390afdbd382SEmanuele Giuseppe Esposito 391afdbd382SEmanuele Giuseppe Esposito return &machine->obj; 392afdbd382SEmanuele Giuseppe Esposito } 393afdbd382SEmanuele Giuseppe Esposito 394afdbd382SEmanuele Giuseppe Esposito static void pc_machine_register_nodes(void) 395afdbd382SEmanuele Giuseppe Esposito { 396afdbd382SEmanuele Giuseppe Esposito /* x86_64/pc --contains--> 1440FX-pcihost --contains--> 397afdbd382SEmanuele Giuseppe Esposito * pci-bus-pc [--produces--> pci-bus (in pci.h)] */ 398afdbd382SEmanuele Giuseppe Esposito qos_node_create_machine("x86_64/pc", qos_create_machine_pc); 399afdbd382SEmanuele Giuseppe Esposito qos_node_contains("x86_64/pc", "i440FX-pcihost", NULL); 400afdbd382SEmanuele Giuseppe Esposito 401afdbd382SEmanuele Giuseppe Esposito /* contained drivers don't need a constructor, 402afdbd382SEmanuele Giuseppe Esposito * they will be init by the parent */ 403afdbd382SEmanuele Giuseppe Esposito qos_node_create_driver("i440FX-pcihost", NULL); 404afdbd382SEmanuele Giuseppe Esposito qos_node_contains("i440FX-pcihost", "pci-bus-pc", NULL); 405afdbd382SEmanuele Giuseppe Esposito } 406afdbd382SEmanuele Giuseppe Esposito 407afdbd382SEmanuele Giuseppe Esposito libqos_init(pc_machine_register_nodes); 408afdbd382SEmanuele Giuseppe Esposito 409afdbd382SEmanuele Giuseppe Esposito``sdhci`` taken from ``tests/qtest/libqos/sdhci.c``:: 410afdbd382SEmanuele Giuseppe Esposito 411afdbd382SEmanuele Giuseppe Esposito /* Interface node, offers the sdhci API */ 412afdbd382SEmanuele Giuseppe Esposito struct QSDHCI { 413afdbd382SEmanuele Giuseppe Esposito uint16_t (*readw)(QSDHCI *s, uint32_t reg); 414afdbd382SEmanuele Giuseppe Esposito uint64_t (*readq)(QSDHCI *s, uint32_t reg); 415afdbd382SEmanuele Giuseppe Esposito void (*writeq)(QSDHCI *s, uint32_t reg, uint64_t val); 416afdbd382SEmanuele Giuseppe Esposito /* other fields */ 417afdbd382SEmanuele Giuseppe Esposito }; 418afdbd382SEmanuele Giuseppe Esposito 419afdbd382SEmanuele Giuseppe Esposito /* Memory Mapped implementation of QSDHCI */ 420afdbd382SEmanuele Giuseppe Esposito struct QSDHCI_MemoryMapped { 421afdbd382SEmanuele Giuseppe Esposito QOSGraphObject obj; 422afdbd382SEmanuele Giuseppe Esposito QSDHCI sdhci; 423afdbd382SEmanuele Giuseppe Esposito /* other driver-specific fields */ 424afdbd382SEmanuele Giuseppe Esposito }; 425afdbd382SEmanuele Giuseppe Esposito 426afdbd382SEmanuele Giuseppe Esposito /* PCI implementation of QSDHCI */ 427afdbd382SEmanuele Giuseppe Esposito struct QSDHCI_PCI { 428afdbd382SEmanuele Giuseppe Esposito QOSGraphObject obj; 429afdbd382SEmanuele Giuseppe Esposito QSDHCI sdhci; 430afdbd382SEmanuele Giuseppe Esposito /* other driver-specific fields */ 431afdbd382SEmanuele Giuseppe Esposito }; 432afdbd382SEmanuele Giuseppe Esposito 433afdbd382SEmanuele Giuseppe Esposito /* Memory mapped implementation of QSDHCI */ 434afdbd382SEmanuele Giuseppe Esposito 435afdbd382SEmanuele Giuseppe Esposito static void *sdhci_mm_get_driver(void *obj, const char *interface) 436afdbd382SEmanuele Giuseppe Esposito { 437afdbd382SEmanuele Giuseppe Esposito QSDHCI_MemoryMapped *smm = obj; 438afdbd382SEmanuele Giuseppe Esposito if (!g_strcmp0(interface, "sdhci")) { 439afdbd382SEmanuele Giuseppe Esposito return &smm->sdhci; 440afdbd382SEmanuele Giuseppe Esposito } 441afdbd382SEmanuele Giuseppe Esposito fprintf(stderr, "%s not present in generic-sdhci\n", interface); 442afdbd382SEmanuele Giuseppe Esposito g_assert_not_reached(); 443afdbd382SEmanuele Giuseppe Esposito } 444afdbd382SEmanuele Giuseppe Esposito 445afdbd382SEmanuele Giuseppe Esposito void qos_init_sdhci_mm(QSDHCI_MemoryMapped *sdhci, QTestState *qts, 446afdbd382SEmanuele Giuseppe Esposito uint32_t addr, QSDHCIProperties *common) 447afdbd382SEmanuele Giuseppe Esposito { 448afdbd382SEmanuele Giuseppe Esposito /* Get node contained inside (CONTAINS) */ 449afdbd382SEmanuele Giuseppe Esposito sdhci->obj.get_driver = sdhci_mm_get_driver; 450afdbd382SEmanuele Giuseppe Esposito 451afdbd382SEmanuele Giuseppe Esposito /* SDHCI interface API */ 452afdbd382SEmanuele Giuseppe Esposito sdhci->sdhci.readw = sdhci_mm_readw; 453afdbd382SEmanuele Giuseppe Esposito sdhci->sdhci.readq = sdhci_mm_readq; 454afdbd382SEmanuele Giuseppe Esposito sdhci->sdhci.writeq = sdhci_mm_writeq; 455afdbd382SEmanuele Giuseppe Esposito sdhci->qts = qts; 456afdbd382SEmanuele Giuseppe Esposito } 457afdbd382SEmanuele Giuseppe Esposito 458afdbd382SEmanuele Giuseppe Esposito /* PCI implementation of QSDHCI */ 459afdbd382SEmanuele Giuseppe Esposito 460afdbd382SEmanuele Giuseppe Esposito static void *sdhci_pci_get_driver(void *object, 461afdbd382SEmanuele Giuseppe Esposito const char *interface) 462afdbd382SEmanuele Giuseppe Esposito { 463afdbd382SEmanuele Giuseppe Esposito QSDHCI_PCI *spci = object; 464afdbd382SEmanuele Giuseppe Esposito if (!g_strcmp0(interface, "sdhci")) { 465afdbd382SEmanuele Giuseppe Esposito return &spci->sdhci; 466afdbd382SEmanuele Giuseppe Esposito } 467afdbd382SEmanuele Giuseppe Esposito 468afdbd382SEmanuele Giuseppe Esposito fprintf(stderr, "%s not present in sdhci-pci\n", interface); 469afdbd382SEmanuele Giuseppe Esposito g_assert_not_reached(); 470afdbd382SEmanuele Giuseppe Esposito } 471afdbd382SEmanuele Giuseppe Esposito 472afdbd382SEmanuele Giuseppe Esposito static void *sdhci_pci_create(void *pci_bus, 473afdbd382SEmanuele Giuseppe Esposito QGuestAllocator *alloc, 474afdbd382SEmanuele Giuseppe Esposito void *addr) 475afdbd382SEmanuele Giuseppe Esposito { 476afdbd382SEmanuele Giuseppe Esposito QSDHCI_PCI *spci = g_new0(QSDHCI_PCI, 1); 477afdbd382SEmanuele Giuseppe Esposito QPCIBus *bus = pci_bus; 478afdbd382SEmanuele Giuseppe Esposito uint64_t barsize; 479afdbd382SEmanuele Giuseppe Esposito 480afdbd382SEmanuele Giuseppe Esposito qpci_device_init(&spci->dev, bus, addr); 481afdbd382SEmanuele Giuseppe Esposito 482afdbd382SEmanuele Giuseppe Esposito /* SDHCI interface API */ 483afdbd382SEmanuele Giuseppe Esposito spci->sdhci.readw = sdhci_pci_readw; 484afdbd382SEmanuele Giuseppe Esposito spci->sdhci.readq = sdhci_pci_readq; 485afdbd382SEmanuele Giuseppe Esposito spci->sdhci.writeq = sdhci_pci_writeq; 486afdbd382SEmanuele Giuseppe Esposito 487afdbd382SEmanuele Giuseppe Esposito /* Get node(s) produced (PRODUCES) */ 488afdbd382SEmanuele Giuseppe Esposito spci->obj.get_driver = sdhci_pci_get_driver; 489afdbd382SEmanuele Giuseppe Esposito 490afdbd382SEmanuele Giuseppe Esposito spci->obj.start_hw = sdhci_pci_start_hw; 491afdbd382SEmanuele Giuseppe Esposito spci->obj.destructor = sdhci_destructor; 492afdbd382SEmanuele Giuseppe Esposito return &spci->obj; 493afdbd382SEmanuele Giuseppe Esposito } 494afdbd382SEmanuele Giuseppe Esposito 495afdbd382SEmanuele Giuseppe Esposito static void qsdhci_register_nodes(void) 496afdbd382SEmanuele Giuseppe Esposito { 497afdbd382SEmanuele Giuseppe Esposito QOSGraphEdgeOptions opts = { 498afdbd382SEmanuele Giuseppe Esposito .extra_device_opts = "addr=04.0", 499afdbd382SEmanuele Giuseppe Esposito }; 500afdbd382SEmanuele Giuseppe Esposito 501afdbd382SEmanuele Giuseppe Esposito /* generic-sdhci */ 502afdbd382SEmanuele Giuseppe Esposito /* generic-sdhci --produces--> sdhci */ 503afdbd382SEmanuele Giuseppe Esposito qos_node_create_driver("generic-sdhci", NULL); 504afdbd382SEmanuele Giuseppe Esposito qos_node_produces("generic-sdhci", "sdhci"); 505afdbd382SEmanuele Giuseppe Esposito 506afdbd382SEmanuele Giuseppe Esposito /* sdhci-pci */ 507afdbd382SEmanuele Giuseppe Esposito /* sdhci-pci --produces--> sdhci 508afdbd382SEmanuele Giuseppe Esposito * sdhci-pci --consumes--> pci-bus */ 509afdbd382SEmanuele Giuseppe Esposito qos_node_create_driver("sdhci-pci", sdhci_pci_create); 510afdbd382SEmanuele Giuseppe Esposito qos_node_produces("sdhci-pci", "sdhci"); 511afdbd382SEmanuele Giuseppe Esposito qos_node_consumes("sdhci-pci", "pci-bus", &opts); 512afdbd382SEmanuele Giuseppe Esposito } 513afdbd382SEmanuele Giuseppe Esposito 514afdbd382SEmanuele Giuseppe Esposito libqos_init(qsdhci_register_nodes); 515afdbd382SEmanuele Giuseppe Esposito 516afdbd382SEmanuele Giuseppe EspositoIn the above example, all possible types of relations are created:: 517afdbd382SEmanuele Giuseppe Esposito 518afdbd382SEmanuele Giuseppe Esposito x86_64/pc --contains--> 1440FX-pcihost --contains--> pci-bus-pc 519222455efSEmanuele Giuseppe Esposito | 520afdbd382SEmanuele Giuseppe Esposito sdhci-pci --consumes--> pci-bus <--produces--+ 521222455efSEmanuele Giuseppe Esposito | 522afdbd382SEmanuele Giuseppe Esposito +--produces--+ 523afdbd382SEmanuele Giuseppe Esposito | 524afdbd382SEmanuele Giuseppe Esposito v 525afdbd382SEmanuele Giuseppe Esposito sdhci 526afdbd382SEmanuele Giuseppe Esposito ^ 527afdbd382SEmanuele Giuseppe Esposito | 528afdbd382SEmanuele Giuseppe Esposito +--produces-- + 529afdbd382SEmanuele Giuseppe Esposito | 530cd066eeaSPhilippe Mathieu-Daudé arm/raspi2b --contains--> generic-sdhci 531222455efSEmanuele Giuseppe Esposito 532222455efSEmanuele Giuseppe Espositoor inverting the consumes edge in consumed_by:: 533222455efSEmanuele Giuseppe Esposito 534afdbd382SEmanuele Giuseppe Esposito x86_64/pc --contains--> 1440FX-pcihost --contains--> pci-bus-pc 535222455efSEmanuele Giuseppe Esposito | 536afdbd382SEmanuele Giuseppe Esposito sdhci-pci <--consumed by-- pci-bus <--produces--+ 537222455efSEmanuele Giuseppe Esposito | 538afdbd382SEmanuele Giuseppe Esposito +--produces--+ 539afdbd382SEmanuele Giuseppe Esposito | 540afdbd382SEmanuele Giuseppe Esposito v 541afdbd382SEmanuele Giuseppe Esposito sdhci 542afdbd382SEmanuele Giuseppe Esposito ^ 543afdbd382SEmanuele Giuseppe Esposito | 544afdbd382SEmanuele Giuseppe Esposito +--produces-- + 545afdbd382SEmanuele Giuseppe Esposito | 546cd066eeaSPhilippe Mathieu-Daudé arm/raspi2b --contains--> generic-sdhci 547222455efSEmanuele Giuseppe Esposito 548afdbd382SEmanuele Giuseppe EspositoAdding a new test 549768f14f9SPaolo Bonzini----------------- 550222455efSEmanuele Giuseppe Esposito 551afdbd382SEmanuele Giuseppe EspositoGiven the above setup, adding a new test is very simple. 552afdbd382SEmanuele Giuseppe Esposito``sdhci-test``, taken from ``tests/qtest/sdhci-test.c``:: 553222455efSEmanuele Giuseppe Esposito 554afdbd382SEmanuele Giuseppe Esposito static void check_capab_sdma(QSDHCI *s, bool supported) 555222455efSEmanuele Giuseppe Esposito { 556afdbd382SEmanuele Giuseppe Esposito uint64_t capab, capab_sdma; 557afdbd382SEmanuele Giuseppe Esposito 558afdbd382SEmanuele Giuseppe Esposito capab = s->readq(s, SDHC_CAPAB); 559afdbd382SEmanuele Giuseppe Esposito capab_sdma = FIELD_EX64(capab, SDHC_CAPAB, SDMA); 560afdbd382SEmanuele Giuseppe Esposito g_assert_cmpuint(capab_sdma, ==, supported); 561222455efSEmanuele Giuseppe Esposito } 562222455efSEmanuele Giuseppe Esposito 563afdbd382SEmanuele Giuseppe Esposito static void test_registers(void *obj, void *data, 564afdbd382SEmanuele Giuseppe Esposito QGuestAllocator *alloc) 565222455efSEmanuele Giuseppe Esposito { 566afdbd382SEmanuele Giuseppe Esposito QSDHCI *s = obj; 567afdbd382SEmanuele Giuseppe Esposito 568afdbd382SEmanuele Giuseppe Esposito /* example test */ 569afdbd382SEmanuele Giuseppe Esposito check_capab_sdma(s, s->props.capab.sdma); 570222455efSEmanuele Giuseppe Esposito } 571222455efSEmanuele Giuseppe Esposito 572afdbd382SEmanuele Giuseppe Esposito static void register_sdhci_test(void) 573afdbd382SEmanuele Giuseppe Esposito { 574afdbd382SEmanuele Giuseppe Esposito /* sdhci-test --consumes--> sdhci */ 575afdbd382SEmanuele Giuseppe Esposito qos_add_test("registers", "sdhci", test_registers, NULL); 576afdbd382SEmanuele Giuseppe Esposito } 577222455efSEmanuele Giuseppe Esposito 578afdbd382SEmanuele Giuseppe Esposito libqos_init(register_sdhci_test); 579afdbd382SEmanuele Giuseppe Esposito 580afdbd382SEmanuele Giuseppe EspositoHere a new test is created, consuming ``sdhci`` interface node 581afdbd382SEmanuele Giuseppe Espositoand creating a valid path from both machines to a test. 582222455efSEmanuele Giuseppe EspositoFinal graph will be like this:: 583222455efSEmanuele Giuseppe Esposito 584afdbd382SEmanuele Giuseppe Esposito x86_64/pc --contains--> 1440FX-pcihost --contains--> pci-bus-pc 585222455efSEmanuele Giuseppe Esposito | 586afdbd382SEmanuele Giuseppe Esposito sdhci-pci --consumes--> pci-bus <--produces--+ 587222455efSEmanuele Giuseppe Esposito | 588afdbd382SEmanuele Giuseppe Esposito +--produces--+ 589afdbd382SEmanuele Giuseppe Esposito | 590afdbd382SEmanuele Giuseppe Esposito v 591afdbd382SEmanuele Giuseppe Esposito sdhci <--consumes-- sdhci-test 592afdbd382SEmanuele Giuseppe Esposito ^ 593afdbd382SEmanuele Giuseppe Esposito | 594afdbd382SEmanuele Giuseppe Esposito +--produces-- + 595afdbd382SEmanuele Giuseppe Esposito | 596cd066eeaSPhilippe Mathieu-Daudé arm/raspi2b --contains--> generic-sdhci 597222455efSEmanuele Giuseppe Esposito 598222455efSEmanuele Giuseppe Espositoor inverting the consumes edge in consumed_by:: 599222455efSEmanuele Giuseppe Esposito 600afdbd382SEmanuele Giuseppe Esposito x86_64/pc --contains--> 1440FX-pcihost --contains--> pci-bus-pc 601222455efSEmanuele Giuseppe Esposito | 602afdbd382SEmanuele Giuseppe Esposito sdhci-pci <--consumed by-- pci-bus <--produces--+ 603222455efSEmanuele Giuseppe Esposito | 604afdbd382SEmanuele Giuseppe Esposito +--produces--+ 605afdbd382SEmanuele Giuseppe Esposito | 606afdbd382SEmanuele Giuseppe Esposito v 607afdbd382SEmanuele Giuseppe Esposito sdhci --consumed by--> sdhci-test 608afdbd382SEmanuele Giuseppe Esposito ^ 609afdbd382SEmanuele Giuseppe Esposito | 610afdbd382SEmanuele Giuseppe Esposito +--produces-- + 611afdbd382SEmanuele Giuseppe Esposito | 612cd066eeaSPhilippe Mathieu-Daudé arm/raspi2b --contains--> generic-sdhci 613222455efSEmanuele Giuseppe Esposito 614222455efSEmanuele Giuseppe EspositoAssuming there the binary is 615222455efSEmanuele Giuseppe Esposito``QTEST_QEMU_BINARY=./qemu-system-x86_64`` 616222455efSEmanuele Giuseppe Espositoa valid test path will be: 617afdbd382SEmanuele Giuseppe Esposito``/x86_64/pc/1440FX-pcihost/pci-bus-pc/pci-bus/sdhci-pc/sdhci/sdhci-test`` 618afdbd382SEmanuele Giuseppe Esposito 619afdbd382SEmanuele Giuseppe Espositoand for the binary ``QTEST_QEMU_BINARY=./qemu-system-arm``: 620afdbd382SEmanuele Giuseppe Esposito 621cd066eeaSPhilippe Mathieu-Daudé``/arm/raspi2b/generic-sdhci/sdhci/sdhci-test`` 622222455efSEmanuele Giuseppe Esposito 623222455efSEmanuele Giuseppe EspositoAdditional examples are also in ``test-qgraph.c`` 624222455efSEmanuele Giuseppe Esposito 625222455efSEmanuele Giuseppe EspositoQgraph API reference 626768f14f9SPaolo Bonzini-------------------- 627222455efSEmanuele Giuseppe Esposito 628222455efSEmanuele Giuseppe Esposito.. kernel-doc:: tests/qtest/libqos/qgraph.h 629