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/virtio.h"
14 #include "libqos/virtio-pci.h"
15 #include "libqos/virtio-mmio.h"
16 #include "libqos/pci-pc.h"
17 #include "libqos/malloc.h"
18 #include "libqos/malloc-pc.h"
19 #include "libqos/malloc-generic.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 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
28 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
29 #define PCI_SLOT_HP 0x06
33 #define MMIO_PAGE_SIZE 4096
34 #define MMIO_DEV_BASE_ADDR 0x0A003E00
35 #define MMIO_RAM_ADDR 0x40000000
36 #define MMIO_RAM_SIZE 0x20000000
38 typedef struct QVirtioBlkReq
{
46 static char *drive_create(void)
49 char *tmp_path
= g_strdup("/tmp/qtest.XXXXXX");
51 /* Create a temporary raw image */
52 fd
= mkstemp(tmp_path
);
53 g_assert_cmpint(fd
, >=, 0);
54 ret
= ftruncate(fd
, TEST_IMAGE_SIZE
);
55 g_assert_cmpint(ret
, ==, 0);
61 static QPCIBus
*pci_test_start(void)
66 tmp_path
= drive_create();
68 cmdline
= g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw "
69 "-drive if=none,id=drive1,file=/dev/null,format=raw "
70 "-device virtio-blk-pci,id=drv0,drive=drive0,"
72 tmp_path
, PCI_SLOT
, PCI_FN
);
78 return qpci_init_pc();
81 static void arm_test_start(void)
86 tmp_path
= drive_create();
88 cmdline
= g_strdup_printf("-machine virt "
89 "-drive if=none,id=drive0,file=%s,format=raw "
90 "-device virtio-blk-device,drive=drive0",
98 static void test_end(void)
103 static QVirtioPCIDevice
*virtio_blk_pci_init(QPCIBus
*bus
, int slot
)
105 QVirtioPCIDevice
*dev
;
107 dev
= qvirtio_pci_device_find(bus
, VIRTIO_ID_BLOCK
);
108 g_assert(dev
!= NULL
);
109 g_assert_cmphex(dev
->vdev
.device_type
, ==, VIRTIO_ID_BLOCK
);
110 g_assert_cmphex(dev
->pdev
->devfn
, ==, ((slot
<< 3) | PCI_FN
));
112 qvirtio_pci_device_enable(dev
);
113 qvirtio_reset(&qvirtio_pci
, &dev
->vdev
);
114 qvirtio_set_acknowledge(&qvirtio_pci
, &dev
->vdev
);
115 qvirtio_set_driver(&qvirtio_pci
, &dev
->vdev
);
120 static inline void virtio_blk_fix_request(QVirtioBlkReq
*req
)
122 #ifdef HOST_WORDS_BIGENDIAN
123 bool host_endian
= true;
125 bool host_endian
= false;
128 if (qtest_big_endian() != host_endian
) {
129 req
->type
= bswap32(req
->type
);
130 req
->ioprio
= bswap32(req
->ioprio
);
131 req
->sector
= bswap64(req
->sector
);
135 static uint64_t virtio_blk_request(QGuestAllocator
*alloc
, QVirtioBlkReq
*req
,
139 uint8_t status
= 0xFF;
141 g_assert_cmpuint(data_size
% 512, ==, 0);
142 addr
= guest_alloc(alloc
, sizeof(*req
) + data_size
);
144 virtio_blk_fix_request(req
);
146 memwrite(addr
, req
, 16);
147 memwrite(addr
+ 16, req
->data
, data_size
);
148 memwrite(addr
+ 16 + data_size
, &status
, sizeof(status
));
153 static void test_basic(const QVirtioBus
*bus
, QVirtioDevice
*dev
,
154 QGuestAllocator
*alloc
, QVirtQueue
*vq
, uint64_t device_specific
)
164 capacity
= qvirtio_config_readq(bus
, dev
, device_specific
);
166 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
168 features
= qvirtio_get_features(bus
, dev
);
169 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
170 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
171 (1u << VIRTIO_RING_F_EVENT_IDX
) |
172 (1u << VIRTIO_BLK_F_SCSI
));
173 qvirtio_set_features(bus
, dev
, features
);
175 qvirtio_set_driver_ok(bus
, dev
);
177 /* Write and read with 3 descriptor layout */
179 req
.type
= VIRTIO_BLK_T_OUT
;
182 req
.data
= g_malloc0(512);
183 strcpy(req
.data
, "TEST");
185 req_addr
= virtio_blk_request(alloc
, &req
, 512);
189 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
190 qvirtqueue_add(vq
, req_addr
+ 16, 512, false, true);
191 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
193 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
195 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
196 status
= readb(req_addr
+ 528);
197 g_assert_cmpint(status
, ==, 0);
199 guest_free(alloc
, req_addr
);
202 req
.type
= VIRTIO_BLK_T_IN
;
205 req
.data
= g_malloc0(512);
207 req_addr
= virtio_blk_request(alloc
, &req
, 512);
211 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
212 qvirtqueue_add(vq
, req_addr
+ 16, 512, true, true);
213 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
215 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
217 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
218 status
= readb(req_addr
+ 528);
219 g_assert_cmpint(status
, ==, 0);
221 data
= g_malloc0(512);
222 memread(req_addr
+ 16, data
, 512);
223 g_assert_cmpstr(data
, ==, "TEST");
226 guest_free(alloc
, req_addr
);
228 if (features
& (1u << VIRTIO_F_ANY_LAYOUT
)) {
229 /* Write and read with 2 descriptor layout */
231 req
.type
= VIRTIO_BLK_T_OUT
;
234 req
.data
= g_malloc0(512);
235 strcpy(req
.data
, "TEST");
237 req_addr
= virtio_blk_request(alloc
, &req
, 512);
241 free_head
= qvirtqueue_add(vq
, req_addr
, 528, false, true);
242 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
243 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
245 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
246 status
= readb(req_addr
+ 528);
247 g_assert_cmpint(status
, ==, 0);
249 guest_free(alloc
, req_addr
);
252 req
.type
= VIRTIO_BLK_T_IN
;
255 req
.data
= g_malloc0(512);
257 req_addr
= virtio_blk_request(alloc
, &req
, 512);
261 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
262 qvirtqueue_add(vq
, req_addr
+ 16, 513, true, false);
264 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
266 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
267 status
= readb(req_addr
+ 528);
268 g_assert_cmpint(status
, ==, 0);
270 data
= g_malloc0(512);
271 memread(req_addr
+ 16, data
, 512);
272 g_assert_cmpstr(data
, ==, "TEST");
275 guest_free(alloc
, req_addr
);
279 static void pci_basic(void)
281 QVirtioPCIDevice
*dev
;
283 QVirtQueuePCI
*vqpci
;
284 QGuestAllocator
*alloc
;
287 bus
= pci_test_start();
288 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
290 alloc
= pc_alloc_init();
291 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
294 /* MSI-X is not enabled */
295 addr
= dev
->addr
+ VIRTIO_PCI_CONFIG_OFF(false);
297 test_basic(&qvirtio_pci
, &dev
->vdev
, alloc
, &vqpci
->vq
,
298 (uint64_t)(uintptr_t)addr
);
301 qvirtqueue_cleanup(&qvirtio_pci
, &vqpci
->vq
, alloc
);
302 pc_alloc_uninit(alloc
);
303 qvirtio_pci_device_disable(dev
);
309 static void pci_indirect(void)
311 QVirtioPCIDevice
*dev
;
313 QVirtQueuePCI
*vqpci
;
314 QGuestAllocator
*alloc
;
316 QVRingIndirectDesc
*indirect
;
325 bus
= pci_test_start();
327 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
329 /* MSI-X is not enabled */
330 addr
= dev
->addr
+ VIRTIO_PCI_CONFIG_OFF(false);
332 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
333 (uint64_t)(uintptr_t)addr
);
334 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
336 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
337 g_assert_cmphex(features
& (1u << VIRTIO_RING_F_INDIRECT_DESC
), !=, 0);
338 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
339 (1u << VIRTIO_RING_F_EVENT_IDX
) |
340 (1u << VIRTIO_BLK_F_SCSI
));
341 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
343 alloc
= pc_alloc_init();
344 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
346 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
349 req
.type
= VIRTIO_BLK_T_OUT
;
352 req
.data
= g_malloc0(512);
353 strcpy(req
.data
, "TEST");
355 req_addr
= virtio_blk_request(alloc
, &req
, 512);
359 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, alloc
, 2);
360 qvring_indirect_desc_add(indirect
, req_addr
, 528, false);
361 qvring_indirect_desc_add(indirect
, req_addr
+ 528, 1, true);
362 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
363 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
365 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
366 QVIRTIO_BLK_TIMEOUT_US
);
367 status
= readb(req_addr
+ 528);
368 g_assert_cmpint(status
, ==, 0);
371 guest_free(alloc
, req_addr
);
374 req
.type
= VIRTIO_BLK_T_IN
;
377 req
.data
= g_malloc0(512);
378 strcpy(req
.data
, "TEST");
380 req_addr
= virtio_blk_request(alloc
, &req
, 512);
384 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, alloc
, 2);
385 qvring_indirect_desc_add(indirect
, req_addr
, 16, false);
386 qvring_indirect_desc_add(indirect
, req_addr
+ 16, 513, true);
387 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
388 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
390 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
391 QVIRTIO_BLK_TIMEOUT_US
);
392 status
= readb(req_addr
+ 528);
393 g_assert_cmpint(status
, ==, 0);
395 data
= g_malloc0(512);
396 memread(req_addr
+ 16, data
, 512);
397 g_assert_cmpstr(data
, ==, "TEST");
401 guest_free(alloc
, req_addr
);
404 qvirtqueue_cleanup(&qvirtio_pci
, &vqpci
->vq
, alloc
);
405 pc_alloc_uninit(alloc
);
406 qvirtio_pci_device_disable(dev
);
412 static void pci_config(void)
414 QVirtioPCIDevice
*dev
;
416 int n_size
= TEST_IMAGE_SIZE
/ 2;
420 bus
= pci_test_start();
422 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
424 /* MSI-X is not enabled */
425 addr
= dev
->addr
+ VIRTIO_PCI_CONFIG_OFF(false);
427 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
428 (uint64_t)(uintptr_t)addr
);
429 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
431 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
433 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
434 " 'size': %d } }", n_size
);
435 qvirtio_wait_config_isr(&qvirtio_pci
, &dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
437 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
438 (uint64_t)(uintptr_t)addr
);
439 g_assert_cmpint(capacity
, ==, n_size
/ 512);
441 qvirtio_pci_device_disable(dev
);
447 static void pci_msix(void)
449 QVirtioPCIDevice
*dev
;
451 QVirtQueuePCI
*vqpci
;
452 QGuestAllocator
*alloc
;
454 int n_size
= TEST_IMAGE_SIZE
/ 2;
463 bus
= pci_test_start();
464 alloc
= pc_alloc_init();
466 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
467 qpci_msix_enable(dev
->pdev
);
469 qvirtio_pci_set_msix_configuration_vector(dev
, alloc
, 0);
471 /* MSI-X is enabled */
472 addr
= dev
->addr
+ VIRTIO_PCI_CONFIG_OFF(true);
474 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
475 (uint64_t)(uintptr_t)addr
);
476 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
478 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
479 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
480 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
481 (1u << VIRTIO_RING_F_EVENT_IDX
) |
482 (1u << VIRTIO_BLK_F_SCSI
));
483 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
485 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
487 qvirtqueue_pci_msix_setup(dev
, vqpci
, alloc
, 1);
489 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
491 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
492 " 'size': %d } }", n_size
);
494 qvirtio_wait_config_isr(&qvirtio_pci
, &dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
496 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
497 (uint64_t)(uintptr_t)addr
);
498 g_assert_cmpint(capacity
, ==, n_size
/ 512);
501 req
.type
= VIRTIO_BLK_T_OUT
;
504 req
.data
= g_malloc0(512);
505 strcpy(req
.data
, "TEST");
507 req_addr
= virtio_blk_request(alloc
, &req
, 512);
511 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
512 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
513 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
514 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
516 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
517 QVIRTIO_BLK_TIMEOUT_US
);
519 status
= readb(req_addr
+ 528);
520 g_assert_cmpint(status
, ==, 0);
522 guest_free(alloc
, req_addr
);
525 req
.type
= VIRTIO_BLK_T_IN
;
528 req
.data
= g_malloc0(512);
530 req_addr
= virtio_blk_request(alloc
, &req
, 512);
534 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
535 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
536 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
538 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
541 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
542 QVIRTIO_BLK_TIMEOUT_US
);
544 status
= readb(req_addr
+ 528);
545 g_assert_cmpint(status
, ==, 0);
547 data
= g_malloc0(512);
548 memread(req_addr
+ 16, data
, 512);
549 g_assert_cmpstr(data
, ==, "TEST");
552 guest_free(alloc
, req_addr
);
555 qvirtqueue_cleanup(&qvirtio_pci
, &vqpci
->vq
, alloc
);
556 pc_alloc_uninit(alloc
);
557 qpci_msix_disable(dev
->pdev
);
558 qvirtio_pci_device_disable(dev
);
564 static void pci_idx(void)
566 QVirtioPCIDevice
*dev
;
568 QVirtQueuePCI
*vqpci
;
569 QGuestAllocator
*alloc
;
579 bus
= pci_test_start();
580 alloc
= pc_alloc_init();
582 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
583 qpci_msix_enable(dev
->pdev
);
585 qvirtio_pci_set_msix_configuration_vector(dev
, alloc
, 0);
587 /* MSI-X is enabled */
588 addr
= dev
->addr
+ VIRTIO_PCI_CONFIG_OFF(true);
590 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
591 (uint64_t)(uintptr_t)addr
);
592 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
594 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
595 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
596 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
597 (1u << VIRTIO_F_NOTIFY_ON_EMPTY
) |
598 (1u << VIRTIO_BLK_F_SCSI
));
599 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
601 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
603 qvirtqueue_pci_msix_setup(dev
, vqpci
, alloc
, 1);
605 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
608 req
.type
= VIRTIO_BLK_T_OUT
;
611 req
.data
= g_malloc0(512);
612 strcpy(req
.data
, "TEST");
614 req_addr
= virtio_blk_request(alloc
, &req
, 512);
618 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
619 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
620 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
621 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
623 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
624 QVIRTIO_BLK_TIMEOUT_US
);
627 req
.type
= VIRTIO_BLK_T_OUT
;
630 req
.data
= g_malloc0(512);
631 strcpy(req
.data
, "TEST");
633 req_addr
= virtio_blk_request(alloc
, &req
, 512);
637 /* Notify after processing the third request */
638 qvirtqueue_set_used_event(&vqpci
->vq
, 2);
639 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
640 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
641 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
642 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
644 /* No notification expected */
645 status
= qvirtio_wait_status_byte_no_isr(&qvirtio_pci
, &dev
->vdev
,
646 &vqpci
->vq
, req_addr
+ 528,
647 QVIRTIO_BLK_TIMEOUT_US
);
648 g_assert_cmpint(status
, ==, 0);
650 guest_free(alloc
, req_addr
);
653 req
.type
= VIRTIO_BLK_T_IN
;
656 req
.data
= g_malloc0(512);
658 req_addr
= virtio_blk_request(alloc
, &req
, 512);
662 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
663 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
664 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
666 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
668 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
669 QVIRTIO_BLK_TIMEOUT_US
);
671 status
= readb(req_addr
+ 528);
672 g_assert_cmpint(status
, ==, 0);
674 data
= g_malloc0(512);
675 memread(req_addr
+ 16, data
, 512);
676 g_assert_cmpstr(data
, ==, "TEST");
679 guest_free(alloc
, req_addr
);
682 qvirtqueue_cleanup(&qvirtio_pci
, &vqpci
->vq
, alloc
);
683 pc_alloc_uninit(alloc
);
684 qpci_msix_disable(dev
->pdev
);
685 qvirtio_pci_device_disable(dev
);
691 static void pci_hotplug(void)
694 QVirtioPCIDevice
*dev
;
696 bus
= pci_test_start();
698 /* plug secondary disk */
699 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP
,
700 "'drive': 'drive1'");
702 dev
= virtio_blk_pci_init(bus
, PCI_SLOT_HP
);
704 qvirtio_pci_device_disable(dev
);
707 /* unplug secondary disk */
708 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP
);
713 static void mmio_basic(void)
715 QVirtioMMIODevice
*dev
;
717 QGuestAllocator
*alloc
;
718 int n_size
= TEST_IMAGE_SIZE
/ 2;
723 dev
= qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR
, MMIO_PAGE_SIZE
);
724 g_assert(dev
!= NULL
);
725 g_assert_cmphex(dev
->vdev
.device_type
, ==, VIRTIO_ID_BLOCK
);
727 qvirtio_reset(&qvirtio_mmio
, &dev
->vdev
);
728 qvirtio_set_acknowledge(&qvirtio_mmio
, &dev
->vdev
);
729 qvirtio_set_driver(&qvirtio_mmio
, &dev
->vdev
);
731 alloc
= generic_alloc_init(MMIO_RAM_ADDR
, MMIO_RAM_SIZE
, MMIO_PAGE_SIZE
);
732 vq
= qvirtqueue_setup(&qvirtio_mmio
, &dev
->vdev
, alloc
, 0);
734 test_basic(&qvirtio_mmio
, &dev
->vdev
, alloc
, vq
,
735 QVIRTIO_MMIO_DEVICE_SPECIFIC
);
737 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
738 " 'size': %d } }", n_size
);
740 qvirtio_wait_queue_isr(&qvirtio_mmio
, &dev
->vdev
, vq
,
741 QVIRTIO_BLK_TIMEOUT_US
);
743 capacity
= qvirtio_config_readq(&qvirtio_mmio
, &dev
->vdev
,
744 QVIRTIO_MMIO_DEVICE_SPECIFIC
);
745 g_assert_cmpint(capacity
, ==, n_size
/ 512);
748 qvirtqueue_cleanup(&qvirtio_mmio
, vq
, alloc
);
749 generic_alloc_uninit(alloc
);
754 int main(int argc
, char **argv
)
756 const char *arch
= qtest_get_arch();
758 g_test_init(&argc
, &argv
, NULL
);
760 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
761 qtest_add_func("/virtio/blk/pci/basic", pci_basic
);
762 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect
);
763 qtest_add_func("/virtio/blk/pci/config", pci_config
);
764 qtest_add_func("/virtio/blk/pci/msix", pci_msix
);
765 qtest_add_func("/virtio/blk/pci/idx", pci_idx
);
766 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug
);
767 } else if (strcmp(arch
, "arm") == 0) {
768 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic
);