qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio
at master 435 lines 13 kB view raw
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 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#include "qemu/osdep.h" 20#include "libqtest.h" 21#include "libqos/qgraph.h" 22#include "libqos/qgraph_internal.h" 23 24#define MACHINE_PC "x86_64/pc" 25#define MACHINE_RASPI2 "arm/raspi2" 26#define I440FX "i440FX-pcihost" 27#define PCIBUS_PC "pcibus-pc" 28#define SDHCI "sdhci" 29#define PCIBUS "pci-bus" 30#define SDHCI_PCI "sdhci-pci" 31#define SDHCI_MM "generic-sdhci" 32#define REGISTER_TEST "register-test" 33 34int npath; 35 36static void *machinefunct(QTestState *qts) 37{ 38 return NULL; 39} 40 41static void *driverfunct(void *obj, QGuestAllocator *machine, void *arg) 42{ 43 return NULL; 44} 45 46static void testfunct(void *obj, void *arg, QGuestAllocator *alloc) 47{ 48 return; 49} 50 51static void check_interface(const char *interface) 52{ 53 g_assert_cmpint(qos_graph_has_machine(interface), ==, FALSE); 54 g_assert_nonnull(qos_graph_get_node(interface)); 55 g_assert_cmpint(qos_graph_has_node(interface), ==, TRUE); 56 g_assert_cmpint(qos_graph_get_node_type(interface), ==, QNODE_INTERFACE); 57 qos_graph_node_set_availability(interface, TRUE); 58 g_assert_cmpint(qos_graph_get_node_availability(interface), ==, TRUE); 59} 60 61static void check_machine(const char *machine) 62{ 63 qos_node_create_machine(machine, machinefunct); 64 g_assert_nonnull(qos_graph_get_machine(machine)); 65 g_assert_cmpint(qos_graph_has_machine(machine), ==, TRUE); 66 g_assert_nonnull(qos_graph_get_node(machine)); 67 g_assert_cmpint(qos_graph_get_node_availability(machine), ==, FALSE); 68 qos_graph_node_set_availability(machine, TRUE); 69 g_assert_cmpint(qos_graph_get_node_availability(machine), ==, TRUE); 70 g_assert_cmpint(qos_graph_has_node(machine), ==, TRUE); 71 g_assert_cmpint(qos_graph_get_node_type(machine), ==, QNODE_MACHINE); 72} 73 74static void check_contains(const char *machine, const char *driver) 75{ 76 QOSGraphEdge *edge; 77 qos_node_contains(machine, driver, NULL); 78 79 edge = qos_graph_get_edge(machine, driver); 80 g_assert_nonnull(edge); 81 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, QEDGE_CONTAINS); 82 g_assert_cmpint(qos_graph_has_edge(machine, driver), ==, TRUE); 83} 84 85static void check_produces(const char *machine, const char *interface) 86{ 87 QOSGraphEdge *edge; 88 89 qos_node_produces(machine, interface); 90 check_interface(interface); 91 edge = qos_graph_get_edge(machine, interface); 92 g_assert_nonnull(edge); 93 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, 94 QEDGE_PRODUCES); 95 g_assert_cmpint(qos_graph_has_edge(machine, interface), ==, TRUE); 96} 97 98static void check_consumes(const char *driver, const char *interface) 99{ 100 QOSGraphEdge *edge; 101 102 qos_node_consumes(driver, interface, NULL); 103 check_interface(interface); 104 edge = qos_graph_get_edge(interface, driver); 105 g_assert_nonnull(edge); 106 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, QEDGE_CONSUMED_BY); 107 g_assert_cmpint(qos_graph_has_edge(interface, driver), ==, TRUE); 108} 109 110static void check_driver(const char *driver) 111{ 112 qos_node_create_driver(driver, driverfunct); 113 g_assert_cmpint(qos_graph_has_machine(driver), ==, FALSE); 114 g_assert_nonnull(qos_graph_get_node(driver)); 115 g_assert_cmpint(qos_graph_has_node(driver), ==, TRUE); 116 g_assert_cmpint(qos_graph_get_node_type(driver), ==, QNODE_DRIVER); 117 g_assert_cmpint(qos_graph_get_node_availability(driver), ==, FALSE); 118 qos_graph_node_set_availability(driver, TRUE); 119 g_assert_cmpint(qos_graph_get_node_availability(driver), ==, TRUE); 120} 121 122static void check_test(const char *test, const char *interface) 123{ 124 QOSGraphEdge *edge; 125 char *full_name = g_strdup_printf("%s-tests/%s", interface, test); 126 127 qos_add_test(test, interface, testfunct, NULL); 128 g_assert_cmpint(qos_graph_has_machine(test), ==, FALSE); 129 g_assert_cmpint(qos_graph_has_machine(full_name), ==, FALSE); 130 g_assert_nonnull(qos_graph_get_node(full_name)); 131 g_assert_cmpint(qos_graph_has_node(full_name), ==, TRUE); 132 g_assert_cmpint(qos_graph_get_node_type(full_name), ==, QNODE_TEST); 133 edge = qos_graph_get_edge(interface, full_name); 134 g_assert_nonnull(edge); 135 g_assert_cmpint(qos_graph_edge_get_type(edge), ==, 136 QEDGE_CONSUMED_BY); 137 g_assert_cmpint(qos_graph_has_edge(interface, full_name), ==, TRUE); 138 g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, TRUE); 139 qos_graph_node_set_availability(full_name, FALSE); 140 g_assert_cmpint(qos_graph_get_node_availability(full_name), ==, FALSE); 141 g_free(full_name); 142} 143 144static void count_each_test(QOSGraphNode *path, int len) 145{ 146 npath++; 147} 148 149static void check_leaf_discovered(int n) 150{ 151 npath = 0; 152 qos_graph_foreach_test_path(count_each_test); 153 g_assert_cmpint(n, ==, npath); 154} 155 156/* G_Test functions */ 157 158static void init_nop(void) 159{ 160 qos_graph_init(); 161 qos_graph_destroy(); 162} 163 164static void test_machine(void) 165{ 166 qos_graph_init(); 167 check_machine(MACHINE_PC); 168 qos_graph_destroy(); 169} 170 171static void test_contains(void) 172{ 173 qos_graph_init(); 174 check_contains(MACHINE_PC, I440FX); 175 g_assert_null(qos_graph_get_machine(MACHINE_PC)); 176 g_assert_null(qos_graph_get_machine(I440FX)); 177 g_assert_null(qos_graph_get_node(MACHINE_PC)); 178 g_assert_null(qos_graph_get_node(I440FX)); 179 qos_graph_destroy(); 180} 181 182static void test_multiple_contains(void) 183{ 184 qos_graph_init(); 185 check_contains(MACHINE_PC, I440FX); 186 check_contains(MACHINE_PC, PCIBUS_PC); 187 qos_graph_destroy(); 188} 189 190static void test_produces(void) 191{ 192 qos_graph_init(); 193 check_produces(MACHINE_PC, I440FX); 194 g_assert_null(qos_graph_get_machine(MACHINE_PC)); 195 g_assert_null(qos_graph_get_machine(I440FX)); 196 g_assert_null(qos_graph_get_node(MACHINE_PC)); 197 g_assert_nonnull(qos_graph_get_node(I440FX)); 198 qos_graph_destroy(); 199} 200 201static void test_multiple_produces(void) 202{ 203 qos_graph_init(); 204 check_produces(MACHINE_PC, I440FX); 205 check_produces(MACHINE_PC, PCIBUS_PC); 206 qos_graph_destroy(); 207} 208 209static void test_consumes(void) 210{ 211 qos_graph_init(); 212 check_consumes(I440FX, SDHCI); 213 g_assert_null(qos_graph_get_machine(I440FX)); 214 g_assert_null(qos_graph_get_machine(SDHCI)); 215 g_assert_null(qos_graph_get_node(I440FX)); 216 g_assert_nonnull(qos_graph_get_node(SDHCI)); 217 qos_graph_destroy(); 218} 219 220static void test_multiple_consumes(void) 221{ 222 qos_graph_init(); 223 check_consumes(I440FX, SDHCI); 224 check_consumes(PCIBUS_PC, SDHCI); 225 qos_graph_destroy(); 226} 227 228static void test_driver(void) 229{ 230 qos_graph_init(); 231 check_driver(I440FX); 232 qos_graph_destroy(); 233} 234 235static void test_test(void) 236{ 237 qos_graph_init(); 238 check_test(REGISTER_TEST, SDHCI); 239 qos_graph_destroy(); 240} 241 242static void test_machine_contains_driver(void) 243{ 244 qos_graph_init(); 245 check_machine(MACHINE_PC); 246 check_driver(I440FX); 247 check_contains(MACHINE_PC, I440FX); 248 qos_graph_destroy(); 249} 250 251static void test_driver_contains_driver(void) 252{ 253 qos_graph_init(); 254 check_driver(PCIBUS_PC); 255 check_driver(I440FX); 256 check_contains(PCIBUS_PC, I440FX); 257 qos_graph_destroy(); 258} 259 260static void test_machine_produces_interface(void) 261{ 262 qos_graph_init(); 263 check_machine(MACHINE_PC); 264 check_produces(MACHINE_PC, SDHCI); 265 qos_graph_destroy(); 266} 267 268static void test_driver_produces_interface(void) 269{ 270 qos_graph_init(); 271 check_driver(I440FX); 272 check_produces(I440FX, SDHCI); 273 qos_graph_destroy(); 274} 275 276static void test_machine_consumes_interface(void) 277{ 278 qos_graph_init(); 279 check_machine(MACHINE_PC); 280 check_consumes(MACHINE_PC, SDHCI); 281 qos_graph_destroy(); 282} 283 284static void test_driver_consumes_interface(void) 285{ 286 qos_graph_init(); 287 check_driver(I440FX); 288 check_consumes(I440FX, SDHCI); 289 qos_graph_destroy(); 290} 291 292static void test_test_consumes_interface(void) 293{ 294 qos_graph_init(); 295 check_test(REGISTER_TEST, SDHCI); 296 qos_graph_destroy(); 297} 298 299static void test_full_sample(void) 300{ 301 qos_graph_init(); 302 check_machine(MACHINE_PC); 303 check_contains(MACHINE_PC, I440FX); 304 check_driver(I440FX); 305 check_driver(PCIBUS_PC); 306 check_contains(I440FX, PCIBUS_PC); 307 check_produces(PCIBUS_PC, PCIBUS); 308 check_driver(SDHCI_PCI); 309 qos_node_consumes(SDHCI_PCI, PCIBUS, NULL); 310 check_produces(SDHCI_PCI, SDHCI); 311 check_driver(SDHCI_MM); 312 check_produces(SDHCI_MM, SDHCI); 313 qos_add_test(REGISTER_TEST, SDHCI, testfunct, NULL); 314 check_leaf_discovered(1); 315 qos_print_graph(); 316 qos_graph_destroy(); 317} 318 319static void test_full_sample_raspi(void) 320{ 321 qos_graph_init(); 322 check_machine(MACHINE_PC); 323 check_contains(MACHINE_PC, I440FX); 324 check_driver(I440FX); 325 check_driver(PCIBUS_PC); 326 check_contains(I440FX, PCIBUS_PC); 327 check_produces(PCIBUS_PC, PCIBUS); 328 check_driver(SDHCI_PCI); 329 qos_node_consumes(SDHCI_PCI, PCIBUS, NULL); 330 check_produces(SDHCI_PCI, SDHCI); 331 check_machine(MACHINE_RASPI2); 332 check_contains(MACHINE_RASPI2, SDHCI_MM); 333 check_driver(SDHCI_MM); 334 check_produces(SDHCI_MM, SDHCI); 335 qos_add_test(REGISTER_TEST, SDHCI, testfunct, NULL); 336 qos_print_graph(); 337 check_leaf_discovered(2); 338 qos_graph_destroy(); 339} 340 341static void test_cycle(void) 342{ 343 qos_graph_init(); 344 check_machine(MACHINE_RASPI2); 345 check_driver("B"); 346 check_driver("C"); 347 check_driver("D"); 348 check_contains(MACHINE_RASPI2, "B"); 349 check_contains("B", "C"); 350 check_contains("C", "D"); 351 check_contains("D", MACHINE_RASPI2); 352 check_leaf_discovered(0); 353 qos_print_graph(); 354 qos_graph_destroy(); 355} 356 357static void test_two_test_same_interface(void) 358{ 359 qos_graph_init(); 360 check_machine(MACHINE_RASPI2); 361 check_produces(MACHINE_RASPI2, "B"); 362 qos_add_test("C", "B", testfunct, NULL); 363 qos_add_test("D", "B", testfunct, NULL); 364 check_contains(MACHINE_RASPI2, "B"); 365 check_leaf_discovered(4); 366 qos_print_graph(); 367 qos_graph_destroy(); 368} 369 370static void test_test_in_path(void) 371{ 372 qos_graph_init(); 373 check_machine(MACHINE_RASPI2); 374 check_produces(MACHINE_RASPI2, "B"); 375 qos_add_test("C", "B", testfunct, NULL); 376 check_driver("D"); 377 check_consumes("D", "B"); 378 check_produces("D", "E"); 379 qos_add_test("F", "E", testfunct, NULL); 380 check_leaf_discovered(2); 381 qos_print_graph(); 382 qos_graph_destroy(); 383} 384 385static void test_double_edge(void) 386{ 387 qos_graph_init(); 388 check_machine(MACHINE_RASPI2); 389 check_produces("B", "C"); 390 qos_node_consumes("C", "B", NULL); 391 qos_add_test("D", "C", testfunct, NULL); 392 check_contains(MACHINE_RASPI2, "B"); 393 qos_print_graph(); 394 qos_graph_destroy(); 395} 396 397int main(int argc, char **argv) 398{ 399 g_test_init(&argc, &argv, NULL); 400 g_test_add_func("/qgraph/init_nop", init_nop); 401 g_test_add_func("/qgraph/test_machine", test_machine); 402 g_test_add_func("/qgraph/test_contains", test_contains); 403 g_test_add_func("/qgraph/test_multiple_contains", test_multiple_contains); 404 g_test_add_func("/qgraph/test_produces", test_produces); 405 g_test_add_func("/qgraph/test_multiple_produces", test_multiple_produces); 406 g_test_add_func("/qgraph/test_consumes", test_consumes); 407 g_test_add_func("/qgraph/test_multiple_consumes", 408 test_multiple_consumes); 409 g_test_add_func("/qgraph/test_driver", test_driver); 410 g_test_add_func("/qgraph/test_test", test_test); 411 g_test_add_func("/qgraph/test_machine_contains_driver", 412 test_machine_contains_driver); 413 g_test_add_func("/qgraph/test_driver_contains_driver", 414 test_driver_contains_driver); 415 g_test_add_func("/qgraph/test_machine_produces_interface", 416 test_machine_produces_interface); 417 g_test_add_func("/qgraph/test_driver_produces_interface", 418 test_driver_produces_interface); 419 g_test_add_func("/qgraph/test_machine_consumes_interface", 420 test_machine_consumes_interface); 421 g_test_add_func("/qgraph/test_driver_consumes_interface", 422 test_driver_consumes_interface); 423 g_test_add_func("/qgraph/test_test_consumes_interface", 424 test_test_consumes_interface); 425 g_test_add_func("/qgraph/test_full_sample", test_full_sample); 426 g_test_add_func("/qgraph/test_full_sample_raspi", test_full_sample_raspi); 427 g_test_add_func("/qgraph/test_cycle", test_cycle); 428 g_test_add_func("/qgraph/test_two_test_same_interface", 429 test_two_test_same_interface); 430 g_test_add_func("/qgraph/test_test_in_path", test_test_in_path); 431 g_test_add_func("/qgraph/test_double_edge", test_double_edge); 432 433 g_test_run(); 434 return 0; 435}