One Hat Cyber Team
Your IP :
216.73.216.115
Server IP :
194.44.31.54
Server :
Linux zen.imath.kiev.ua 4.18.0-553.77.1.el8_10.x86_64 #1 SMP Fri Oct 3 14:30:23 UTC 2025 x86_64
Server Software :
Apache/2.4.37 (Rocky Linux) OpenSSL/1.1.1k
PHP Version :
5.6.40
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
doc
/
qemu-kvm
/
devel
/
Edit File:
qgraph.html
<!DOCTYPE html> <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]--> <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]--> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Qtest Driver Framework — QEMU qemu-kvm-6.2.0-53.module+el8.10.0+2055+8eb7870b.4 documentation</title> <link rel="shortcut icon" href="../_static/qemu_32x32.png"/> <link rel="stylesheet" href="../_static/css/theme.css" type="text/css" /> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> <link rel="index" title="Index" href="../genindex.html" /> <link rel="search" title="Search" href="../search.html" /> <link rel="next" title="Decodetree Specification" href="decodetree.html" /> <link rel="prev" title="QTest Device Emulation Testing Framework" href="qtest.html" /> <script src="../_static/js/modernizr.min.js"></script> </head> <body class="wy-body-for-nav"> <div class="wy-grid-for-nav"> <nav data-toggle="wy-nav-shift" class="wy-nav-side"> <div class="wy-side-scroll"> <div class="wy-side-nav-search"> <a href="../index.html" class="icon icon-home"> QEMU <img src="../_static/qemu_128x128.png" class="logo" alt="Logo"/> </a> <div class="version"> 6.2.0 </div> <div role="search"> <form id="rtd-search-form" class="wy-form" action="../search.html" method="get"> <input type="text" name="q" placeholder="Search docs" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> </div> </div> <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation"> <p class="caption"><span class="caption-text">Contents:</span></p> <ul class="current"> <li class="toctree-l1"><a class="reference internal" href="../about/index.html">About QEMU</a></li> <li class="toctree-l1"><a class="reference internal" href="../system/index.html">System Emulation</a></li> <li class="toctree-l1"><a class="reference internal" href="../user/index.html">User Mode Emulation</a></li> <li class="toctree-l1"><a class="reference internal" href="../tools/index.html">Tools</a></li> <li class="toctree-l1"><a class="reference internal" href="../interop/index.html">System Emulation Management and Interoperability</a></li> <li class="toctree-l1"><a class="reference internal" href="../specs/index.html">System Emulation Guest Hardware Specifications</a></li> <li class="toctree-l1 current"><a class="reference internal" href="index.html">Developer Information</a><ul class="current"> <li class="toctree-l2"><a class="reference internal" href="code-of-conduct.html">Code of Conduct</a></li> <li class="toctree-l2"><a class="reference internal" href="conflict-resolution.html">Conflict Resolution Policy</a></li> <li class="toctree-l2"><a class="reference internal" href="build-system.html">The QEMU build system architecture</a></li> <li class="toctree-l2"><a class="reference internal" href="style.html">QEMU Coding Style</a></li> <li class="toctree-l2"><a class="reference internal" href="kconfig.html">QEMU and Kconfig</a></li> <li class="toctree-l2"><a class="reference internal" href="testing.html">Testing in QEMU</a></li> <li class="toctree-l2"><a class="reference internal" href="fuzzing.html">Fuzzing</a></li> <li class="toctree-l2"><a class="reference internal" href="control-flow-integrity.html">Control-Flow Integrity (CFI)</a></li> <li class="toctree-l2"><a class="reference internal" href="loads-stores.html">Load and Store APIs</a></li> <li class="toctree-l2"><a class="reference internal" href="memory.html">The memory API</a></li> <li class="toctree-l2"><a class="reference internal" href="migration.html">Migration</a></li> <li class="toctree-l2"><a class="reference internal" href="atomics.html">Atomic operations in QEMU</a></li> <li class="toctree-l2"><a class="reference internal" href="stable-process.html">QEMU and the stable process</a></li> <li class="toctree-l2"><a class="reference internal" href="ci.html">CI</a></li> <li class="toctree-l2 current"><a class="reference internal" href="qtest.html">QTest Device Emulation Testing Framework</a><ul class="current"> <li class="toctree-l3 current"><a class="current reference internal" href="#">Qtest Driver Framework</a><ul> <li class="toctree-l4"><a class="reference internal" href="#qgraph-concepts">QGraph concepts</a></li> <li class="toctree-l4"><a class="reference internal" href="#creating-a-new-driver-and-its-interface">Creating a new driver and its interface</a></li> <li class="toctree-l4"><a class="reference internal" href="#adding-a-new-test">Adding a new test</a></li> <li class="toctree-l4"><a class="reference internal" href="#qgraph-api-reference">Qgraph API reference</a></li> </ul> </li> <li class="toctree-l3"><a class="reference internal" href="qtest.html#qtest-protocol">QTest Protocol</a></li> <li class="toctree-l3"><a class="reference internal" href="qtest.html#libqtest-api-reference">libqtest API reference</a></li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="decodetree.html">Decodetree Specification</a></li> <li class="toctree-l2"><a class="reference internal" href="secure-coding-practices.html">Secure Coding Practices</a></li> <li class="toctree-l2"><a class="reference internal" href="tcg.html">Translator Internals</a></li> <li class="toctree-l2"><a class="reference internal" href="tcg-icount.html">TCG Instruction Counting</a></li> <li class="toctree-l2"><a class="reference internal" href="tracing.html">Tracing</a></li> <li class="toctree-l2"><a class="reference internal" href="multi-thread-tcg.html">Multi-threaded TCG</a></li> <li class="toctree-l2"><a class="reference internal" href="tcg-plugins.html">QEMU TCG Plugins</a></li> <li class="toctree-l2"><a class="reference internal" href="bitops.html">Bitwise operations</a></li> <li class="toctree-l2"><a class="reference internal" href="ui.html">QEMU UI subsystem</a></li> <li class="toctree-l2"><a class="reference internal" href="reset.html">Reset in QEMU: the Resettable interface</a></li> <li class="toctree-l2"><a class="reference internal" href="s390-dasd-ipl.html">Booting from real channel-attached devices on s390x</a></li> <li class="toctree-l2"><a class="reference internal" href="clocks.html">Modelling a clock tree in QEMU</a></li> <li class="toctree-l2"><a class="reference internal" href="qom.html">The QEMU Object Model (QOM)</a></li> <li class="toctree-l2"><a class="reference internal" href="modules.html">QEMU modules</a></li> <li class="toctree-l2"><a class="reference internal" href="block-coroutine-wrapper.html">block-coroutine-wrapper</a></li> <li class="toctree-l2"><a class="reference internal" href="multi-process.html">Multi-process QEMU</a></li> <li class="toctree-l2"><a class="reference internal" href="ebpf_rss.html">eBPF RSS virtio-net support</a></li> <li class="toctree-l2"><a class="reference internal" href="vfio-migration.html">VFIO device Migration</a></li> <li class="toctree-l2"><a class="reference internal" href="qapi-code-gen.html">How to use the QAPI code generator</a></li> <li class="toctree-l2"><a class="reference internal" href="writing-monitor-commands.html">How to write monitor commands</a></li> <li class="toctree-l2"><a class="reference internal" href="trivial-patches.html">Trivial Patches</a></li> <li class="toctree-l2"><a class="reference internal" href="submitting-a-patch.html">Submitting a Patch</a></li> <li class="toctree-l2"><a class="reference internal" href="submitting-a-pull-request.html">Submitting a Pull Request</a></li> </ul> </li> </ul> </div> </div> </nav> <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"> <nav class="wy-nav-top" aria-label="top navigation"> <i data-toggle="wy-nav-top" class="fa fa-bars"></i> <a href="../index.html">QEMU</a> </nav> <div class="wy-nav-content"> <div class="rst-content"> <div role="navigation" aria-label="breadcrumbs navigation"> <ul class="wy-breadcrumbs"> <li><a href="../index.html">Docs</a> »</li> <li><a href="index.html">Developer Information</a> »</li> <li><a href="qtest.html">QTest Device Emulation Testing Framework</a> »</li> <li>Qtest Driver Framework</li> <li class="wy-breadcrumbs-aside"> <a href="https://gitlab.com/qemu-project/qemu/blob/master/docs/devel/qgraph.rst" class="fa fa-gitlab"> Edit on GitLab</a> </li> </ul> <hr/> </div> <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> <div itemprop="articleBody"> <div class="section" id="qtest-driver-framework"> <span id="qgraph"></span><h1>Qtest Driver Framework<a class="headerlink" href="#qtest-driver-framework" title="Permalink to this headline">¶</a></h1> <p>In order to test a specific driver, plain libqos tests need to take care of booting QEMU with the right machine and devices. This makes each test “hardcoded” for a specific configuration, reducing the possible coverage that it can reach.</p> <p>For example, the sdhci device is supported on both x86_64 and ARM boards, therefore a generic sdhci test should test all machines and drivers that support that device. Using only libqos APIs, the test has to manually take care of covering all the setups, and build the correct command line.</p> <p>This also introduces backward compatibility issues: if a device/driver command line name is changed, all tests that use that will not work properly anymore and need to be adjusted.</p> <p>The aim of qgraph is to create a graph of drivers, machines and tests such that a test aimed to a certain driver does not have to care of booting the right QEMU machine, pick the right device, build the command line and so on. Instead, it only defines what type of device it is testing (interface in qgraph terms) and the framework takes care of covering all supported types of devices and machine architectures.</p> <p>Following the above example, an interface would be <code class="docutils literal notranslate"><span class="pre">sdhci</span></code>, so the sdhci-test should only care of linking its qgraph node with that interface. In this way, if the command line of a sdhci driver is changed, only the respective qgraph driver node has to be adjusted.</p> <div class="section" id="qgraph-concepts"> <h2>QGraph concepts<a class="headerlink" href="#qgraph-concepts" title="Permalink to this headline">¶</a></h2> <p>The graph is composed by nodes that represent machines, drivers, tests and edges that define the relationships between them (<code class="docutils literal notranslate"><span class="pre">CONSUMES</span></code>, <code class="docutils literal notranslate"><span class="pre">PRODUCES</span></code>, and <code class="docutils literal notranslate"><span class="pre">CONTAINS</span></code>).</p> <div class="section" id="nodes"> <h3>Nodes<a class="headerlink" href="#nodes" title="Permalink to this headline">¶</a></h3> <p>A node can be of four types:</p> <ul class="simple"> <li><strong>QNODE_MACHINE</strong>: for example <code class="docutils literal notranslate"><span class="pre">arm/raspi2b</span></code></li> <li><strong>QNODE_DRIVER</strong>: for example <code class="docutils literal notranslate"><span class="pre">generic-sdhci</span></code></li> <li><strong>QNODE_INTERFACE</strong>: for example <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> (interface for all <code class="docutils literal notranslate"><span class="pre">-sdhci</span></code> drivers). An interface is not explicitly created, it will be automatically instantiated when a node consumes or produces it. An interface is simply a struct that abstracts the various drivers for the same type of device, and offers an API to the nodes that use it (“consume” relation in qgraph terms) that is implemented/backed up by the drivers that implement it (“produce” relation in qgraph terms).</li> <li><strong>QNODE_TEST</strong>: for example <code class="docutils literal notranslate"><span class="pre">sdhci-test</span></code>. A test consumes an interface and tests the functions provided by it.</li> </ul> <p>Notes for the nodes:</p> <ul class="simple"> <li>QNODE_MACHINE: each machine struct must have a <code class="docutils literal notranslate"><span class="pre">QGuestAllocator</span></code> and implement <code class="docutils literal notranslate"><span class="pre">get_driver()</span></code> to return the allocator mapped to the interface “memory”. The function can also return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> if the allocator is not set.</li> <li>QNODE_DRIVER: driver names must be unique, and machines and nodes planned to be “consumed” by other nodes must match QEMU drivers name, otherwise they won’t be discovered</li> </ul> </div> <div class="section" id="edges"> <h3>Edges<a class="headerlink" href="#edges" title="Permalink to this headline">¶</a></h3> <p>An edge relation between two nodes (drivers or machines) <code class="docutils literal notranslate"><span class="pre">X</span></code> and <code class="docutils literal notranslate"><span class="pre">Y</span></code> can be:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">CONSUMES</span> <span class="pre">Y</span></code>: <code class="docutils literal notranslate"><span class="pre">Y</span></code> can be plugged into <code class="docutils literal notranslate"><span class="pre">X</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">PRODUCES</span> <span class="pre">Y</span></code>: <code class="docutils literal notranslate"><span class="pre">X</span></code> provides the interface <code class="docutils literal notranslate"><span class="pre">Y</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">X</span> <span class="pre">CONTAINS</span> <span class="pre">Y</span></code>: <code class="docutils literal notranslate"><span class="pre">Y</span></code> is part of <code class="docutils literal notranslate"><span class="pre">X</span></code> component</li> </ul> </div> <div class="section" id="execution-steps"> <h3>Execution steps<a class="headerlink" href="#execution-steps" title="Permalink to this headline">¶</a></h3> <p>The basic framework steps are the following:</p> <ul class="simple"> <li>All nodes and edges are created in their respective machine/driver/test files</li> <li>The framework starts QEMU and asks for a list of available devices and machines (note that only machines and “consumed” nodes are mapped 1:1 with QEMU devices)</li> <li>The framework walks the graph starting from the available machines and performs a Depth First Search for tests</li> <li>Once a test is found, the path is walked again and all drivers are allocated accordingly and the final interface is passed to the test</li> <li>The test is executed</li> <li>Unused objects are cleaned and the path discovery is continued</li> </ul> <p>Depending on the QEMU binary used, only some drivers/machines will be available and only test that are reached by them will be executed.</p> </div> <div class="section" id="command-line"> <h3>Command line<a class="headerlink" href="#command-line" title="Permalink to this headline">¶</a></h3> <p>Command line is built by using node names and optional arguments passed by the user when building the edges.</p> <p>There are three types of command line arguments:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">in</span> <span class="pre">node</span></code> : created from the node name. For example, machines will have <code class="docutils literal notranslate"><span class="pre">-M</span> <span class="pre"><machine></span></code> to its command line, while devices <code class="docutils literal notranslate"><span class="pre">-device</span> <span class="pre"><device></span></code>. It is automatically done by the framework.</li> <li><code class="docutils literal notranslate"><span class="pre">after</span> <span class="pre">node</span></code> : added as additional argument to the node name. This argument is added optionally when creating edges, by setting the parameter <code class="docutils literal notranslate"><span class="pre">after_cmd_line</span></code> and <code class="docutils literal notranslate"><span class="pre">extra_edge_opts</span></code> in <code class="docutils literal notranslate"><span class="pre">QOSGraphEdgeOptions</span></code>. The framework automatically adds a comma before <code class="docutils literal notranslate"><span class="pre">extra_edge_opts</span></code>, because it is going to add attributes after the destination node pointed by the edge containing these options, and automatically adds a space before <code class="docutils literal notranslate"><span class="pre">after_cmd_line</span></code>, because it adds an additional device, not an attribute.</li> <li><code class="docutils literal notranslate"><span class="pre">before</span> <span class="pre">node</span></code> : added as additional argument to the node name. This argument is added optionally when creating edges, by setting the parameter <code class="docutils literal notranslate"><span class="pre">before_cmd_line</span></code> in <code class="docutils literal notranslate"><span class="pre">QOSGraphEdgeOptions</span></code>. This attribute is going to add attributes before the destination node pointed by the edge containing these options. It is helpful to commands that are not node-representable, such as <code class="docutils literal notranslate"><span class="pre">-fdsev</span></code> or <code class="docutils literal notranslate"><span class="pre">-netdev</span></code>.</li> </ul> <p>While adding command line in edges is always used, not all nodes names are used in every path walk: this is because the contained or produced ones are already added by QEMU, so only nodes that “consumes” will be used to build the command line. Also, nodes that will have <code class="docutils literal notranslate"><span class="pre">{</span> <span class="pre">"abstract"</span> <span class="pre">:</span> <span class="pre">true</span> <span class="pre">}</span></code> as QMP attribute will loose their command line, since they are not proper devices to be added in QEMU.</p> <p>Example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">QOSGraphEdgeOptions</span> <span class="n">opts</span> <span class="o">=</span> <span class="p">{</span> <span class="o">.</span><span class="n">before_cmd_line</span> <span class="o">=</span> <span class="s2">"-drive id=drv0,if=none,file=null-co://,"</span> <span class="s2">"file.read-zeroes=on,format=raw"</span><span class="p">,</span> <span class="o">.</span><span class="n">after_cmd_line</span> <span class="o">=</span> <span class="s2">"-device scsi-hd,bus=vs0.0,drive=drv0"</span><span class="p">,</span> <span class="n">opts</span><span class="o">.</span><span class="n">extra_device_opts</span> <span class="o">=</span> <span class="s2">"id=vs0"</span><span class="p">;</span> <span class="p">};</span> <span class="n">qos_node_create_driver</span><span class="p">(</span><span class="s2">"virtio-scsi-device"</span><span class="p">,</span> <span class="n">virtio_scsi_device_create</span><span class="p">);</span> <span class="n">qos_node_consumes</span><span class="p">(</span><span class="s2">"virtio-scsi-device"</span><span class="p">,</span> <span class="s2">"virtio-bus"</span><span class="p">,</span> <span class="o">&</span><span class="n">opts</span><span class="p">);</span> </pre></div> </div> <p>Will produce the following command line: <code class="docutils literal notranslate"><span class="pre">-drive</span> <span class="pre">id=drv0,if=none,file=null-co://,</span> <span class="pre">-device</span> <span class="pre">virtio-scsi-device,id=vs0</span> <span class="pre">-device</span> <span class="pre">scsi-hd,bus=vs0.0,drive=drv0</span></code></p> </div> <div class="section" id="troubleshooting-unavailable-tests"> <h3>Troubleshooting unavailable tests<a class="headerlink" href="#troubleshooting-unavailable-tests" title="Permalink to this headline">¶</a></h3> <p>If there is no path from an available machine to a test then that test will be unavailable and won’t execute. This can happen if a test or driver did not set up its qgraph node correctly. It can also happen if the necessary machine type or device is missing from the QEMU binary because it was compiled out or otherwise.</p> <p>It is possible to troubleshoot unavailable tests by running:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ QTEST_QEMU_BINARY=build/qemu-system-x86_64 build/tests/qtest/qos-test --verbose # ALL QGRAPH EDGES: { # src='virtio-net' # |-> dest='virtio-net-tests/vhost-user/multiqueue' type=2 (node=0x559142109e30) # |-> dest='virtio-net-tests/vhost-user/migrate' type=2 (node=0x559142109d00) # src='virtio-net-pci' # |-> dest='virtio-net' type=1 (node=0x55914210d740) # src='pci-bus' # |-> dest='virtio-net-pci' type=2 (node=0x55914210d880) # src='pci-bus-pc' # |-> dest='pci-bus' type=1 (node=0x559142103f40) # src='i440FX-pcihost' # |-> dest='pci-bus-pc' type=0 (node=0x55914210ac70) # src='x86_64/pc' # |-> dest='i440FX-pcihost' type=0 (node=0x5591421117f0) # src='' # |-> dest='x86_64/pc' type=0 (node=0x559142111600) # |-> dest='arm/raspi2b' type=0 (node=0x559142110740) ... # } # ALL QGRAPH NODES: { # name='virtio-net-tests/announce-self' type=3 cmd_line='(null)' [available] # name='arm/raspi2b' type=0 cmd_line='-M raspi2b ' [UNAVAILABLE] ... # } </pre></div> </div> <p>The <code class="docutils literal notranslate"><span class="pre">virtio-net-tests/announce-self</span></code> test is listed as “available” in the “ALL QGRAPH NODES” output. This means the test will execute. We can follow the qgraph path in the “ALL QGRAPH EDGES” output as follows: ‘’ -> ‘x86_64/pc’ -> ‘i440FX-pcihost’ -> ‘pci-bus-pc’ -> ‘pci-bus’ -> ‘virtio-net-pci’ -> ‘virtio-net’. The root of the qgraph is ‘’ and the depth first search begins there.</p> <p>The <code class="docutils literal notranslate"><span class="pre">arm/raspi2b</span></code> machine node is listed as “UNAVAILABLE”. Although it is reachable from the root via ‘’ -> ‘arm/raspi2b’ the node is unavailable because the QEMU binary did not list it when queried by the framework. This is expected because we used the <code class="docutils literal notranslate"><span class="pre">qemu-system-x86_64</span></code> binary which does not support ARM machine types.</p> <p>If a test is unexpectedly listed as “UNAVAILABLE”, first check that the “ALL QGRAPH EDGES” output reports edge connectivity from the root (‘’) to the test. If there is no connectivity then the qgraph nodes were not set up correctly and the driver or test code is incorrect. If there is connectivity, check the availability of each node in the path in the “ALL QGRAPH NODES” output. The first unavailable node in the path is the reason why the test is unavailable. Typically this is because the QEMU binary lacks support for the necessary machine type or device.</p> </div> </div> <div class="section" id="creating-a-new-driver-and-its-interface"> <h2>Creating a new driver and its interface<a class="headerlink" href="#creating-a-new-driver-and-its-interface" title="Permalink to this headline">¶</a></h2> <p>Here we continue the <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> use case, with the following scenario:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">sdhci-test</span></code> aims to test the <code class="docutils literal notranslate"><span class="pre">read[q,w],</span> <span class="pre">writeq</span></code> functions offered by the <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> drivers.</li> <li>The current <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> device is supported by both <code class="docutils literal notranslate"><span class="pre">x86_64/pc</span></code> and <code class="docutils literal notranslate"><span class="pre">ARM</span></code> (in this example we focus on the <code class="docutils literal notranslate"><span class="pre">arm-raspi2b</span></code>) machines.</li> <li>QEMU offers 2 types of drivers: <code class="docutils literal notranslate"><span class="pre">QSDHCI_MemoryMapped</span></code> for <code class="docutils literal notranslate"><span class="pre">ARM</span></code> and <code class="docutils literal notranslate"><span class="pre">QSDHCI_PCI</span></code> for <code class="docutils literal notranslate"><span class="pre">x86_64/pc</span></code>. Both implement the <code class="docutils literal notranslate"><span class="pre">read[q,w],</span> <span class="pre">writeq</span></code> functions.</li> </ul> <p>In order to implement such scenario in qgraph, the test developer needs to:</p> <ul> <li><p class="first">Create the <code class="docutils literal notranslate"><span class="pre">x86_64/pc</span></code> machine node. This machine uses the <code class="docutils literal notranslate"><span class="pre">pci-bus</span></code> architecture so it <code class="docutils literal notranslate"><span class="pre">contains</span></code> a PCI driver, <code class="docutils literal notranslate"><span class="pre">pci-bus-pc</span></code>. The actual path is</p> <p><code class="docutils literal notranslate"><span class="pre">x86_64/pc</span> <span class="pre">--contains--></span> <span class="pre">1440FX-pcihost</span> <span class="pre">--contains--></span> <span class="pre">pci-bus-pc</span> <span class="pre">--produces--></span> <span class="pre">pci-bus</span></code>.</p> <p>For the sake of this example, we do not focus on the PCI interface implementation.</p> </li> <li><p class="first">Create the <code class="docutils literal notranslate"><span class="pre">sdhci-pci</span></code> driver node, representing <code class="docutils literal notranslate"><span class="pre">QSDHCI_PCI</span></code>. The driver uses the PCI bus (and its API), so it must <code class="docutils literal notranslate"><span class="pre">consume</span></code> the <code class="docutils literal notranslate"><span class="pre">pci-bus</span></code> generic interface (which abstracts all the pci drivers available)</p> <p><code class="docutils literal notranslate"><span class="pre">sdhci-pci</span> <span class="pre">--consumes--></span> <span class="pre">pci-bus</span></code></p> </li> <li><p class="first">Create an <code class="docutils literal notranslate"><span class="pre">arm/raspi2b</span></code> machine node. This machine <code class="docutils literal notranslate"><span class="pre">contains</span></code> a <code class="docutils literal notranslate"><span class="pre">generic-sdhci</span></code> memory mapped <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> driver node, representing <code class="docutils literal notranslate"><span class="pre">QSDHCI_MemoryMapped</span></code>.</p> <p><code class="docutils literal notranslate"><span class="pre">arm/raspi2b</span> <span class="pre">--contains--></span> <span class="pre">generic-sdhci</span></code></p> </li> <li><p class="first">Create the <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> interface node. This interface offers the functions that are shared by all <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> devices. The interface is produced by <code class="docutils literal notranslate"><span class="pre">sdhci-pci</span></code> and <code class="docutils literal notranslate"><span class="pre">generic-sdhci</span></code>, the available architecture-specific drivers.</p> <p><code class="docutils literal notranslate"><span class="pre">sdhci-pci</span> <span class="pre">--produces--></span> <span class="pre">sdhci</span></code></p> <p><code class="docutils literal notranslate"><span class="pre">generic-sdhci</span> <span class="pre">--produces--></span> <span class="pre">sdhci</span></code></p> </li> <li><p class="first">Create the <code class="docutils literal notranslate"><span class="pre">sdhci-test</span></code> test node. The test <code class="docutils literal notranslate"><span class="pre">consumes</span></code> the <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> interface, using its API. It doesn’t need to look at the supported machines or drivers.</p> <p><code class="docutils literal notranslate"><span class="pre">sdhci-test</span> <span class="pre">--consumes--></span> <span class="pre">sdhci</span></code></p> </li> </ul> <p><code class="docutils literal notranslate"><span class="pre">arm-raspi2b</span></code> machine, simplified from <code class="docutils literal notranslate"><span class="pre">tests/qtest/libqos/arm-raspi2-machine.c</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>#include "qgraph.h" struct QRaspi2Machine { QOSGraphObject obj; QGuestAllocator alloc; QSDHCI_MemoryMapped sdhci; }; static void *raspi2_get_driver(void *object, const char *interface) { QRaspi2Machine *machine = object; if (!g_strcmp0(interface, "memory")) { return &machine->alloc; } fprintf(stderr, "%s not present in arm/raspi2b\n", interface); g_assert_not_reached(); } static QOSGraphObject *raspi2_get_device(void *obj, const char *device) { QRaspi2Machine *machine = obj; if (!g_strcmp0(device, "generic-sdhci")) { return &machine->sdhci.obj; } fprintf(stderr, "%s not present in arm/raspi2b\n", device); g_assert_not_reached(); } static void *qos_create_machine_arm_raspi2(QTestState *qts) { QRaspi2Machine *machine = g_new0(QRaspi2Machine, 1); alloc_init(&machine->alloc, ...); /* Get node(s) contained inside (CONTAINS) */ machine->obj.get_device = raspi2_get_device; /* Get node(s) produced (PRODUCES) */ machine->obj.get_driver = raspi2_get_driver; /* free the object */ machine->obj.destructor = raspi2_destructor; qos_init_sdhci_mm(&machine->sdhci, ...); return &machine->obj; } static void raspi2_register_nodes(void) { /* arm/raspi2b --contains--> generic-sdhci */ qos_node_create_machine("arm/raspi2b", qos_create_machine_arm_raspi2); qos_node_contains("arm/raspi2b", "generic-sdhci", NULL); } libqos_init(raspi2_register_nodes); </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">x86_64/pc</span></code> machine, simplified from <code class="docutils literal notranslate"><span class="pre">tests/qtest/libqos/x86_64_pc-machine.c</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>#include "qgraph.h" struct i440FX_pcihost { QOSGraphObject obj; QPCIBusPC pci; }; struct QX86PCMachine { QOSGraphObject obj; QGuestAllocator alloc; i440FX_pcihost bridge; }; /* i440FX_pcihost */ static QOSGraphObject *i440FX_host_get_device(void *obj, const char *device) { i440FX_pcihost *host = obj; if (!g_strcmp0(device, "pci-bus-pc")) { return &host->pci.obj; } fprintf(stderr, "%s not present in i440FX-pcihost\n", device); g_assert_not_reached(); } /* x86_64/pc machine */ static void *pc_get_driver(void *object, const char *interface) { QX86PCMachine *machine = object; if (!g_strcmp0(interface, "memory")) { return &machine->alloc; } fprintf(stderr, "%s not present in x86_64/pc\n", interface); g_assert_not_reached(); } static QOSGraphObject *pc_get_device(void *obj, const char *device) { QX86PCMachine *machine = obj; if (!g_strcmp0(device, "i440FX-pcihost")) { return &machine->bridge.obj; } fprintf(stderr, "%s not present in x86_64/pc\n", device); g_assert_not_reached(); } static void *qos_create_machine_pc(QTestState *qts) { QX86PCMachine *machine = g_new0(QX86PCMachine, 1); /* Get node(s) contained inside (CONTAINS) */ machine->obj.get_device = pc_get_device; /* Get node(s) produced (PRODUCES) */ machine->obj.get_driver = pc_get_driver; /* free the object */ machine->obj.destructor = pc_destructor; pc_alloc_init(&machine->alloc, qts, ALLOC_NO_FLAGS); /* Get node(s) contained inside (CONTAINS) */ machine->bridge.obj.get_device = i440FX_host_get_device; return &machine->obj; } static void pc_machine_register_nodes(void) { /* x86_64/pc --contains--> 1440FX-pcihost --contains--> * pci-bus-pc [--produces--> pci-bus (in pci.h)] */ qos_node_create_machine("x86_64/pc", qos_create_machine_pc); qos_node_contains("x86_64/pc", "i440FX-pcihost", NULL); /* contained drivers don't need a constructor, * they will be init by the parent */ qos_node_create_driver("i440FX-pcihost", NULL); qos_node_contains("i440FX-pcihost", "pci-bus-pc", NULL); } libqos_init(pc_machine_register_nodes); </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">sdhci</span></code> taken from <code class="docutils literal notranslate"><span class="pre">tests/qtest/libqos/sdhci.c</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>/* Interface node, offers the sdhci API */ struct QSDHCI { uint16_t (*readw)(QSDHCI *s, uint32_t reg); uint64_t (*readq)(QSDHCI *s, uint32_t reg); void (*writeq)(QSDHCI *s, uint32_t reg, uint64_t val); /* other fields */ }; /* Memory Mapped implementation of QSDHCI */ struct QSDHCI_MemoryMapped { QOSGraphObject obj; QSDHCI sdhci; /* other driver-specific fields */ }; /* PCI implementation of QSDHCI */ struct QSDHCI_PCI { QOSGraphObject obj; QSDHCI sdhci; /* other driver-specific fields */ }; /* Memory mapped implementation of QSDHCI */ static void *sdhci_mm_get_driver(void *obj, const char *interface) { QSDHCI_MemoryMapped *smm = obj; if (!g_strcmp0(interface, "sdhci")) { return &smm->sdhci; } fprintf(stderr, "%s not present in generic-sdhci\n", interface); g_assert_not_reached(); } void qos_init_sdhci_mm(QSDHCI_MemoryMapped *sdhci, QTestState *qts, uint32_t addr, QSDHCIProperties *common) { /* Get node contained inside (CONTAINS) */ sdhci->obj.get_driver = sdhci_mm_get_driver; /* SDHCI interface API */ sdhci->sdhci.readw = sdhci_mm_readw; sdhci->sdhci.readq = sdhci_mm_readq; sdhci->sdhci.writeq = sdhci_mm_writeq; sdhci->qts = qts; } /* PCI implementation of QSDHCI */ static void *sdhci_pci_get_driver(void *object, const char *interface) { QSDHCI_PCI *spci = object; if (!g_strcmp0(interface, "sdhci")) { return &spci->sdhci; } fprintf(stderr, "%s not present in sdhci-pci\n", interface); g_assert_not_reached(); } static void *sdhci_pci_create(void *pci_bus, QGuestAllocator *alloc, void *addr) { QSDHCI_PCI *spci = g_new0(QSDHCI_PCI, 1); QPCIBus *bus = pci_bus; uint64_t barsize; qpci_device_init(&spci->dev, bus, addr); /* SDHCI interface API */ spci->sdhci.readw = sdhci_pci_readw; spci->sdhci.readq = sdhci_pci_readq; spci->sdhci.writeq = sdhci_pci_writeq; /* Get node(s) produced (PRODUCES) */ spci->obj.get_driver = sdhci_pci_get_driver; spci->obj.start_hw = sdhci_pci_start_hw; spci->obj.destructor = sdhci_destructor; return &spci->obj; } static void qsdhci_register_nodes(void) { QOSGraphEdgeOptions opts = { .extra_device_opts = "addr=04.0", }; /* generic-sdhci */ /* generic-sdhci --produces--> sdhci */ qos_node_create_driver("generic-sdhci", NULL); qos_node_produces("generic-sdhci", "sdhci"); /* sdhci-pci */ /* sdhci-pci --produces--> sdhci * sdhci-pci --consumes--> pci-bus */ qos_node_create_driver("sdhci-pci", sdhci_pci_create); qos_node_produces("sdhci-pci", "sdhci"); qos_node_consumes("sdhci-pci", "pci-bus", &opts); } libqos_init(qsdhci_register_nodes); </pre></div> </div> <p>In the above example, all possible types of relations are created:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x86_64</span><span class="o">/</span><span class="n">pc</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="mi">1440</span><span class="n">FX</span><span class="o">-</span><span class="n">pcihost</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="n">pci</span><span class="o">-</span><span class="n">bus</span><span class="o">-</span><span class="n">pc</span> <span class="o">|</span> <span class="n">sdhci</span><span class="o">-</span><span class="n">pci</span> <span class="o">--</span><span class="n">consumes</span><span class="o">--></span> <span class="n">pci</span><span class="o">-</span><span class="n">bus</span> <span class="o"><--</span><span class="n">produces</span><span class="o">--+</span> <span class="o">|</span> <span class="o">+--</span><span class="n">produces</span><span class="o">--+</span> <span class="o">|</span> <span class="n">v</span> <span class="n">sdhci</span> <span class="o">^</span> <span class="o">|</span> <span class="o">+--</span><span class="n">produces</span><span class="o">--</span> <span class="o">+</span> <span class="o">|</span> <span class="n">arm</span><span class="o">/</span><span class="n">raspi2b</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="n">generic</span><span class="o">-</span><span class="n">sdhci</span> </pre></div> </div> <p>or inverting the consumes edge in consumed_by:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x86_64</span><span class="o">/</span><span class="n">pc</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="mi">1440</span><span class="n">FX</span><span class="o">-</span><span class="n">pcihost</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="n">pci</span><span class="o">-</span><span class="n">bus</span><span class="o">-</span><span class="n">pc</span> <span class="o">|</span> <span class="n">sdhci</span><span class="o">-</span><span class="n">pci</span> <span class="o"><--</span><span class="n">consumed</span> <span class="n">by</span><span class="o">--</span> <span class="n">pci</span><span class="o">-</span><span class="n">bus</span> <span class="o"><--</span><span class="n">produces</span><span class="o">--+</span> <span class="o">|</span> <span class="o">+--</span><span class="n">produces</span><span class="o">--+</span> <span class="o">|</span> <span class="n">v</span> <span class="n">sdhci</span> <span class="o">^</span> <span class="o">|</span> <span class="o">+--</span><span class="n">produces</span><span class="o">--</span> <span class="o">+</span> <span class="o">|</span> <span class="n">arm</span><span class="o">/</span><span class="n">raspi2b</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="n">generic</span><span class="o">-</span><span class="n">sdhci</span> </pre></div> </div> </div> <div class="section" id="adding-a-new-test"> <h2>Adding a new test<a class="headerlink" href="#adding-a-new-test" title="Permalink to this headline">¶</a></h2> <p>Given the above setup, adding a new test is very simple. <code class="docutils literal notranslate"><span class="pre">sdhci-test</span></code>, taken from <code class="docutils literal notranslate"><span class="pre">tests/qtest/sdhci-test.c</span></code>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">static</span> <span class="n">void</span> <span class="n">check_capab_sdma</span><span class="p">(</span><span class="n">QSDHCI</span> <span class="o">*</span><span class="n">s</span><span class="p">,</span> <span class="nb">bool</span> <span class="n">supported</span><span class="p">)</span> <span class="p">{</span> <span class="n">uint64_t</span> <span class="n">capab</span><span class="p">,</span> <span class="n">capab_sdma</span><span class="p">;</span> <span class="n">capab</span> <span class="o">=</span> <span class="n">s</span><span class="o">-></span><span class="n">readq</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">SDHC_CAPAB</span><span class="p">);</span> <span class="n">capab_sdma</span> <span class="o">=</span> <span class="n">FIELD_EX64</span><span class="p">(</span><span class="n">capab</span><span class="p">,</span> <span class="n">SDHC_CAPAB</span><span class="p">,</span> <span class="n">SDMA</span><span class="p">);</span> <span class="n">g_assert_cmpuint</span><span class="p">(</span><span class="n">capab_sdma</span><span class="p">,</span> <span class="o">==</span><span class="p">,</span> <span class="n">supported</span><span class="p">);</span> <span class="p">}</span> <span class="n">static</span> <span class="n">void</span> <span class="n">test_registers</span><span class="p">(</span><span class="n">void</span> <span class="o">*</span><span class="n">obj</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="n">QGuestAllocator</span> <span class="o">*</span><span class="n">alloc</span><span class="p">)</span> <span class="p">{</span> <span class="n">QSDHCI</span> <span class="o">*</span><span class="n">s</span> <span class="o">=</span> <span class="n">obj</span><span class="p">;</span> <span class="o">/*</span> <span class="n">example</span> <span class="n">test</span> <span class="o">*/</span> <span class="n">check_capab_sdma</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">s</span><span class="o">-></span><span class="n">props</span><span class="o">.</span><span class="n">capab</span><span class="o">.</span><span class="n">sdma</span><span class="p">);</span> <span class="p">}</span> <span class="n">static</span> <span class="n">void</span> <span class="n">register_sdhci_test</span><span class="p">(</span><span class="n">void</span><span class="p">)</span> <span class="p">{</span> <span class="o">/*</span> <span class="n">sdhci</span><span class="o">-</span><span class="n">test</span> <span class="o">--</span><span class="n">consumes</span><span class="o">--></span> <span class="n">sdhci</span> <span class="o">*/</span> <span class="n">qos_add_test</span><span class="p">(</span><span class="s2">"registers"</span><span class="p">,</span> <span class="s2">"sdhci"</span><span class="p">,</span> <span class="n">test_registers</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span> <span class="p">}</span> <span class="n">libqos_init</span><span class="p">(</span><span class="n">register_sdhci_test</span><span class="p">);</span> </pre></div> </div> <p>Here a new test is created, consuming <code class="docutils literal notranslate"><span class="pre">sdhci</span></code> interface node and creating a valid path from both machines to a test. Final graph will be like this:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x86_64</span><span class="o">/</span><span class="n">pc</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="mi">1440</span><span class="n">FX</span><span class="o">-</span><span class="n">pcihost</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="n">pci</span><span class="o">-</span><span class="n">bus</span><span class="o">-</span><span class="n">pc</span> <span class="o">|</span> <span class="n">sdhci</span><span class="o">-</span><span class="n">pci</span> <span class="o">--</span><span class="n">consumes</span><span class="o">--></span> <span class="n">pci</span><span class="o">-</span><span class="n">bus</span> <span class="o"><--</span><span class="n">produces</span><span class="o">--+</span> <span class="o">|</span> <span class="o">+--</span><span class="n">produces</span><span class="o">--+</span> <span class="o">|</span> <span class="n">v</span> <span class="n">sdhci</span> <span class="o"><--</span><span class="n">consumes</span><span class="o">--</span> <span class="n">sdhci</span><span class="o">-</span><span class="n">test</span> <span class="o">^</span> <span class="o">|</span> <span class="o">+--</span><span class="n">produces</span><span class="o">--</span> <span class="o">+</span> <span class="o">|</span> <span class="n">arm</span><span class="o">/</span><span class="n">raspi2b</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="n">generic</span><span class="o">-</span><span class="n">sdhci</span> </pre></div> </div> <p>or inverting the consumes edge in consumed_by:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">x86_64</span><span class="o">/</span><span class="n">pc</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="mi">1440</span><span class="n">FX</span><span class="o">-</span><span class="n">pcihost</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="n">pci</span><span class="o">-</span><span class="n">bus</span><span class="o">-</span><span class="n">pc</span> <span class="o">|</span> <span class="n">sdhci</span><span class="o">-</span><span class="n">pci</span> <span class="o"><--</span><span class="n">consumed</span> <span class="n">by</span><span class="o">--</span> <span class="n">pci</span><span class="o">-</span><span class="n">bus</span> <span class="o"><--</span><span class="n">produces</span><span class="o">--+</span> <span class="o">|</span> <span class="o">+--</span><span class="n">produces</span><span class="o">--+</span> <span class="o">|</span> <span class="n">v</span> <span class="n">sdhci</span> <span class="o">--</span><span class="n">consumed</span> <span class="n">by</span><span class="o">--></span> <span class="n">sdhci</span><span class="o">-</span><span class="n">test</span> <span class="o">^</span> <span class="o">|</span> <span class="o">+--</span><span class="n">produces</span><span class="o">--</span> <span class="o">+</span> <span class="o">|</span> <span class="n">arm</span><span class="o">/</span><span class="n">raspi2b</span> <span class="o">--</span><span class="n">contains</span><span class="o">--></span> <span class="n">generic</span><span class="o">-</span><span class="n">sdhci</span> </pre></div> </div> <p>Assuming there the binary is <code class="docutils literal notranslate"><span class="pre">QTEST_QEMU_BINARY=./qemu-system-x86_64</span></code> a valid test path will be: <code class="docutils literal notranslate"><span class="pre">/x86_64/pc/1440FX-pcihost/pci-bus-pc/pci-bus/sdhci-pc/sdhci/sdhci-test</span></code></p> <p>and for the binary <code class="docutils literal notranslate"><span class="pre">QTEST_QEMU_BINARY=./qemu-system-arm</span></code>:</p> <p><code class="docutils literal notranslate"><span class="pre">/arm/raspi2b/generic-sdhci/sdhci/sdhci-test</span></code></p> <p>Additional examples are also in <code class="docutils literal notranslate"><span class="pre">test-qgraph.c</span></code></p> </div> <div class="section" id="qgraph-api-reference"> <h2>Qgraph API reference<a class="headerlink" href="#qgraph-api-reference" title="Permalink to this headline">¶</a></h2> <dl class="type"> <dt id="c.QOSGraphEdgeOptions"> struct <code class="descname">QOSGraphEdgeOptions</code><a class="headerlink" href="#c.QOSGraphEdgeOptions" title="Permalink to this definition">¶</a></dt> <dd><p>Edge options to be passed to the contains/consumes *_args function.</p> </dd></dl> <p><strong>Definition</strong></p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">QOSGraphEdgeOptions</span> <span class="p">{</span> <span class="n">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">;</span> <span class="n">uint32_t</span> <span class="n">size_arg</span><span class="p">;</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">extra_device_opts</span><span class="p">;</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">before_cmd_line</span><span class="p">;</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">after_cmd_line</span><span class="p">;</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">edge_name</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p><strong>Members</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">arg</span></code></dt> <dd>optional arg that will be used by dest edge</dd> <dt><code class="docutils literal notranslate"><span class="pre">size_arg</span></code></dt> <dd><strong>arg</strong> size that will be used by dest edge</dd> <dt><code class="docutils literal notranslate"><span class="pre">extra_device_opts</span></code></dt> <dd>optional additional command line for dest edge, used to add additional attributes <em>after</em> the node command line, the framework automatically prepends “,” to this argument.</dd> <dt><code class="docutils literal notranslate"><span class="pre">before_cmd_line</span></code></dt> <dd>optional additional command line for dest edge, used to add additional attributes <em>before</em> the node command line, usually other non-node represented commands, like “-fdsev synt”</dd> <dt><code class="docutils literal notranslate"><span class="pre">after_cmd_line</span></code></dt> <dd>optional extra command line to be added after the device command. This option is used to add other devices command line that depend on current node. Automatically prepends ” ” to this argument</dd> <dt><code class="docutils literal notranslate"><span class="pre">edge_name</span></code></dt> <dd>optional edge to differentiate multiple devices with same node name</dd> </dl> <dl class="type"> <dt id="c.QOSGraphTestOptions"> struct <code class="descname">QOSGraphTestOptions</code><a class="headerlink" href="#c.QOSGraphTestOptions" title="Permalink to this definition">¶</a></dt> <dd><p>Test options to be passed to the test functions.</p> </dd></dl> <p><strong>Definition</strong></p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">QOSGraphTestOptions</span> <span class="p">{</span> <span class="n">QOSGraphEdgeOptions</span> <span class="n">edge</span><span class="p">;</span> <span class="n">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">;</span> <span class="n">QOSBeforeTest</span> <span class="n">before</span><span class="p">;</span> <span class="nb">bool</span> <span class="n">subprocess</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p><strong>Members</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">edge</span></code></dt> <dd>edge arguments that will be used by test. Note that test <em>does not</em> use edge_name, and uses instead arg and size_arg as data arg for its test function.</dd> <dt><code class="docutils literal notranslate"><span class="pre">arg</span></code></dt> <dd>if <strong>before</strong> is non-NULL, pass <strong>arg</strong> there. Otherwise pass it to the test function.</dd> <dt><code class="docutils literal notranslate"><span class="pre">before</span></code></dt> <dd>executed before the test. Used to add additional parameters to the command line and modify the argument to the test function.</dd> <dt><code class="docutils literal notranslate"><span class="pre">subprocess</span></code></dt> <dd>run the test in a subprocess.</dd> </dl> <dl class="type"> <dt id="c.QOSGraphObject"> struct <code class="descname">QOSGraphObject</code><a class="headerlink" href="#c.QOSGraphObject" title="Permalink to this definition">¶</a></dt> <dd><p>Each driver, test or machine of this framework will have a QOSGraphObject as first field.</p> </dd></dl> <p><strong>Definition</strong></p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">struct</span> <span class="n">QOSGraphObject</span> <span class="p">{</span> <span class="n">QOSGetDriver</span> <span class="n">get_driver</span><span class="p">;</span> <span class="n">QOSGetDevice</span> <span class="n">get_device</span><span class="p">;</span> <span class="n">QOSStartFunct</span> <span class="n">start_hw</span><span class="p">;</span> <span class="n">QOSDestructorFunc</span> <span class="n">destructor</span><span class="p">;</span> <span class="n">GDestroyNotify</span> <span class="n">free</span><span class="p">;</span> <span class="p">};</span> </pre></div> </div> <p><strong>Members</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">get_driver</span></code></dt> <dd>see <strong>get_device</strong></dd> <dt><code class="docutils literal notranslate"><span class="pre">get_device</span></code></dt> <dd>Once a machine-to-test path has been found, the framework traverses it again and allocates all the nodes, using the provided constructor. To satisfy their relations, i.e. for produces or contains, where a struct constructor needs an external parameter represented by the previous node, the framework will call <strong>get_device</strong> (for contains) or <strong>get_driver</strong> (for produces), depending on the edge type, passing them the name of the next node to be taken and getting from them the corresponding pointer to the actual structure of the next node to be used in the path.</dd> <dt><code class="docutils literal notranslate"><span class="pre">start_hw</span></code></dt> <dd>This function is executed after all the path objects have been allocated, but before the test is run. It starts the hw, setting the initial configurations (*_device_enable) and making it ready for the test.</dd> <dt><code class="docutils literal notranslate"><span class="pre">destructor</span></code></dt> <dd>Opposite to the node constructor, destroys the object. This function is called after the test has been executed, and performs a complete cleanup of each node allocated field. In case no constructor is provided, no destructor will be called.</dd> <dt><code class="docutils literal notranslate"><span class="pre">free</span></code></dt> <dd>free the memory associated to the QOSGraphObject and its contained children</dd> </dl> <p><strong>Description</strong></p> <p>This set of functions offered by QOSGraphObject are executed in different stages of the framework:</p> <dl class="function"> <dt id="c.qos_graph_init"> void <code class="descname">qos_graph_init</code><span class="sig-paren">(</span>void<span class="sig-paren">)</span><a class="headerlink" href="#c.qos_graph_init" title="Permalink to this definition">¶</a></dt> <dd><p>initialize the framework, creates two hash tables: one for the nodes and another for the edges.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">void</span></code></dt> <dd>no arguments</dd> </dl> <dl class="function"> <dt id="c.qos_graph_destroy"> void <code class="descname">qos_graph_destroy</code><span class="sig-paren">(</span>void<span class="sig-paren">)</span><a class="headerlink" href="#c.qos_graph_destroy" title="Permalink to this definition">¶</a></dt> <dd><p>deallocates all the hash tables, freeing all nodes and edges.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">void</span></code></dt> <dd>no arguments</dd> </dl> <dl class="function"> <dt id="c.qos_node_destroy"> void <code class="descname">qos_node_destroy</code><span class="sig-paren">(</span>void<em> *key</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_node_destroy" title="Permalink to this definition">¶</a></dt> <dd><p>removes and frees a node from the nodes hash table.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">*key</span></code></dt> <dd>Name of the node</dd> </dl> <dl class="function"> <dt id="c.qos_edge_destroy"> void <code class="descname">qos_edge_destroy</code><span class="sig-paren">(</span>void<em> *key</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_edge_destroy" title="Permalink to this definition">¶</a></dt> <dd><p>removes and frees an edge from the edges hash table.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">*key</span></code></dt> <dd>Name of the node</dd> </dl> <dl class="function"> <dt id="c.qos_add_test"> void <code class="descname">qos_add_test</code><span class="sig-paren">(</span>const char<em> *name</em>, const char<em> *interface</em>, QOSTestFunc<em> test_func</em>, <a class="reference internal" href="#c.QOSGraphTestOptions" title="QOSGraphTestOptions">QOSGraphTestOptions</a><em> *opts</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_add_test" title="Permalink to this definition">¶</a></dt> <dd><p>adds a test node <strong>name</strong> to the nodes hash table.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name</span></code></dt> <dd>Name of the test</dd> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*interface</span></code></dt> <dd>Name of the interface node it consumes</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSTestFunc</span> <span class="pre">test_func</span></code></dt> <dd>Actual test to perform</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphTestOptions</span> <span class="pre">*opts</span></code></dt> <dd>Facultative options (see <code class="docutils literal notranslate"><span class="pre">QOSGraphTestOptions</span></code>)</dd> </dl> <p><strong>Description</strong></p> <p>The test will consume a <strong>interface</strong> node, and once the graph walking algorithm has found it, the <strong>test_func</strong> will be executed. It also has the possibility to add an optional <strong>opts</strong> (see <code class="docutils literal notranslate"><span class="pre">QOSGraphTestOptions</span></code>).</p> <p>For tests, opts->edge.arg and size_arg represent the arg to pass to <strong>test_func</strong></p> <dl class="function"> <dt id="c.qos_node_create_machine"> void <code class="descname">qos_node_create_machine</code><span class="sig-paren">(</span>const char<em> *name</em>, QOSCreateMachineFunc<em> function</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_node_create_machine" title="Permalink to this definition">¶</a></dt> <dd><p>creates the machine <strong>name</strong> and adds it to the node hash table.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name</span></code></dt> <dd>Name of the machine</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSCreateMachineFunc</span> <span class="pre">function</span></code></dt> <dd>Machine constructor</dd> </dl> <p><strong>Description</strong></p> <p>This node will be of type QNODE_MACHINE and have <strong>function</strong> as constructor</p> <dl class="function"> <dt id="c.qos_node_create_machine_args"> void <code class="descname">qos_node_create_machine_args</code><span class="sig-paren">(</span>const char<em> *name</em>, QOSCreateMachineFunc<em> function</em>, const char<em> *opts</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_node_create_machine_args" title="Permalink to this definition">¶</a></dt> <dd><p>same as qos_node_create_machine, but with the possibility to add an optional “, <strong>opts</strong>” after -M machine command line.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name</span></code></dt> <dd>Name of the machine</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSCreateMachineFunc</span> <span class="pre">function</span></code></dt> <dd>Machine constructor</dd> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*opts</span></code></dt> <dd>Optional additional command line</dd> </dl> <dl class="function"> <dt id="c.qos_node_create_driver"> void <code class="descname">qos_node_create_driver</code><span class="sig-paren">(</span>const char<em> *name</em>, QOSCreateDriverFunc<em> function</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_node_create_driver" title="Permalink to this definition">¶</a></dt> <dd><p>creates the driver <strong>name</strong> and adds it to the node hash table.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name</span></code></dt> <dd>Name of the driver</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSCreateDriverFunc</span> <span class="pre">function</span></code></dt> <dd>Driver constructor</dd> </dl> <p><strong>Description</strong></p> <p>This node will be of type QNODE_DRIVER and have <strong>function</strong> as constructor</p> <dl class="function"> <dt id="c.qos_node_create_driver_named"> void <code class="descname">qos_node_create_driver_named</code><span class="sig-paren">(</span>const char<em> *name</em>, const char<em> *qemu_name</em>, QOSCreateDriverFunc<em> function</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_node_create_driver_named" title="Permalink to this definition">¶</a></dt> <dd><p>behaves as qos_node_create_driver() with the extension of allowing to specify a different node name vs. associated QEMU device name.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name</span></code></dt> <dd>Custom, unique name of the node to be created</dd> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*qemu_name</span></code></dt> <dd>Actual (official) QEMU driver name the node shall be associated with</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSCreateDriverFunc</span> <span class="pre">function</span></code></dt> <dd>Driver constructor</dd> </dl> <p><strong>Description</strong></p> <p>Use this function instead of qos_node_create_driver() if you need to create several instances of the same QEMU device. You are free to choose a custom node name, however the chosen node name must always be unique.</p> <dl class="function"> <dt id="c.qos_node_contains"> void <code class="descname">qos_node_contains</code><span class="sig-paren">(</span>const char<em> *container</em>, const char<em> *contained</em>, <a class="reference internal" href="#c.QOSGraphEdgeOptions" title="QOSGraphEdgeOptions">QOSGraphEdgeOptions</a><em> *opts</em>, ...<span class="sig-paren">)</span><a class="headerlink" href="#c.qos_node_contains" title="Permalink to this definition">¶</a></dt> <dd><p>creates one or more edges of type QEDGE_CONTAINS and adds them to the edge list mapped to <strong>container</strong> in the edge hash table.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*container</span></code></dt> <dd>Source node that “contains”</dd> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*contained</span></code></dt> <dd>Destination node that “is contained”</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphEdgeOptions</span> <span class="pre">*opts</span></code></dt> <dd>Facultative options (see <code class="docutils literal notranslate"><span class="pre">QOSGraphEdgeOptions</span></code>)</dd> <dt><code class="docutils literal notranslate"><span class="pre">...</span></code></dt> <dd>variable arguments</dd> </dl> <p><strong>Description</strong></p> <p>The edges will have <strong>container</strong> as source and <strong>contained</strong> as destination.</p> <p>If <strong>opts</strong> is NULL, a single edge will be added with no options. If <strong>opts</strong> is non-NULL, the arguments after <strong>contained</strong> represent a NULL-terminated list of <code class="docutils literal notranslate"><span class="pre">QOSGraphEdgeOptions</span></code> structs, and an edge will be added for each of them.</p> <p>This function can be useful when there are multiple devices with the same node name contained in a machine/other node</p> <p>For example, if <code class="docutils literal notranslate"><span class="pre">arm/raspi2b</span></code> contains 2 <code class="docutils literal notranslate"><span class="pre">generic-sdhci</span></code> devices, the right commands will be:</p> <div class="code highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">qos_node_create_machine</span><span class="p">(</span><span class="s2">"arm/raspi2b"</span><span class="p">);</span> <span class="n">qos_node_create_driver</span><span class="p">(</span><span class="s2">"generic-sdhci"</span><span class="p">,</span> <span class="n">constructor</span><span class="p">);</span> <span class="o">//</span> <span class="n">assume</span> <span class="n">rest</span> <span class="n">of</span> <span class="n">the</span> <span class="n">fields</span> <span class="n">are</span> <span class="nb">set</span> <span class="n">NULL</span> <span class="n">QOSGraphEdgeOptions</span> <span class="n">op1</span> <span class="o">=</span> <span class="p">{</span> <span class="o">.</span><span class="n">edge_name</span> <span class="o">=</span> <span class="s2">"emmc"</span> <span class="p">};</span> <span class="n">QOSGraphEdgeOptions</span> <span class="n">op2</span> <span class="o">=</span> <span class="p">{</span> <span class="o">.</span><span class="n">edge_name</span> <span class="o">=</span> <span class="s2">"sdcard"</span> <span class="p">};</span> <span class="n">qos_node_contains</span><span class="p">(</span><span class="s2">"arm/raspi2b"</span><span class="p">,</span> <span class="s2">"generic-sdhci"</span><span class="p">,</span> <span class="o">&</span><span class="n">op1</span><span class="p">,</span> <span class="o">&</span><span class="n">op2</span><span class="p">,</span> <span class="n">NULL</span><span class="p">);</span> </pre></div> </div> <p>Of course this also requires that the <strong>container</strong>’s get_device function should implement a case for “emmc” and “sdcard”.</p> <p>For contains, op1.arg and op1.size_arg represent the arg to pass to <strong>contained</strong> constructor to properly initialize it.</p> <dl class="function"> <dt id="c.qos_node_produces"> void <code class="descname">qos_node_produces</code><span class="sig-paren">(</span>const char<em> *producer</em>, const char<em> *interface</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_node_produces" title="Permalink to this definition">¶</a></dt> <dd><p>creates an edge of type QEDGE_PRODUCES and adds it to the edge list mapped to <strong>producer</strong> in the edge hash table.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*producer</span></code></dt> <dd>Source node that “produces”</dd> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*interface</span></code></dt> <dd>Interface node that “is produced”</dd> </dl> <p><strong>Description</strong></p> <p>This edge will have <strong>producer</strong> as source and <strong>interface</strong> as destination.</p> <dl class="function"> <dt id="c.qos_node_consumes"> void <code class="descname">qos_node_consumes</code><span class="sig-paren">(</span>const char<em> *consumer</em>, const char<em> *interface</em>, <a class="reference internal" href="#c.QOSGraphEdgeOptions" title="QOSGraphEdgeOptions">QOSGraphEdgeOptions</a><em> *opts</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_node_consumes" title="Permalink to this definition">¶</a></dt> <dd><p>creates an edge of type QEDGE_CONSUMED_BY and adds it to the edge list mapped to <strong>interface</strong> in the edge hash table.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*consumer</span></code></dt> <dd>Node that “consumes”</dd> <dt><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*interface</span></code></dt> <dd>Interface node that “is consumed by”</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphEdgeOptions</span> <span class="pre">*opts</span></code></dt> <dd>Facultative options (see <code class="docutils literal notranslate"><span class="pre">QOSGraphEdgeOptions</span></code>)</dd> </dl> <p><strong>Description</strong></p> <p>This edge will have <strong>interface</strong> as source and <strong>consumer</strong> as destination. It also has the possibility to add an optional <strong>opts</strong> (see <code class="docutils literal notranslate"><span class="pre">QOSGraphEdgeOptions</span></code>)</p> <dl class="function"> <dt id="c.qos_invalidate_command_line"> void <code class="descname">qos_invalidate_command_line</code><span class="sig-paren">(</span>void<span class="sig-paren">)</span><a class="headerlink" href="#c.qos_invalidate_command_line" title="Permalink to this definition">¶</a></dt> <dd><p>invalidates current command line, so that qgraph framework cannot try to cache the current command line and forces QEMU to restart.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">void</span></code></dt> <dd>no arguments</dd> </dl> <dl class="function"> <dt id="c.qos_get_current_command_line"> const char * <code class="descname">qos_get_current_command_line</code><span class="sig-paren">(</span>void<span class="sig-paren">)</span><a class="headerlink" href="#c.qos_get_current_command_line" title="Permalink to this definition">¶</a></dt> <dd><p>return the command line required by the machine and driver objects. This is the same string that was passed to the test’s “before” callback, if any.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">void</span></code></dt> <dd>no arguments</dd> </dl> <dl class="function"> <dt id="c.qos_allocate_objects"> void * <code class="descname">qos_allocate_objects</code><span class="sig-paren">(</span>QTestState<em> *qts</em>, QGuestAllocator<em> **p_alloc</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_allocate_objects" title="Permalink to this definition">¶</a></dt> <dd></dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">QTestState</span> <span class="pre">*qts</span></code></dt> <dd>The <code class="xref c c-type docutils literal notranslate"><span class="pre">QTestState</span></code> that will be referred to by the machine object.</dd> <dt><code class="docutils literal notranslate"><span class="pre">QGuestAllocator</span> <span class="pre">**p_alloc</span></code></dt> <dd>Where to store the allocator for the machine object, or <code class="docutils literal notranslate"><span class="pre">NULL</span></code>.</dd> </dl> <p><strong>Description</strong></p> <p>Allocate driver objects for the current test path, but relative to the QTestState <strong>qts</strong>.</p> <p>Returns a test object just like the one that was passed to the test function, but relative to <strong>qts</strong>.</p> <dl class="function"> <dt id="c.qos_object_destroy"> void <code class="descname">qos_object_destroy</code><span class="sig-paren">(</span><a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject">QOSGraphObject</a><em> *obj</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_object_destroy" title="Permalink to this definition">¶</a></dt> <dd><p>calls the destructor for <strong>obj</strong></p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphObject</span> <span class="pre">*obj</span></code></dt> <dd>A <a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">QOSGraphObject</span></code></a> to destroy</dd> </dl> <dl class="function"> <dt id="c.qos_object_queue_destroy"> void <code class="descname">qos_object_queue_destroy</code><span class="sig-paren">(</span><a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject">QOSGraphObject</a><em> *obj</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_object_queue_destroy" title="Permalink to this definition">¶</a></dt> <dd><p>queue the destructor for <strong>obj</strong> so that it is called at the end of the test</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphObject</span> <span class="pre">*obj</span></code></dt> <dd>A <a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">QOSGraphObject</span></code></a> to destroy</dd> </dl> <dl class="function"> <dt id="c.qos_object_start_hw"> void <code class="descname">qos_object_start_hw</code><span class="sig-paren">(</span><a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject">QOSGraphObject</a><em> *obj</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_object_start_hw" title="Permalink to this definition">¶</a></dt> <dd><p>calls the start_hw function for <strong>obj</strong></p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphObject</span> <span class="pre">*obj</span></code></dt> <dd>A <a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">QOSGraphObject</span></code></a> containing the start_hw function</dd> </dl> <dl class="function"> <dt id="c.qos_machine_new"> <a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject">QOSGraphObject</a> * <code class="descname">qos_machine_new</code><span class="sig-paren">(</span>QOSGraphNode<em> *node</em>, QTestState<em> *qts</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_machine_new" title="Permalink to this definition">¶</a></dt> <dd><p>instantiate a new machine node</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphNode</span> <span class="pre">*node</span></code></dt> <dd>Machine node to be instantiated</dd> <dt><code class="docutils literal notranslate"><span class="pre">QTestState</span> <span class="pre">*qts</span></code></dt> <dd>A <code class="xref c c-type docutils literal notranslate"><span class="pre">QTestState</span></code> that will be referred to by the machine object.</dd> </dl> <p><strong>Description</strong></p> <p>Returns a machine object.</p> <dl class="function"> <dt id="c.qos_driver_new"> <a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject">QOSGraphObject</a> * <code class="descname">qos_driver_new</code><span class="sig-paren">(</span>QOSGraphNode<em> *node</em>, <a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject">QOSGraphObject</a><em> *parent</em>, QGuestAllocator<em> *alloc</em>, void<em> *arg</em><span class="sig-paren">)</span><a class="headerlink" href="#c.qos_driver_new" title="Permalink to this definition">¶</a></dt> <dd><p>instantiate a new driver node</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphNode</span> <span class="pre">*node</span></code></dt> <dd>A driver node to be instantiated</dd> <dt><code class="docutils literal notranslate"><span class="pre">QOSGraphObject</span> <span class="pre">*parent</span></code></dt> <dd>A <a class="reference internal" href="#c.QOSGraphObject" title="QOSGraphObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">QOSGraphObject</span></code></a> to be consumed by the new driver node</dd> <dt><code class="docutils literal notranslate"><span class="pre">QGuestAllocator</span> <span class="pre">*alloc</span></code></dt> <dd>An allocator to be used by the new driver node.</dd> <dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">*arg</span></code></dt> <dd>The argument for the consumed-by edge to <strong>node</strong>.</dd> </dl> <p><strong>Description</strong></p> <p>Calls the constructor for the driver object.</p> <dl class="function"> <dt id="c.qos_dump_graph"> void <code class="descname">qos_dump_graph</code><span class="sig-paren">(</span>void<span class="sig-paren">)</span><a class="headerlink" href="#c.qos_dump_graph" title="Permalink to this definition">¶</a></dt> <dd><p>prints all currently existing nodes and edges to stdout. Just for debugging purposes.</p> </dd></dl> <p><strong>Parameters</strong></p> <dl class="docutils"> <dt><code class="docutils literal notranslate"><span class="pre">void</span></code></dt> <dd>no arguments</dd> </dl> <p><strong>Description</strong></p> <p>All qtests add themselves to the overall qos graph by calling qgraph functions that add device nodes and edges between the individual graph nodes for tests. As the actual graph is assmbled at runtime by the qos subsystem, it is sometimes not obvious how the overall graph looks like. E.g. when writing new tests it may happen that those new tests are simply ignored by the qtest framework.</p> <p>This function allows to identify problems in the created qgraph. Keep in mind: only tests with a path down from the actual test case node (leaf) up to the graph’s root node are actually executed by the qtest framework. And the qtest framework uses QMP to automatically check which QEMU drivers are actually currently available, and accordingly qos marks certain pathes as ‘unavailable’ in such cases (e.g. when QEMU was compiled without support for a certain feature).</p> </div> </div> </div> </div> <footer> <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation"> <a href="decodetree.html" class="btn btn-neutral float-right" title="Decodetree Specification" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right"></span></a> <a href="qtest.html" class="btn btn-neutral" title="QTest Device Emulation Testing Framework" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> Previous</a> </div> <hr/> <div role="contentinfo"> <p> © Copyright 2021, The QEMU Project Developers. </p> </div> Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. <!-- Empty para to force a blank line after "Built with Sphinx ..." --> <p></p> <p>This documentation is for QEMU version 6.2.0.</p> <p><a href="../about/license.html">QEMU and this manual are released under the GNU General Public License, version 2.</a></p> </footer> </div> </div> </section> </div> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT:'../', VERSION:'qemu-kvm-6.2.0-53.module+el8.10.0+2055+8eb7870b.4', LANGUAGE:'None', COLLAPSE_INDEX:false, FILE_SUFFIX:'.html', HAS_SOURCE: false, SOURCELINK_SUFFIX: '.txt' }; </script> <script type="text/javascript" src="../_static/jquery.js"></script> <script type="text/javascript" src="../_static/underscore.js"></script> <script type="text/javascript" src="../_static/doctools.js"></script> <script type="text/javascript" src="../_static/js/theme.js"></script> <script type="text/javascript"> jQuery(function () { SphinxRtdTheme.Navigation.enable(true); }); </script> </body> </html>
Simpan