1f62a0bffSAlexander Bulekov /*
2f62a0bffSAlexander Bulekov * libqos driver framework
3f62a0bffSAlexander Bulekov *
4f62a0bffSAlexander Bulekov * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
5f62a0bffSAlexander Bulekov *
6f62a0bffSAlexander Bulekov * This library is free software; you can redistribute it and/or
7f62a0bffSAlexander Bulekov * modify it under the terms of the GNU Lesser General Public
8dc0ad02dSThomas Huth * License version 2.1 as published by the Free Software Foundation.
9f62a0bffSAlexander Bulekov *
10f62a0bffSAlexander Bulekov * This library is distributed in the hope that it will be useful,
11f62a0bffSAlexander Bulekov * but WITHOUT ANY WARRANTY; without even the implied warranty of
12f62a0bffSAlexander Bulekov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13f62a0bffSAlexander Bulekov * Lesser General Public License for more details.
14f62a0bffSAlexander Bulekov *
15f62a0bffSAlexander Bulekov * You should have received a copy of the GNU Lesser General Public
16f62a0bffSAlexander Bulekov * License along with this library; if not, see <http://www.gnu.org/licenses/>
17f62a0bffSAlexander Bulekov */
18f62a0bffSAlexander Bulekov
19f62a0bffSAlexander Bulekov #include "qemu/osdep.h"
20f62a0bffSAlexander Bulekov #include <getopt.h>
21907b5105SMarc-André Lureau #include "../libqtest.h"
22f62a0bffSAlexander Bulekov #include "qapi/qmp/qdict.h"
23f62a0bffSAlexander Bulekov #include "qapi/qmp/qbool.h"
24f62a0bffSAlexander Bulekov #include "qapi/qmp/qstring.h"
25f62a0bffSAlexander Bulekov #include "qemu/module.h"
26f62a0bffSAlexander Bulekov #include "qapi/qmp/qlist.h"
27*b243c73cSXuzhou Cheng #include "libqos-malloc.h"
28a2ce7dbdSPaolo Bonzini #include "qgraph.h"
29a2ce7dbdSPaolo Bonzini #include "qgraph_internal.h"
30a2ce7dbdSPaolo Bonzini #include "qos_external.h"
31f62a0bffSAlexander Bulekov
machine_apply_to_node(const char * name)32a56f3cdbSMarkus Armbruster static void machine_apply_to_node(const char *name)
33f62a0bffSAlexander Bulekov {
34a56f3cdbSMarkus Armbruster char *machine_name = g_strconcat(qtest_get_arch(), "/", name, NULL);
35a56f3cdbSMarkus Armbruster
36a56f3cdbSMarkus Armbruster qos_graph_node_set_availability(machine_name, true);
37a56f3cdbSMarkus Armbruster g_free(machine_name);
38f62a0bffSAlexander Bulekov }
39a56f3cdbSMarkus Armbruster
machines_apply_to_node(MachineInfoList * mach_info)40a56f3cdbSMarkus Armbruster void machines_apply_to_node(MachineInfoList *mach_info)
41a56f3cdbSMarkus Armbruster {
42a56f3cdbSMarkus Armbruster MachineInfoList *tail;
43a56f3cdbSMarkus Armbruster
44a56f3cdbSMarkus Armbruster for (tail = mach_info; tail; tail = tail->next) {
45a56f3cdbSMarkus Armbruster machine_apply_to_node(tail->value->name);
46a56f3cdbSMarkus Armbruster if (tail->value->alias) {
47a56f3cdbSMarkus Armbruster machine_apply_to_node(tail->value->alias);
48a56f3cdbSMarkus Armbruster }
49a56f3cdbSMarkus Armbruster }
50a56f3cdbSMarkus Armbruster }
51a56f3cdbSMarkus Armbruster
type_apply_to_node(const char * name,bool is_abstract)52a56f3cdbSMarkus Armbruster static void type_apply_to_node(const char *name, bool is_abstract)
53a56f3cdbSMarkus Armbruster {
54f62a0bffSAlexander Bulekov qos_graph_node_set_availability(name, true);
55f62a0bffSAlexander Bulekov if (is_abstract) {
56f62a0bffSAlexander Bulekov qos_delete_cmd_line(name);
57f62a0bffSAlexander Bulekov }
58f62a0bffSAlexander Bulekov }
59f62a0bffSAlexander Bulekov
types_apply_to_node(ObjectTypeInfoList * type_info)60a56f3cdbSMarkus Armbruster void types_apply_to_node(ObjectTypeInfoList *type_info)
61f62a0bffSAlexander Bulekov {
62a56f3cdbSMarkus Armbruster ObjectTypeInfoList *tail;
63f62a0bffSAlexander Bulekov
64a56f3cdbSMarkus Armbruster for (tail = type_info; tail; tail = tail->next) {
65a56f3cdbSMarkus Armbruster type_apply_to_node(tail->value->name, tail->value->abstract);
66f62a0bffSAlexander Bulekov }
67f62a0bffSAlexander Bulekov }
68f62a0bffSAlexander Bulekov
get_machine_allocator(QOSGraphObject * obj)69f6528054SMarkus Armbruster static QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
70f62a0bffSAlexander Bulekov {
71f62a0bffSAlexander Bulekov return obj->get_driver(obj, "memory");
72f62a0bffSAlexander Bulekov }
73f62a0bffSAlexander Bulekov
74f62a0bffSAlexander Bulekov /**
75f62a0bffSAlexander Bulekov * allocate_objects(): given an array of nodes @arg,
76f62a0bffSAlexander Bulekov * walks the path invoking all constructors and
77f62a0bffSAlexander Bulekov * passing the corresponding parameter in order to
78f62a0bffSAlexander Bulekov * continue the objects allocation.
79f62a0bffSAlexander Bulekov * Once the test is reached, return the object it consumes.
80f62a0bffSAlexander Bulekov *
81f62a0bffSAlexander Bulekov * Since the machine and QEDGE_CONSUMED_BY nodes allocate
82f62a0bffSAlexander Bulekov * memory in the constructor, g_test_queue_destroy is used so
83f62a0bffSAlexander Bulekov * that after execution they can be safely free'd. (The test's
84f62a0bffSAlexander Bulekov * ->before callback is also welcome to use g_test_queue_destroy).
85f62a0bffSAlexander Bulekov *
86f62a0bffSAlexander Bulekov * Note: as specified in walk_path() too, @arg is an array of
87f62a0bffSAlexander Bulekov * char *, where arg[0] is a pointer to the command line
88f62a0bffSAlexander Bulekov * string that will be used to properly start QEMU when executing
89f62a0bffSAlexander Bulekov * the test, and the remaining elements represent the actual objects
90f62a0bffSAlexander Bulekov * that will be allocated.
91f62a0bffSAlexander Bulekov */
allocate_objects(QTestState * qts,char ** path,QGuestAllocator ** p_alloc)92f62a0bffSAlexander Bulekov void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc)
93f62a0bffSAlexander Bulekov {
94f62a0bffSAlexander Bulekov int current = 0;
95f62a0bffSAlexander Bulekov QGuestAllocator *alloc;
96f62a0bffSAlexander Bulekov QOSGraphObject *parent = NULL;
97f62a0bffSAlexander Bulekov QOSGraphEdge *edge;
98f62a0bffSAlexander Bulekov QOSGraphNode *node;
99f62a0bffSAlexander Bulekov void *edge_arg;
100f62a0bffSAlexander Bulekov void *obj;
101f62a0bffSAlexander Bulekov
102f62a0bffSAlexander Bulekov node = qos_graph_get_node(path[current]);
103f62a0bffSAlexander Bulekov g_assert(node->type == QNODE_MACHINE);
104f62a0bffSAlexander Bulekov
105f62a0bffSAlexander Bulekov obj = qos_machine_new(node, qts);
106f62a0bffSAlexander Bulekov qos_object_queue_destroy(obj);
107f62a0bffSAlexander Bulekov
108f62a0bffSAlexander Bulekov alloc = get_machine_allocator(obj);
109f62a0bffSAlexander Bulekov if (p_alloc) {
110f62a0bffSAlexander Bulekov *p_alloc = alloc;
111f62a0bffSAlexander Bulekov }
112f62a0bffSAlexander Bulekov
113f62a0bffSAlexander Bulekov for (;;) {
114f62a0bffSAlexander Bulekov if (node->type != QNODE_INTERFACE) {
115f62a0bffSAlexander Bulekov qos_object_start_hw(obj);
116f62a0bffSAlexander Bulekov parent = obj;
117f62a0bffSAlexander Bulekov }
118f62a0bffSAlexander Bulekov
119f62a0bffSAlexander Bulekov /* follow edge and get object for next node constructor */
120f62a0bffSAlexander Bulekov current++;
121f62a0bffSAlexander Bulekov edge = qos_graph_get_edge(path[current - 1], path[current]);
122f62a0bffSAlexander Bulekov node = qos_graph_get_node(path[current]);
123f62a0bffSAlexander Bulekov
124f62a0bffSAlexander Bulekov if (node->type == QNODE_TEST) {
125f62a0bffSAlexander Bulekov g_assert(qos_graph_edge_get_type(edge) == QEDGE_CONSUMED_BY);
126f62a0bffSAlexander Bulekov return obj;
127f62a0bffSAlexander Bulekov }
128f62a0bffSAlexander Bulekov
129f62a0bffSAlexander Bulekov switch (qos_graph_edge_get_type(edge)) {
130f62a0bffSAlexander Bulekov case QEDGE_PRODUCES:
131f62a0bffSAlexander Bulekov obj = parent->get_driver(parent, path[current]);
132f62a0bffSAlexander Bulekov break;
133f62a0bffSAlexander Bulekov
134f62a0bffSAlexander Bulekov case QEDGE_CONSUMED_BY:
135f62a0bffSAlexander Bulekov edge_arg = qos_graph_edge_get_arg(edge);
136f62a0bffSAlexander Bulekov obj = qos_driver_new(node, obj, alloc, edge_arg);
137f62a0bffSAlexander Bulekov qos_object_queue_destroy(obj);
138f62a0bffSAlexander Bulekov break;
139f62a0bffSAlexander Bulekov
140f62a0bffSAlexander Bulekov case QEDGE_CONTAINS:
141f62a0bffSAlexander Bulekov obj = parent->get_device(parent, path[current]);
142f62a0bffSAlexander Bulekov break;
143f62a0bffSAlexander Bulekov }
144f62a0bffSAlexander Bulekov }
145f62a0bffSAlexander Bulekov }
146f62a0bffSAlexander Bulekov
147