2 * QTest testcase for VirtIO Block Device
4 * Copyright (c) 2014 SUSE LINUX Products GmbH
5 * Copyright (c) 2014 Marc MarĂ
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
11 #include "qemu/osdep.h"
13 #include "libqos/libqos-pc.h"
14 #include "libqos/libqos-spapr.h"
15 #include "libqos/virtio.h"
16 #include "libqos/virtio-pci.h"
17 #include "libqos/virtio-mmio.h"
18 #include "libqos/malloc-generic.h"
19 #include "qapi/qmp/qdict.h"
20 #include "qemu/bswap.h"
21 #include "standard-headers/linux/virtio_ids.h"
22 #include "standard-headers/linux/virtio_config.h"
23 #include "standard-headers/linux/virtio_ring.h"
24 #include "standard-headers/linux/virtio_blk.h"
25 #include "standard-headers/linux/virtio_pci.h"
27 /* TODO actually test the results and get rid of this */
28 #define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__))
30 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
31 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
32 #define PCI_SLOT_HP 0x06
36 #define MMIO_PAGE_SIZE 4096
37 #define MMIO_DEV_BASE_ADDR 0x0A003E00
38 #define MMIO_RAM_ADDR 0x40000000
39 #define MMIO_RAM_SIZE 0x20000000
41 typedef struct QVirtioBlkReq {
49 static char *drive_create(void)
52 char *tmp_path = g_strdup("/tmp/qtest.XXXXXX");
54 /* Create a temporary raw image */
55 fd = mkstemp(tmp_path);
56 g_assert_cmpint(fd, >=, 0);
57 ret = ftruncate(fd, TEST_IMAGE_SIZE);
58 g_assert_cmpint(ret, ==, 0);
64 static QOSState *pci_test_start(void)
67 const char *arch = qtest_get_arch();
69 const char *cmd = "-drive if=none,id=drive0,file=%s,format=raw "
70 "-drive if=none,id=drive1,file=null-co://,format=raw "
71 "-device virtio-blk-pci,id=drv0,drive=drive0,"
74 tmp_path = drive_create();
76 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
77 qs = qtest_pc_boot(cmd, tmp_path, PCI_SLOT, PCI_FN);
78 } else if (strcmp(arch, "ppc64") == 0) {
79 qs = qtest_spapr_boot(cmd, tmp_path, PCI_SLOT, PCI_FN);
81 g_printerr("virtio-blk tests are only available on x86 or ppc64\n");
84 global_qtest = qs->qts;
90 static void arm_test_start(void)
94 tmp_path = drive_create();
96 global_qtest = qtest_initf("-machine virt "
97 "-drive if=none,id=drive0,file=%s,format=raw "
98 "-device virtio-blk-device,drive=drive0",
104 static void test_end(void)
109 static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
111 QVirtioPCIDevice *dev;
113 dev = qvirtio_pci_device_find_slot(bus, VIRTIO_ID_BLOCK, slot);
114 g_assert(dev != NULL);
115 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
116 g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN));
118 qvirtio_pci_device_enable(dev);
119 qvirtio_reset(&dev->vdev);
120 qvirtio_set_acknowledge(&dev->vdev);
121 qvirtio_set_driver(&dev->vdev);
126 static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
128 #ifdef HOST_WORDS_BIGENDIAN
129 const bool host_is_big_endian = true;
131 const bool host_is_big_endian = false;
134 if (qvirtio_is_big_endian(d) != host_is_big_endian) {
135 req->type = bswap32(req->type);
136 req->ioprio = bswap32(req->ioprio);
137 req->sector = bswap64(req->sector);
141 static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
142 QVirtioBlkReq *req, uint64_t data_size)
145 uint8_t status = 0xFF;
147 g_assert_cmpuint(data_size % 512, ==, 0);
148 addr = guest_alloc(alloc, sizeof(*req) + data_size);
150 virtio_blk_fix_request(d, req);
152 memwrite(addr, req, 16);
153 memwrite(addr + 16, req->data, data_size);
154 memwrite(addr + 16 + data_size, &status, sizeof(status));
159 static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
170 capacity = qvirtio_config_readq(dev, 0);
172 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
174 features = qvirtio_get_features(dev);
175 features = features & ~(QVIRTIO_F_BAD_FEATURE |
176 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
177 (1u << VIRTIO_RING_F_EVENT_IDX) |
178 (1u << VIRTIO_BLK_F_SCSI));
179 qvirtio_set_features(dev, features);
181 qvirtio_set_driver_ok(dev);
183 /* Write and read with 3 descriptor layout */
185 req.type = VIRTIO_BLK_T_OUT;
188 req.data = g_malloc0(512);
189 strcpy(req.data, "TEST");
191 req_addr = virtio_blk_request(alloc, dev, &req, 512);
195 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
196 qvirtqueue_add(vq, req_addr + 16, 512, false, true);
197 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
199 qvirtqueue_kick(dev, vq, free_head);
201 qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
202 status = readb(req_addr + 528);
203 g_assert_cmpint(status, ==, 0);
205 guest_free(alloc, req_addr);
208 req.type = VIRTIO_BLK_T_IN;
211 req.data = g_malloc0(512);
213 req_addr = virtio_blk_request(alloc, dev, &req, 512);
217 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
218 qvirtqueue_add(vq, req_addr + 16, 512, true, true);
219 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
221 qvirtqueue_kick(dev, vq, free_head);
223 qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
224 status = readb(req_addr + 528);
225 g_assert_cmpint(status, ==, 0);
227 data = g_malloc0(512);
228 memread(req_addr + 16, data, 512);
229 g_assert_cmpstr(data, ==, "TEST");
232 guest_free(alloc, req_addr);
234 if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
235 /* Write and read with 2 descriptor layout */
237 req.type = VIRTIO_BLK_T_OUT;
240 req.data = g_malloc0(512);
241 strcpy(req.data, "TEST");
243 req_addr = virtio_blk_request(alloc, dev, &req, 512);
247 free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
248 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
249 qvirtqueue_kick(dev, vq, free_head);
251 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
252 QVIRTIO_BLK_TIMEOUT_US);
253 status = readb(req_addr + 528);
254 g_assert_cmpint(status, ==, 0);
256 guest_free(alloc, req_addr);
259 req.type = VIRTIO_BLK_T_IN;
262 req.data = g_malloc0(512);
264 req_addr = virtio_blk_request(alloc, dev, &req, 512);
268 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
269 qvirtqueue_add(vq, req_addr + 16, 513, true, false);
271 qvirtqueue_kick(dev, vq, free_head);
273 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
274 QVIRTIO_BLK_TIMEOUT_US);
275 status = readb(req_addr + 528);
276 g_assert_cmpint(status, ==, 0);
278 data = g_malloc0(512);
279 memread(req_addr + 16, data, 512);
280 g_assert_cmpstr(data, ==, "TEST");
283 guest_free(alloc, req_addr);
287 static void pci_basic(void)
289 QVirtioPCIDevice *dev;
291 QVirtQueuePCI *vqpci;
293 qs = pci_test_start();
294 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
296 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
298 test_basic(&dev->vdev, qs->alloc, &vqpci->vq);
301 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
302 qvirtio_pci_device_disable(dev);
303 qvirtio_pci_device_free(dev);
307 static void pci_indirect(void)
309 QVirtioPCIDevice *dev;
310 QVirtQueuePCI *vqpci;
313 QVRingIndirectDesc *indirect;
321 qs = pci_test_start();
323 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
325 capacity = qvirtio_config_readq(&dev->vdev, 0);
326 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
328 features = qvirtio_get_features(&dev->vdev);
329 g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
330 features = features & ~(QVIRTIO_F_BAD_FEATURE |
331 (1u << VIRTIO_RING_F_EVENT_IDX) |
332 (1u << VIRTIO_BLK_F_SCSI));
333 qvirtio_set_features(&dev->vdev, features);
335 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
336 qvirtio_set_driver_ok(&dev->vdev);
339 req.type = VIRTIO_BLK_T_OUT;
342 req.data = g_malloc0(512);
343 strcpy(req.data, "TEST");
345 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
349 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
350 qvring_indirect_desc_add(indirect, req_addr, 528, false);
351 qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
352 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
353 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
355 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
356 QVIRTIO_BLK_TIMEOUT_US);
357 status = readb(req_addr + 528);
358 g_assert_cmpint(status, ==, 0);
361 guest_free(qs->alloc, req_addr);
364 req.type = VIRTIO_BLK_T_IN;
367 req.data = g_malloc0(512);
368 strcpy(req.data, "TEST");
370 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
374 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
375 qvring_indirect_desc_add(indirect, req_addr, 16, false);
376 qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
377 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
378 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
380 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
381 QVIRTIO_BLK_TIMEOUT_US);
382 status = readb(req_addr + 528);
383 g_assert_cmpint(status, ==, 0);
385 data = g_malloc0(512);
386 memread(req_addr + 16, data, 512);
387 g_assert_cmpstr(data, ==, "TEST");
391 guest_free(qs->alloc, req_addr);
394 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
395 qvirtio_pci_device_disable(dev);
396 qvirtio_pci_device_free(dev);
400 static void pci_config(void)
402 QVirtioPCIDevice *dev;
404 int n_size = TEST_IMAGE_SIZE / 2;
407 qs = pci_test_start();
409 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
411 capacity = qvirtio_config_readq(&dev->vdev, 0);
412 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
414 qvirtio_set_driver_ok(&dev->vdev);
416 qmp_discard_response("{ 'execute': 'block_resize', "
417 " 'arguments': { 'device': 'drive0', "
418 " 'size': %d } }", n_size);
419 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
421 capacity = qvirtio_config_readq(&dev->vdev, 0);
422 g_assert_cmpint(capacity, ==, n_size / 512);
424 qvirtio_pci_device_disable(dev);
425 qvirtio_pci_device_free(dev);
430 static void pci_msix(void)
432 QVirtioPCIDevice *dev;
434 QVirtQueuePCI *vqpci;
436 int n_size = TEST_IMAGE_SIZE / 2;
444 qs = pci_test_start();
446 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
447 qpci_msix_enable(dev->pdev);
449 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
451 capacity = qvirtio_config_readq(&dev->vdev, 0);
452 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
454 features = qvirtio_get_features(&dev->vdev);
455 features = features & ~(QVIRTIO_F_BAD_FEATURE |
456 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
457 (1u << VIRTIO_RING_F_EVENT_IDX) |
458 (1u << VIRTIO_BLK_F_SCSI));
459 qvirtio_set_features(&dev->vdev, features);
461 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
462 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
464 qvirtio_set_driver_ok(&dev->vdev);
466 qmp_discard_response("{ 'execute': 'block_resize', "
467 " 'arguments': { 'device': 'drive0', "
468 " 'size': %d } }", n_size);
470 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
472 capacity = qvirtio_config_readq(&dev->vdev, 0);
473 g_assert_cmpint(capacity, ==, n_size / 512);
476 req.type = VIRTIO_BLK_T_OUT;
479 req.data = g_malloc0(512);
480 strcpy(req.data, "TEST");
482 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
486 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
487 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
488 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
489 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
491 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
492 QVIRTIO_BLK_TIMEOUT_US);
494 status = readb(req_addr + 528);
495 g_assert_cmpint(status, ==, 0);
497 guest_free(qs->alloc, req_addr);
500 req.type = VIRTIO_BLK_T_IN;
503 req.data = g_malloc0(512);
505 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
509 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
510 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
511 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
513 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
516 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
517 QVIRTIO_BLK_TIMEOUT_US);
519 status = readb(req_addr + 528);
520 g_assert_cmpint(status, ==, 0);
522 data = g_malloc0(512);
523 memread(req_addr + 16, data, 512);
524 g_assert_cmpstr(data, ==, "TEST");
527 guest_free(qs->alloc, req_addr);
530 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
531 qpci_msix_disable(dev->pdev);
532 qvirtio_pci_device_disable(dev);
533 qvirtio_pci_device_free(dev);
537 static void pci_idx(void)
539 QVirtioPCIDevice *dev;
541 QVirtQueuePCI *vqpci;
552 qs = pci_test_start();
554 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
555 qpci_msix_enable(dev->pdev);
557 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
559 capacity = qvirtio_config_readq(&dev->vdev, 0);
560 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
562 features = qvirtio_get_features(&dev->vdev);
563 features = features & ~(QVIRTIO_F_BAD_FEATURE |
564 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
565 (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
566 (1u << VIRTIO_BLK_F_SCSI));
567 qvirtio_set_features(&dev->vdev, features);
569 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
570 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
572 qvirtio_set_driver_ok(&dev->vdev);
575 req.type = VIRTIO_BLK_T_OUT;
578 req.data = g_malloc0(512);
579 strcpy(req.data, "TEST");
581 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
585 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
586 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
587 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
588 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
590 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
591 QVIRTIO_BLK_TIMEOUT_US);
594 req.type = VIRTIO_BLK_T_OUT;
597 req.data = g_malloc0(512);
598 strcpy(req.data, "TEST");
600 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
604 /* Notify after processing the third request */
605 qvirtqueue_set_used_event(&vqpci->vq, 2);
606 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
607 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
608 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
609 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
610 write_head = free_head;
612 /* No notification expected */
613 status = qvirtio_wait_status_byte_no_isr(&dev->vdev,
614 &vqpci->vq, req_addr + 528,
615 QVIRTIO_BLK_TIMEOUT_US);
616 g_assert_cmpint(status, ==, 0);
618 guest_free(qs->alloc, req_addr);
621 req.type = VIRTIO_BLK_T_IN;
624 req.data = g_malloc0(512);
626 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
630 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
631 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
632 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
634 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
636 /* We get just one notification for both requests */
637 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head, NULL,
638 QVIRTIO_BLK_TIMEOUT_US);
639 g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx, NULL));
640 g_assert_cmpint(desc_idx, ==, free_head);
642 status = readb(req_addr + 528);
643 g_assert_cmpint(status, ==, 0);
645 data = g_malloc0(512);
646 memread(req_addr + 16, data, 512);
647 g_assert_cmpstr(data, ==, "TEST");
650 guest_free(qs->alloc, req_addr);
653 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
654 qpci_msix_disable(dev->pdev);
655 qvirtio_pci_device_disable(dev);
656 qvirtio_pci_device_free(dev);
660 static void pci_hotplug(void)
662 QVirtioPCIDevice *dev;
664 const char *arch = qtest_get_arch();
666 qs = pci_test_start();
668 /* plug secondary disk */
669 qtest_qmp_device_add("virtio-blk-pci", "drv1",
670 "{'addr': %s, 'drive': 'drive1'}",
671 stringify(PCI_SLOT_HP));
673 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT_HP);
675 qvirtio_pci_device_disable(dev);
676 qvirtio_pci_device_free(dev);
678 /* unplug secondary disk */
679 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
680 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
686 * Check that setting the vring addr on a non-existent virtqueue does
689 static void test_nonexistent_virtqueue(void)
695 qs = pci_test_start();
696 dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4, 0));
697 g_assert(dev != NULL);
699 qpci_device_enable(dev);
700 bar0 = qpci_iomap(dev, 0, NULL);
702 qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2);
703 qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1);
709 static void mmio_basic(void)
711 QVirtioMMIODevice *dev;
713 QGuestAllocator *alloc;
714 int n_size = TEST_IMAGE_SIZE / 2;
719 dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
720 g_assert(dev != NULL);
721 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
723 qvirtio_reset(&dev->vdev);
724 qvirtio_set_acknowledge(&dev->vdev);
725 qvirtio_set_driver(&dev->vdev);
727 alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
728 vq = qvirtqueue_setup(&dev->vdev, alloc, 0);
730 test_basic(&dev->vdev, alloc, vq);
732 qmp_discard_response("{ 'execute': 'block_resize', "
733 " 'arguments': { 'device': 'drive0', "
734 " 'size': %d } }", n_size);
736 qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US);
738 capacity = qvirtio_config_readq(&dev->vdev, 0);
739 g_assert_cmpint(capacity, ==, n_size / 512);
742 qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
744 generic_alloc_uninit(alloc);
748 int main(int argc, char **argv)
750 const char *arch = qtest_get_arch();
752 g_test_init(&argc, &argv, NULL);
754 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0 ||
755 strcmp(arch, "ppc64") == 0) {
756 qtest_add_func("/virtio/blk/pci/basic", pci_basic);
757 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
758 qtest_add_func("/virtio/blk/pci/config", pci_config);
759 qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue);
760 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
761 qtest_add_func("/virtio/blk/pci/msix", pci_msix);
762 qtest_add_func("/virtio/blk/pci/idx", pci_idx);
764 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
765 } else if (strcmp(arch, "arm") == 0) {
766 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);