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;
148 case VIRTIO_BLK_T_IN
:
149 case VIRTIO_BLK_T_OUT
:
150 g_assert_cmpuint(data_size
% 512, ==, 0);
152 case VIRTIO_BLK_T_DISCARD
:
153 case VIRTIO_BLK_T_WRITE_ZEROES
:
154 g_assert_cmpuint(data_size
%
155 sizeof(struct virtio_blk_discard_write_zeroes
), ==, 0);
158 g_assert_cmpuint(data_size
, ==, 0);
161 addr
= guest_alloc(alloc
, sizeof(*req
) + data_size
);
163 virtio_blk_fix_request(d
, req
);
165 memwrite(addr
, req
, 16);
166 memwrite(addr
+ 16, req
->data
, data_size
);
167 memwrite(addr
+ 16 + data_size
, &status
, sizeof(status
));
172 static void test_basic(QVirtioDevice
*dev
, QGuestAllocator
*alloc
,
183 capacity
= qvirtio_config_readq(dev
, 0);
185 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
187 features
= qvirtio_get_features(dev
);
188 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
189 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
190 (1u << VIRTIO_RING_F_EVENT_IDX
) |
191 (1u << VIRTIO_BLK_F_SCSI
));
192 qvirtio_set_features(dev
, features
);
194 qvirtio_set_driver_ok(dev
);
196 /* Write and read with 3 descriptor layout */
198 req
.type
= VIRTIO_BLK_T_OUT
;
201 req
.data
= g_malloc0(512);
202 strcpy(req
.data
, "TEST");
204 req_addr
= virtio_blk_request(alloc
, dev
, &req
, 512);
208 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
209 qvirtqueue_add(vq
, req_addr
+ 16, 512, false, true);
210 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
212 qvirtqueue_kick(dev
, vq
, free_head
);
214 qvirtio_wait_used_elem(dev
, vq
, free_head
, NULL
, QVIRTIO_BLK_TIMEOUT_US
);
215 status
= readb(req_addr
+ 528);
216 g_assert_cmpint(status
, ==, 0);
218 guest_free(alloc
, req_addr
);
221 req
.type
= VIRTIO_BLK_T_IN
;
224 req
.data
= g_malloc0(512);
226 req_addr
= virtio_blk_request(alloc
, dev
, &req
, 512);
230 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
231 qvirtqueue_add(vq
, req_addr
+ 16, 512, true, true);
232 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
234 qvirtqueue_kick(dev
, vq
, free_head
);
236 qvirtio_wait_used_elem(dev
, vq
, free_head
, NULL
, QVIRTIO_BLK_TIMEOUT_US
);
237 status
= readb(req_addr
+ 528);
238 g_assert_cmpint(status
, ==, 0);
240 data
= g_malloc0(512);
241 memread(req_addr
+ 16, data
, 512);
242 g_assert_cmpstr(data
, ==, "TEST");
245 guest_free(alloc
, req_addr
);
247 if (features
& (1u << VIRTIO_F_ANY_LAYOUT
)) {
248 /* Write and read with 2 descriptor layout */
250 req
.type
= VIRTIO_BLK_T_OUT
;
253 req
.data
= g_malloc0(512);
254 strcpy(req
.data
, "TEST");
256 req_addr
= virtio_blk_request(alloc
, dev
, &req
, 512);
260 free_head
= qvirtqueue_add(vq
, req_addr
, 528, false, true);
261 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
262 qvirtqueue_kick(dev
, vq
, free_head
);
264 qvirtio_wait_used_elem(dev
, vq
, free_head
, NULL
,
265 QVIRTIO_BLK_TIMEOUT_US
);
266 status
= readb(req_addr
+ 528);
267 g_assert_cmpint(status
, ==, 0);
269 guest_free(alloc
, req_addr
);
272 req
.type
= VIRTIO_BLK_T_IN
;
275 req
.data
= g_malloc0(512);
277 req_addr
= virtio_blk_request(alloc
, dev
, &req
, 512);
281 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
282 qvirtqueue_add(vq
, req_addr
+ 16, 513, true, false);
284 qvirtqueue_kick(dev
, vq
, free_head
);
286 qvirtio_wait_used_elem(dev
, vq
, free_head
, NULL
,
287 QVIRTIO_BLK_TIMEOUT_US
);
288 status
= readb(req_addr
+ 528);
289 g_assert_cmpint(status
, ==, 0);
291 data
= g_malloc0(512);
292 memread(req_addr
+ 16, data
, 512);
293 g_assert_cmpstr(data
, ==, "TEST");
296 guest_free(alloc
, req_addr
);
300 static void pci_basic(void)
302 QVirtioPCIDevice
*dev
;
304 QVirtQueuePCI
*vqpci
;
306 qs
= pci_test_start();
307 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
309 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&dev
->vdev
, qs
->alloc
, 0);
311 test_basic(&dev
->vdev
, qs
->alloc
, &vqpci
->vq
);
314 qvirtqueue_cleanup(dev
->vdev
.bus
, &vqpci
->vq
, qs
->alloc
);
315 qvirtio_pci_device_disable(dev
);
316 qvirtio_pci_device_free(dev
);
320 static void pci_indirect(void)
322 QVirtioPCIDevice
*dev
;
323 QVirtQueuePCI
*vqpci
;
326 QVRingIndirectDesc
*indirect
;
334 qs
= pci_test_start();
336 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
338 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
339 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
341 features
= qvirtio_get_features(&dev
->vdev
);
342 g_assert_cmphex(features
& (1u << VIRTIO_RING_F_INDIRECT_DESC
), !=, 0);
343 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
344 (1u << VIRTIO_RING_F_EVENT_IDX
) |
345 (1u << VIRTIO_BLK_F_SCSI
));
346 qvirtio_set_features(&dev
->vdev
, features
);
348 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&dev
->vdev
, qs
->alloc
, 0);
349 qvirtio_set_driver_ok(&dev
->vdev
);
352 req
.type
= VIRTIO_BLK_T_OUT
;
355 req
.data
= g_malloc0(512);
356 strcpy(req
.data
, "TEST");
358 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
362 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, qs
->alloc
, 2);
363 qvring_indirect_desc_add(indirect
, req_addr
, 528, false);
364 qvring_indirect_desc_add(indirect
, req_addr
+ 528, 1, true);
365 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
366 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
368 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
369 QVIRTIO_BLK_TIMEOUT_US
);
370 status
= readb(req_addr
+ 528);
371 g_assert_cmpint(status
, ==, 0);
374 guest_free(qs
->alloc
, req_addr
);
377 req
.type
= VIRTIO_BLK_T_IN
;
380 req
.data
= g_malloc0(512);
381 strcpy(req
.data
, "TEST");
383 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
387 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, qs
->alloc
, 2);
388 qvring_indirect_desc_add(indirect
, req_addr
, 16, false);
389 qvring_indirect_desc_add(indirect
, req_addr
+ 16, 513, true);
390 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
391 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
393 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
394 QVIRTIO_BLK_TIMEOUT_US
);
395 status
= readb(req_addr
+ 528);
396 g_assert_cmpint(status
, ==, 0);
398 data
= g_malloc0(512);
399 memread(req_addr
+ 16, data
, 512);
400 g_assert_cmpstr(data
, ==, "TEST");
404 guest_free(qs
->alloc
, req_addr
);
407 qvirtqueue_cleanup(dev
->vdev
.bus
, &vqpci
->vq
, qs
->alloc
);
408 qvirtio_pci_device_disable(dev
);
409 qvirtio_pci_device_free(dev
);
413 static void pci_config(void)
415 QVirtioPCIDevice
*dev
;
417 int n_size
= TEST_IMAGE_SIZE
/ 2;
420 qs
= pci_test_start();
422 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
424 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
425 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
427 qvirtio_set_driver_ok(&dev
->vdev
);
429 qmp_discard_response("{ 'execute': 'block_resize', "
430 " 'arguments': { 'device': 'drive0', "
431 " 'size': %d } }", n_size
);
432 qvirtio_wait_config_isr(&dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
434 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
435 g_assert_cmpint(capacity
, ==, n_size
/ 512);
437 qvirtio_pci_device_disable(dev
);
438 qvirtio_pci_device_free(dev
);
443 static void pci_msix(void)
445 QVirtioPCIDevice
*dev
;
447 QVirtQueuePCI
*vqpci
;
449 int n_size
= TEST_IMAGE_SIZE
/ 2;
457 qs
= pci_test_start();
459 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
460 qpci_msix_enable(dev
->pdev
);
462 qvirtio_pci_set_msix_configuration_vector(dev
, qs
->alloc
, 0);
464 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
465 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
467 features
= qvirtio_get_features(&dev
->vdev
);
468 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
469 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
470 (1u << VIRTIO_RING_F_EVENT_IDX
) |
471 (1u << VIRTIO_BLK_F_SCSI
));
472 qvirtio_set_features(&dev
->vdev
, features
);
474 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&dev
->vdev
, qs
->alloc
, 0);
475 qvirtqueue_pci_msix_setup(dev
, vqpci
, qs
->alloc
, 1);
477 qvirtio_set_driver_ok(&dev
->vdev
);
479 qmp_discard_response("{ 'execute': 'block_resize', "
480 " 'arguments': { 'device': 'drive0', "
481 " 'size': %d } }", n_size
);
483 qvirtio_wait_config_isr(&dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
485 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
486 g_assert_cmpint(capacity
, ==, n_size
/ 512);
489 req
.type
= VIRTIO_BLK_T_OUT
;
492 req
.data
= g_malloc0(512);
493 strcpy(req
.data
, "TEST");
495 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
499 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
500 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
501 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
502 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
504 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
505 QVIRTIO_BLK_TIMEOUT_US
);
507 status
= readb(req_addr
+ 528);
508 g_assert_cmpint(status
, ==, 0);
510 guest_free(qs
->alloc
, req_addr
);
513 req
.type
= VIRTIO_BLK_T_IN
;
516 req
.data
= g_malloc0(512);
518 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
522 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
523 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
524 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
526 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
529 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
530 QVIRTIO_BLK_TIMEOUT_US
);
532 status
= readb(req_addr
+ 528);
533 g_assert_cmpint(status
, ==, 0);
535 data
= g_malloc0(512);
536 memread(req_addr
+ 16, data
, 512);
537 g_assert_cmpstr(data
, ==, "TEST");
540 guest_free(qs
->alloc
, req_addr
);
543 qvirtqueue_cleanup(dev
->vdev
.bus
, &vqpci
->vq
, qs
->alloc
);
544 qpci_msix_disable(dev
->pdev
);
545 qvirtio_pci_device_disable(dev
);
546 qvirtio_pci_device_free(dev
);
550 static void pci_idx(void)
552 QVirtioPCIDevice
*dev
;
554 QVirtQueuePCI
*vqpci
;
565 qs
= pci_test_start();
567 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
568 qpci_msix_enable(dev
->pdev
);
570 qvirtio_pci_set_msix_configuration_vector(dev
, qs
->alloc
, 0);
572 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
573 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
575 features
= qvirtio_get_features(&dev
->vdev
);
576 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
577 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
578 (1u << VIRTIO_F_NOTIFY_ON_EMPTY
) |
579 (1u << VIRTIO_BLK_F_SCSI
));
580 qvirtio_set_features(&dev
->vdev
, features
);
582 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&dev
->vdev
, qs
->alloc
, 0);
583 qvirtqueue_pci_msix_setup(dev
, vqpci
, qs
->alloc
, 1);
585 qvirtio_set_driver_ok(&dev
->vdev
);
588 req
.type
= VIRTIO_BLK_T_OUT
;
591 req
.data
= g_malloc0(512);
592 strcpy(req
.data
, "TEST");
594 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
598 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
599 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
600 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
601 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
603 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
604 QVIRTIO_BLK_TIMEOUT_US
);
607 req
.type
= VIRTIO_BLK_T_OUT
;
610 req
.data
= g_malloc0(512);
611 strcpy(req
.data
, "TEST");
613 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
617 /* Notify after processing the third request */
618 qvirtqueue_set_used_event(&vqpci
->vq
, 2);
619 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
620 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
621 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
622 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
623 write_head
= free_head
;
625 /* No notification expected */
626 status
= qvirtio_wait_status_byte_no_isr(&dev
->vdev
,
627 &vqpci
->vq
, req_addr
+ 528,
628 QVIRTIO_BLK_TIMEOUT_US
);
629 g_assert_cmpint(status
, ==, 0);
631 guest_free(qs
->alloc
, req_addr
);
634 req
.type
= VIRTIO_BLK_T_IN
;
637 req
.data
= g_malloc0(512);
639 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
643 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
644 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
645 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
647 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
649 /* We get just one notification for both requests */
650 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, write_head
, NULL
,
651 QVIRTIO_BLK_TIMEOUT_US
);
652 g_assert(qvirtqueue_get_buf(&vqpci
->vq
, &desc_idx
, NULL
));
653 g_assert_cmpint(desc_idx
, ==, free_head
);
655 status
= readb(req_addr
+ 528);
656 g_assert_cmpint(status
, ==, 0);
658 data
= g_malloc0(512);
659 memread(req_addr
+ 16, data
, 512);
660 g_assert_cmpstr(data
, ==, "TEST");
663 guest_free(qs
->alloc
, req_addr
);
666 qvirtqueue_cleanup(dev
->vdev
.bus
, &vqpci
->vq
, qs
->alloc
);
667 qpci_msix_disable(dev
->pdev
);
668 qvirtio_pci_device_disable(dev
);
669 qvirtio_pci_device_free(dev
);
673 static void pci_hotplug(void)
675 QVirtioPCIDevice
*dev
;
677 const char *arch
= qtest_get_arch();
679 qs
= pci_test_start();
681 /* plug secondary disk */
682 qtest_qmp_device_add("virtio-blk-pci", "drv1",
683 "{'addr': %s, 'drive': 'drive1'}",
684 stringify(PCI_SLOT_HP
));
686 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT_HP
);
688 qvirtio_pci_device_disable(dev
);
689 qvirtio_pci_device_free(dev
);
691 /* unplug secondary disk */
692 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
693 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP
);
699 * Check that setting the vring addr on a non-existent virtqueue does
702 static void test_nonexistent_virtqueue(void)
708 qs
= pci_test_start();
709 dev
= qpci_device_find(qs
->pcibus
, QPCI_DEVFN(4, 0));
710 g_assert(dev
!= NULL
);
712 qpci_device_enable(dev
);
713 bar0
= qpci_iomap(dev
, 0, NULL
);
715 qpci_io_writeb(dev
, bar0
, VIRTIO_PCI_QUEUE_SEL
, 2);
716 qpci_io_writel(dev
, bar0
, VIRTIO_PCI_QUEUE_PFN
, 1);
722 static void mmio_basic(void)
724 QVirtioMMIODevice
*dev
;
726 QGuestAllocator
*alloc
;
727 int n_size
= TEST_IMAGE_SIZE
/ 2;
732 dev
= qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR
, MMIO_PAGE_SIZE
);
733 g_assert(dev
!= NULL
);
734 g_assert_cmphex(dev
->vdev
.device_type
, ==, VIRTIO_ID_BLOCK
);
736 qvirtio_reset(&dev
->vdev
);
737 qvirtio_set_acknowledge(&dev
->vdev
);
738 qvirtio_set_driver(&dev
->vdev
);
740 alloc
= generic_alloc_init(MMIO_RAM_ADDR
, MMIO_RAM_SIZE
, MMIO_PAGE_SIZE
);
741 vq
= qvirtqueue_setup(&dev
->vdev
, alloc
, 0);
743 test_basic(&dev
->vdev
, alloc
, vq
);
745 qmp_discard_response("{ 'execute': 'block_resize', "
746 " 'arguments': { 'device': 'drive0', "
747 " 'size': %d } }", n_size
);
749 qvirtio_wait_queue_isr(&dev
->vdev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
751 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
752 g_assert_cmpint(capacity
, ==, n_size
/ 512);
755 qvirtqueue_cleanup(dev
->vdev
.bus
, vq
, alloc
);
757 generic_alloc_uninit(alloc
);
761 int main(int argc
, char **argv
)
763 const char *arch
= qtest_get_arch();
765 g_test_init(&argc
, &argv
, NULL
);
767 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0 ||
768 strcmp(arch
, "ppc64") == 0) {
769 qtest_add_func("/virtio/blk/pci/basic", pci_basic
);
770 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect
);
771 qtest_add_func("/virtio/blk/pci/config", pci_config
);
772 qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue
);
773 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
774 qtest_add_func("/virtio/blk/pci/msix", pci_msix
);
775 qtest_add_func("/virtio/blk/pci/idx", pci_idx
);
777 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug
);
778 } else if (strcmp(arch
, "arm") == 0) {
779 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic
);