qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qgraph.h (14764B)


      1 /*
      2  * libqos driver framework
      3  *
      4  * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Lesser General Public
      8  * License version 2.1 as published by the Free Software Foundation.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Lesser General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Lesser General Public
     16  * License along with this library; if not, see <http://www.gnu.org/licenses/>
     17  */
     18 
     19 #ifndef QGRAPH_H
     20 #define QGRAPH_H
     21 
     22 #include <gmodule.h>
     23 #include "qemu/module.h"
     24 #include "libqos-malloc.h"
     25 
     26 /* maximum path length */
     27 #define QOS_PATH_MAX_ELEMENT_SIZE 64
     28 
     29 typedef struct QOSGraphObject QOSGraphObject;
     30 typedef struct QOSGraphNode QOSGraphNode;
     31 typedef struct QOSGraphEdge QOSGraphEdge;
     32 typedef struct QOSGraphEdgeOptions QOSGraphEdgeOptions;
     33 typedef struct QOSGraphTestOptions QOSGraphTestOptions;
     34 
     35 /* Constructor for drivers, machines and test */
     36 typedef void *(*QOSCreateDriverFunc) (void *parent, QGuestAllocator *alloc,
     37                                       void *addr);
     38 typedef void *(*QOSCreateMachineFunc) (QTestState *qts);
     39 typedef void (*QOSTestFunc) (void *parent, void *arg, QGuestAllocator *alloc);
     40 
     41 /* QOSGraphObject functions */
     42 typedef void *(*QOSGetDriver) (void *object, const char *interface);
     43 typedef QOSGraphObject *(*QOSGetDevice) (void *object, const char *name);
     44 typedef void (*QOSDestructorFunc) (QOSGraphObject *object);
     45 typedef void (*QOSStartFunct) (QOSGraphObject *object);
     46 
     47 /* Test options functions */
     48 typedef void *(*QOSBeforeTest) (GString *cmd_line, void *arg);
     49 
     50 /**
     51  * struct QOSGraphEdgeOptions:
     52  * Edge options to be passed to the contains/consumes \*_args function.
     53  * @arg: optional arg that will be used by dest edge
     54  * @size_arg: @arg size that will be used by dest edge
     55  * @extra_device_opts: optional additional command line for dest
     56  *                     edge, used to add additional attributes
     57  *                     *after* the node command line, the
     58  *                     framework automatically prepends ","
     59  *                     to this argument.
     60  * @before_cmd_line: optional additional command line for dest
     61  *                   edge, used to add additional attributes
     62  *                   *before* the node command line, usually
     63  *                   other non-node represented commands,
     64  *                   like "-fdsev synt"
     65  * @after_cmd_line: optional extra command line to be added
     66  *                  after the device command. This option
     67  *                  is used to add other devices
     68  *                  command line that depend on current node.
     69  *                  Automatically prepends " " to this argument
     70  * @edge_name: optional edge to differentiate multiple
     71  *             devices with same node name
     72  */
     73 struct QOSGraphEdgeOptions {
     74     void *arg;
     75     uint32_t size_arg;
     76     const char *extra_device_opts;
     77     const char *before_cmd_line;
     78     const char *after_cmd_line;
     79     const char *edge_name;
     80 };
     81 
     82 /**
     83  * struct QOSGraphTestOptions:
     84  * Test options to be passed to the test functions.
     85  * @edge: edge arguments that will be used by test.
     86  *        Note that test *does not* use edge_name,
     87  *        and uses instead arg and size_arg as
     88  *        data arg for its test function.
     89  * @arg:  if @before is non-NULL, pass @arg there.
     90  *        Otherwise pass it to the test function.
     91  * @before: executed before the test. Used to add
     92  *          additional parameters to the command line
     93  *          and modify the argument to the test function.
     94  * @subprocess: run the test in a subprocess.
     95  */
     96 struct QOSGraphTestOptions {
     97     QOSGraphEdgeOptions edge;
     98     void *arg;
     99     QOSBeforeTest before;
    100     bool subprocess;
    101 };
    102 
    103 /**
    104  * struct QOSGraphObject:
    105  * Each driver, test or machine of this framework will have a
    106  * QOSGraphObject as first field.
    107  *
    108  * This set of functions offered by QOSGraphObject are executed
    109  * in different stages of the framework:
    110  * @get_driver: see @get_device
    111  * @get_device: Once a machine-to-test path has been
    112  *              found, the framework traverses it again and allocates all the
    113  *              nodes, using the provided constructor. To satisfy their
    114  *              relations, i.e. for produces or contains, where a struct
    115  *              constructor needs an external parameter represented by the
    116  *              previous node, the framework will call
    117  *              @get_device (for contains) or @get_driver (for produces),
    118  *              depending on the edge type, passing them the name of the next
    119  *              node to be taken and getting from them the corresponding
    120  *              pointer to the actual structure of the next node to
    121  *              be used in the path.
    122  * @start_hw: This function is executed after all the path objects
    123  *            have been allocated, but before the test is run. It starts the
    124  *            hw, setting the initial configurations (\*_device_enable) and
    125  *            making it ready for the test.
    126  * @destructor: Opposite to the node constructor, destroys the object.
    127  *              This function is called after the test has been executed, and
    128  *              performs a complete cleanup of each node allocated field.
    129  *              In case no constructor is provided, no destructor will be
    130  *              called.
    131  * @free: free the memory associated to the QOSGraphObject and its contained
    132  *        children
    133  */
    134 struct QOSGraphObject {
    135     QOSGetDriver get_driver;
    136     QOSGetDevice get_device;
    137     QOSStartFunct start_hw;
    138     QOSDestructorFunc destructor;
    139     GDestroyNotify free;
    140 };
    141 
    142 /**
    143  * qos_graph_init(): initialize the framework, creates two hash
    144  * tables: one for the nodes and another for the edges.
    145  */
    146 void qos_graph_init(void);
    147 
    148 /**
    149  * qos_graph_destroy(): deallocates all the hash tables,
    150  * freeing all nodes and edges.
    151  */
    152 void qos_graph_destroy(void);
    153 
    154 /**
    155  * qos_node_destroy(): removes and frees a node from the
    156  * nodes hash table.
    157  * @key: Name of the node
    158  */
    159 void qos_node_destroy(void *key);
    160 
    161 /**
    162  * qos_edge_destroy(): removes and frees an edge from the
    163  * edges hash table.
    164  * @key: Name of the node
    165  */
    166 void qos_edge_destroy(void *key);
    167 
    168 /**
    169  * qos_add_test(): adds a test node @name to the nodes hash table.
    170  * @name: Name of the test
    171  * @interface: Name of the interface node it consumes
    172  * @test_func: Actual test to perform
    173  * @opts: Facultative options (see %QOSGraphTestOptions)
    174  *
    175  * The test will consume a @interface node, and once the
    176  * graph walking algorithm has found it, the @test_func will be
    177  * executed. It also has the possibility to
    178  * add an optional @opts (see %QOSGraphTestOptions).
    179  *
    180  * For tests, opts->edge.arg and size_arg represent the arg to pass
    181  * to @test_func
    182  */
    183 void qos_add_test(const char *name, const char *interface,
    184                   QOSTestFunc test_func,
    185                   QOSGraphTestOptions *opts);
    186 
    187 /**
    188  * qos_node_create_machine(): creates the machine @name and
    189  * adds it to the node hash table.
    190  * @name: Name of the machine
    191  * @function: Machine constructor
    192  *
    193  * This node will be of type QNODE_MACHINE and have @function
    194  * as constructor
    195  */
    196 void qos_node_create_machine(const char *name, QOSCreateMachineFunc function);
    197 
    198 /**
    199  * qos_node_create_machine_args(): same as qos_node_create_machine,
    200  * but with the possibility to add an optional ", @opts" after -M machine
    201  * command line.
    202  * @name: Name of the machine
    203  * @function: Machine constructor
    204  * @opts: Optional additional command line
    205  */
    206 void qos_node_create_machine_args(const char *name,
    207                                   QOSCreateMachineFunc function,
    208                                   const char *opts);
    209 
    210 /**
    211  * qos_node_create_driver(): creates the driver @name and
    212  * adds it to the node hash table.
    213  * @name: Name of the driver
    214  * @function: Driver constructor
    215  *
    216  * This node will be of type QNODE_DRIVER and have @function
    217  * as constructor
    218  */
    219 void qos_node_create_driver(const char *name, QOSCreateDriverFunc function);
    220 
    221 /**
    222  * qos_node_create_driver_named(): behaves as qos_node_create_driver() with the
    223  * extension of allowing to specify a different node name vs. associated QEMU
    224  * device name.
    225  * @name: Custom, unique name of the node to be created
    226  * @qemu_name: Actual (official) QEMU driver name the node shall be
    227  * associated with
    228  * @function: Driver constructor
    229  *
    230  * Use this function instead of qos_node_create_driver() if you need to create
    231  * several instances of the same QEMU device. You are free to choose a custom
    232  * node name, however the chosen node name must always be unique.
    233  */
    234 void qos_node_create_driver_named(const char *name, const char *qemu_name,
    235                                   QOSCreateDriverFunc function);
    236 
    237 /**
    238  * qos_node_contains(): creates one or more edges of type QEDGE_CONTAINS
    239  * and adds them to the edge list mapped to @container in the
    240  * edge hash table.
    241  * @container: Source node that "contains"
    242  * @contained: Destination node that "is contained"
    243  * @opts: Facultative options (see %QOSGraphEdgeOptions)
    244  *
    245  * The edges will have @container as source and @contained as destination.
    246  *
    247  * If @opts is NULL, a single edge will be added with no options.
    248  * If @opts is non-NULL, the arguments after @contained represent a
    249  * NULL-terminated list of %QOSGraphEdgeOptions structs, and an
    250  * edge will be added for each of them.
    251  *
    252  * This function can be useful when there are multiple devices
    253  * with the same node name contained in a machine/other node
    254  *
    255  * For example, if ``arm/raspi2b`` contains 2 ``generic-sdhci``
    256  * devices, the right commands will be:
    257  *
    258  * .. code::
    259  *
    260  *    qos_node_create_machine("arm/raspi2b");
    261  *    qos_node_create_driver("generic-sdhci", constructor);
    262  *    // assume rest of the fields are set NULL
    263  *    QOSGraphEdgeOptions op1 = { .edge_name = "emmc" };
    264  *    QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" };
    265  *    qos_node_contains("arm/raspi2b", "generic-sdhci", &op1, &op2, NULL);
    266  *
    267  * Of course this also requires that the @container's get_device function
    268  * should implement a case for "emmc" and "sdcard".
    269  *
    270  * For contains, op1.arg and op1.size_arg represent the arg to pass
    271  * to @contained constructor to properly initialize it.
    272  */
    273 void qos_node_contains(const char *container, const char *contained,
    274                        QOSGraphEdgeOptions *opts, ...);
    275 
    276 /**
    277  * qos_node_produces(): creates an edge of type QEDGE_PRODUCES and
    278  * adds it to the edge list mapped to @producer in the
    279  * edge hash table.
    280  * @producer: Source node that "produces"
    281  * @interface: Interface node that "is produced"
    282  *
    283  * This edge will have @producer as source and @interface as destination.
    284  */
    285 void qos_node_produces(const char *producer, const char *interface);
    286 
    287 /**
    288  * qos_node_consumes():  creates an edge of type QEDGE_CONSUMED_BY and
    289  * adds it to the edge list mapped to @interface in the
    290  * edge hash table.
    291  * @consumer: Node that "consumes"
    292  * @interface: Interface node that "is consumed by"
    293  * @opts: Facultative options (see %QOSGraphEdgeOptions)
    294  *
    295  * This edge will have @interface as source and @consumer as destination.
    296  * It also has the possibility to add an optional @opts
    297  * (see %QOSGraphEdgeOptions)
    298  */
    299 void qos_node_consumes(const char *consumer, const char *interface,
    300                        QOSGraphEdgeOptions *opts);
    301 
    302 /**
    303  * qos_invalidate_command_line(): invalidates current command line, so that
    304  * qgraph framework cannot try to cache the current command line and
    305  * forces QEMU to restart.
    306  */
    307 void qos_invalidate_command_line(void);
    308 
    309 /**
    310  * qos_get_current_command_line(): return the command line required by the
    311  * machine and driver objects.  This is the same string that was passed to
    312  * the test's "before" callback, if any.
    313  */
    314 const char *qos_get_current_command_line(void);
    315 
    316 /**
    317  * qos_allocate_objects():
    318  * @qts: The #QTestState that will be referred to by the machine object.
    319  * @p_alloc: Where to store the allocator for the machine object, or %NULL.
    320  *
    321  * Allocate driver objects for the current test
    322  * path, but relative to the QTestState @qts.
    323  *
    324  * Returns a test object just like the one that was passed to
    325  * the test function, but relative to @qts.
    326  */
    327 void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc);
    328 
    329 /**
    330  * qos_object_destroy(): calls the destructor for @obj
    331  * @obj: A #QOSGraphObject to destroy
    332  */
    333 void qos_object_destroy(QOSGraphObject *obj);
    334 
    335 /**
    336  * qos_object_queue_destroy(): queue the destructor for @obj so that it is
    337  * called at the end of the test
    338  * @obj: A #QOSGraphObject to destroy
    339  */
    340 void qos_object_queue_destroy(QOSGraphObject *obj);
    341 
    342 /**
    343  * qos_object_start_hw(): calls the start_hw function for @obj
    344  * @obj: A #QOSGraphObject containing the start_hw function
    345  */
    346 void qos_object_start_hw(QOSGraphObject *obj);
    347 
    348 /**
    349  * qos_machine_new(): instantiate a new machine node
    350  * @node: Machine node to be instantiated
    351  * @qts: A #QTestState that will be referred to by the machine object.
    352  *
    353  * Returns a machine object.
    354  */
    355 QOSGraphObject *qos_machine_new(QOSGraphNode *node, QTestState *qts);
    356 
    357 /**
    358  * qos_machine_new(): instantiate a new driver node
    359  * @node: A driver node to be instantiated
    360  * @parent: A #QOSGraphObject to be consumed by the new driver node
    361  * @alloc: An allocator to be used by the new driver node.
    362  * @arg: The argument for the consumed-by edge to @node.
    363  *
    364  * Calls the constructor for the driver object.
    365  */
    366 QOSGraphObject *qos_driver_new(QOSGraphNode *node, QOSGraphObject *parent,
    367                                QGuestAllocator *alloc, void *arg);
    368 
    369 /**
    370  * qos_dump_graph(): prints all currently existing nodes and
    371  * edges to stdout. Just for debugging purposes.
    372  *
    373  * All qtests add themselves to the overall qos graph by calling qgraph
    374  * functions that add device nodes and edges between the individual graph
    375  * nodes for tests. As the actual graph is assmbled at runtime by the qos
    376  * subsystem, it is sometimes not obvious how the overall graph looks like.
    377  * E.g. when writing new tests it may happen that those new tests are simply
    378  * ignored by the qtest framework.
    379  *
    380  * This function allows to identify problems in the created qgraph. Keep in
    381  * mind: only tests with a path down from the actual test case node (leaf) up
    382  * to the graph's root node are actually executed by the qtest framework. And
    383  * the qtest framework uses QMP to automatically check which QEMU drivers are
    384  * actually currently available, and accordingly qos marks certain paths as
    385  * 'unavailable' in such cases (e.g. when QEMU was compiled without support for
    386  * a certain feature).
    387  */
    388 void qos_dump_graph(void);
    389 
    390 #endif