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.
17 #include "libqos/virtio.h"
18 #include "libqos/virtio-pci.h"
19 #include "libqos/virtio-mmio.h"
20 #include "libqos/pci-pc.h"
21 #include "libqos/malloc.h"
22 #include "libqos/malloc-pc.h"
23 #include "libqos/malloc-generic.h"
24 #include "qemu/bswap.h"
26 #define QVIRTIO_BLK_F_BARRIER 0x00000001
27 #define QVIRTIO_BLK_F_SIZE_MAX 0x00000002
28 #define QVIRTIO_BLK_F_SEG_MAX 0x00000004
29 #define QVIRTIO_BLK_F_GEOMETRY 0x00000010
30 #define QVIRTIO_BLK_F_RO 0x00000020
31 #define QVIRTIO_BLK_F_BLK_SIZE 0x00000040
32 #define QVIRTIO_BLK_F_SCSI 0x00000080
33 #define QVIRTIO_BLK_F_WCE 0x00000200
34 #define QVIRTIO_BLK_F_TOPOLOGY 0x00000400
35 #define QVIRTIO_BLK_F_CONFIG_WCE 0x00000800
37 #define QVIRTIO_BLK_T_IN 0
38 #define QVIRTIO_BLK_T_OUT 1
39 #define QVIRTIO_BLK_T_SCSI_CMD 2
40 #define QVIRTIO_BLK_T_SCSI_CMD_OUT 3
41 #define QVIRTIO_BLK_T_FLUSH 4
42 #define QVIRTIO_BLK_T_FLUSH_OUT 5
43 #define QVIRTIO_BLK_T_GET_ID 8
45 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
46 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
47 #define PCI_SLOT_HP 0x06
51 #define MMIO_PAGE_SIZE 4096
52 #define MMIO_DEV_BASE_ADDR 0x0A003E00
53 #define MMIO_RAM_ADDR 0x40000000
54 #define MMIO_RAM_SIZE 0x20000000
56 typedef struct QVirtioBlkReq
{
64 static char *drive_create(void)
67 char *tmp_path
= g_strdup("/tmp/qtest.XXXXXX");
69 /* Create a temporary raw image */
70 fd
= mkstemp(tmp_path
);
71 g_assert_cmpint(fd
, >=, 0);
72 ret
= ftruncate(fd
, TEST_IMAGE_SIZE
);
73 g_assert_cmpint(ret
, ==, 0);
79 static QPCIBus
*pci_test_start(void)
84 tmp_path
= drive_create();
86 cmdline
= g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw "
87 "-drive if=none,id=drive1,file=/dev/null,format=raw "
88 "-device virtio-blk-pci,id=drv0,drive=drive0,"
90 tmp_path
, PCI_SLOT
, PCI_FN
);
96 return qpci_init_pc();
99 static void arm_test_start(void)
104 tmp_path
= drive_create();
106 cmdline
= g_strdup_printf("-machine virt "
107 "-drive if=none,id=drive0,file=%s,format=raw "
108 "-device virtio-blk-device,drive=drive0",
110 qtest_start(cmdline
);
116 static void test_end(void)
121 static QVirtioPCIDevice
*virtio_blk_pci_init(QPCIBus
*bus
, int slot
)
123 QVirtioPCIDevice
*dev
;
125 dev
= qvirtio_pci_device_find(bus
, QVIRTIO_BLK_DEVICE_ID
);
126 g_assert(dev
!= NULL
);
127 g_assert_cmphex(dev
->vdev
.device_type
, ==, QVIRTIO_BLK_DEVICE_ID
);
128 g_assert_cmphex(dev
->pdev
->devfn
, ==, ((slot
<< 3) | PCI_FN
));
130 qvirtio_pci_device_enable(dev
);
131 qvirtio_reset(&qvirtio_pci
, &dev
->vdev
);
132 qvirtio_set_acknowledge(&qvirtio_pci
, &dev
->vdev
);
133 qvirtio_set_driver(&qvirtio_pci
, &dev
->vdev
);
138 static inline void virtio_blk_fix_request(QVirtioBlkReq
*req
)
140 #ifdef HOST_WORDS_BIGENDIAN
141 bool host_endian
= true;
143 bool host_endian
= false;
146 if (qtest_big_endian() != host_endian
) {
147 req
->type
= bswap32(req
->type
);
148 req
->ioprio
= bswap32(req
->ioprio
);
149 req
->sector
= bswap64(req
->sector
);
153 static uint64_t virtio_blk_request(QGuestAllocator
*alloc
, QVirtioBlkReq
*req
,
157 uint8_t status
= 0xFF;
159 g_assert_cmpuint(data_size
% 512, ==, 0);
160 addr
= guest_alloc(alloc
, sizeof(*req
) + data_size
);
162 virtio_blk_fix_request(req
);
164 memwrite(addr
, req
, 16);
165 memwrite(addr
+ 16, req
->data
, data_size
);
166 memwrite(addr
+ 16 + data_size
, &status
, sizeof(status
));
171 static void test_basic(const QVirtioBus
*bus
, QVirtioDevice
*dev
,
172 QGuestAllocator
*alloc
, QVirtQueue
*vq
, uint64_t device_specific
)
182 capacity
= qvirtio_config_readq(bus
, dev
, device_specific
);
184 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
186 features
= qvirtio_get_features(bus
, dev
);
187 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
188 QVIRTIO_F_RING_INDIRECT_DESC
| QVIRTIO_F_RING_EVENT_IDX
|
190 qvirtio_set_features(bus
, dev
, features
);
192 qvirtio_set_driver_ok(bus
, dev
);
194 /* Write and read with 3 descriptor layout */
196 req
.type
= QVIRTIO_BLK_T_OUT
;
199 req
.data
= g_malloc0(512);
200 strcpy(req
.data
, "TEST");
202 req_addr
= virtio_blk_request(alloc
, &req
, 512);
206 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
207 qvirtqueue_add(vq
, req_addr
+ 16, 512, false, true);
208 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
210 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
212 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
213 status
= readb(req_addr
+ 528);
214 g_assert_cmpint(status
, ==, 0);
216 guest_free(alloc
, req_addr
);
219 req
.type
= QVIRTIO_BLK_T_IN
;
222 req
.data
= g_malloc0(512);
224 req_addr
= virtio_blk_request(alloc
, &req
, 512);
228 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
229 qvirtqueue_add(vq
, req_addr
+ 16, 512, true, true);
230 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
232 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
234 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
235 status
= readb(req_addr
+ 528);
236 g_assert_cmpint(status
, ==, 0);
238 data
= g_malloc0(512);
239 memread(req_addr
+ 16, data
, 512);
240 g_assert_cmpstr(data
, ==, "TEST");
243 guest_free(alloc
, req_addr
);
245 if (features
& QVIRTIO_F_ANY_LAYOUT
) {
246 /* Write and read with 2 descriptor layout */
248 req
.type
= QVIRTIO_BLK_T_OUT
;
251 req
.data
= g_malloc0(512);
252 strcpy(req
.data
, "TEST");
254 req_addr
= virtio_blk_request(alloc
, &req
, 512);
258 free_head
= qvirtqueue_add(vq
, req_addr
, 528, false, true);
259 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
260 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
262 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
263 status
= readb(req_addr
+ 528);
264 g_assert_cmpint(status
, ==, 0);
266 guest_free(alloc
, req_addr
);
269 req
.type
= QVIRTIO_BLK_T_IN
;
272 req
.data
= g_malloc0(512);
274 req_addr
= virtio_blk_request(alloc
, &req
, 512);
278 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
279 qvirtqueue_add(vq
, req_addr
+ 16, 513, true, false);
281 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
283 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
284 status
= readb(req_addr
+ 528);
285 g_assert_cmpint(status
, ==, 0);
287 data
= g_malloc0(512);
288 memread(req_addr
+ 16, data
, 512);
289 g_assert_cmpstr(data
, ==, "TEST");
292 guest_free(alloc
, req_addr
);
296 static void pci_basic(void)
298 QVirtioPCIDevice
*dev
;
300 QVirtQueuePCI
*vqpci
;
301 QGuestAllocator
*alloc
;
304 bus
= pci_test_start();
305 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
307 alloc
= pc_alloc_init();
308 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
311 /* MSI-X is not enabled */
312 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
314 test_basic(&qvirtio_pci
, &dev
->vdev
, alloc
, &vqpci
->vq
,
315 (uint64_t)(uintptr_t)addr
);
318 guest_free(alloc
, vqpci
->vq
.desc
);
319 pc_alloc_uninit(alloc
);
320 qvirtio_pci_device_disable(dev
);
326 static void pci_indirect(void)
328 QVirtioPCIDevice
*dev
;
330 QVirtQueuePCI
*vqpci
;
331 QGuestAllocator
*alloc
;
333 QVRingIndirectDesc
*indirect
;
342 bus
= pci_test_start();
344 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
346 /* MSI-X is not enabled */
347 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
349 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
350 (uint64_t)(uintptr_t)addr
);
351 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
353 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
354 g_assert_cmphex(features
& QVIRTIO_F_RING_INDIRECT_DESC
, !=, 0);
355 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
| QVIRTIO_F_RING_EVENT_IDX
|
357 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
359 alloc
= pc_alloc_init();
360 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
362 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
365 req
.type
= QVIRTIO_BLK_T_OUT
;
368 req
.data
= g_malloc0(512);
369 strcpy(req
.data
, "TEST");
371 req_addr
= virtio_blk_request(alloc
, &req
, 512);
375 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, alloc
, 2);
376 qvring_indirect_desc_add(indirect
, req_addr
, 528, false);
377 qvring_indirect_desc_add(indirect
, req_addr
+ 528, 1, true);
378 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
379 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
381 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
382 QVIRTIO_BLK_TIMEOUT_US
);
383 status
= readb(req_addr
+ 528);
384 g_assert_cmpint(status
, ==, 0);
387 guest_free(alloc
, req_addr
);
390 req
.type
= QVIRTIO_BLK_T_IN
;
393 req
.data
= g_malloc0(512);
394 strcpy(req
.data
, "TEST");
396 req_addr
= virtio_blk_request(alloc
, &req
, 512);
400 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, alloc
, 2);
401 qvring_indirect_desc_add(indirect
, req_addr
, 16, false);
402 qvring_indirect_desc_add(indirect
, req_addr
+ 16, 513, true);
403 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
404 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
406 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
407 QVIRTIO_BLK_TIMEOUT_US
);
408 status
= readb(req_addr
+ 528);
409 g_assert_cmpint(status
, ==, 0);
411 data
= g_malloc0(512);
412 memread(req_addr
+ 16, data
, 512);
413 g_assert_cmpstr(data
, ==, "TEST");
417 guest_free(alloc
, req_addr
);
420 guest_free(alloc
, vqpci
->vq
.desc
);
421 pc_alloc_uninit(alloc
);
422 qvirtio_pci_device_disable(dev
);
428 static void pci_config(void)
430 QVirtioPCIDevice
*dev
;
432 int n_size
= TEST_IMAGE_SIZE
/ 2;
436 bus
= pci_test_start();
438 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
440 /* MSI-X is not enabled */
441 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
443 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
444 (uint64_t)(uintptr_t)addr
);
445 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
447 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
449 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
450 " 'size': %d } }", n_size
);
451 qvirtio_wait_config_isr(&qvirtio_pci
, &dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
453 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
454 (uint64_t)(uintptr_t)addr
);
455 g_assert_cmpint(capacity
, ==, n_size
/ 512);
457 qvirtio_pci_device_disable(dev
);
463 static void pci_msix(void)
465 QVirtioPCIDevice
*dev
;
467 QVirtQueuePCI
*vqpci
;
468 QGuestAllocator
*alloc
;
470 int n_size
= TEST_IMAGE_SIZE
/ 2;
479 bus
= pci_test_start();
480 alloc
= pc_alloc_init();
482 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
483 qpci_msix_enable(dev
->pdev
);
485 qvirtio_pci_set_msix_configuration_vector(dev
, alloc
, 0);
487 /* MSI-X is enabled */
488 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX
;
490 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
491 (uint64_t)(uintptr_t)addr
);
492 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
494 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
495 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
496 QVIRTIO_F_RING_INDIRECT_DESC
|
497 QVIRTIO_F_RING_EVENT_IDX
| QVIRTIO_BLK_F_SCSI
);
498 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
500 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
502 qvirtqueue_pci_msix_setup(dev
, vqpci
, alloc
, 1);
504 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
506 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
507 " 'size': %d } }", n_size
);
509 qvirtio_wait_config_isr(&qvirtio_pci
, &dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
511 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
512 (uint64_t)(uintptr_t)addr
);
513 g_assert_cmpint(capacity
, ==, n_size
/ 512);
516 req
.type
= QVIRTIO_BLK_T_OUT
;
519 req
.data
= g_malloc0(512);
520 strcpy(req
.data
, "TEST");
522 req_addr
= virtio_blk_request(alloc
, &req
, 512);
526 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
527 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
528 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
529 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
531 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
532 QVIRTIO_BLK_TIMEOUT_US
);
534 status
= readb(req_addr
+ 528);
535 g_assert_cmpint(status
, ==, 0);
537 guest_free(alloc
, req_addr
);
540 req
.type
= QVIRTIO_BLK_T_IN
;
543 req
.data
= g_malloc0(512);
545 req_addr
= virtio_blk_request(alloc
, &req
, 512);
549 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
550 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
551 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
553 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
556 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
557 QVIRTIO_BLK_TIMEOUT_US
);
559 status
= readb(req_addr
+ 528);
560 g_assert_cmpint(status
, ==, 0);
562 data
= g_malloc0(512);
563 memread(req_addr
+ 16, data
, 512);
564 g_assert_cmpstr(data
, ==, "TEST");
567 guest_free(alloc
, req_addr
);
570 guest_free(alloc
, vqpci
->vq
.desc
);
571 pc_alloc_uninit(alloc
);
572 qpci_msix_disable(dev
->pdev
);
573 qvirtio_pci_device_disable(dev
);
579 static void pci_idx(void)
581 QVirtioPCIDevice
*dev
;
583 QVirtQueuePCI
*vqpci
;
584 QGuestAllocator
*alloc
;
594 bus
= pci_test_start();
595 alloc
= pc_alloc_init();
597 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
598 qpci_msix_enable(dev
->pdev
);
600 qvirtio_pci_set_msix_configuration_vector(dev
, alloc
, 0);
602 /* MSI-X is enabled */
603 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX
;
605 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
606 (uint64_t)(uintptr_t)addr
);
607 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
609 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
610 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
611 QVIRTIO_F_RING_INDIRECT_DESC
|
612 QVIRTIO_F_NOTIFY_ON_EMPTY
| QVIRTIO_BLK_F_SCSI
);
613 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
615 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
617 qvirtqueue_pci_msix_setup(dev
, vqpci
, alloc
, 1);
619 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
622 req
.type
= QVIRTIO_BLK_T_OUT
;
625 req
.data
= g_malloc0(512);
626 strcpy(req
.data
, "TEST");
628 req_addr
= virtio_blk_request(alloc
, &req
, 512);
632 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
633 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
634 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
635 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
637 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
638 QVIRTIO_BLK_TIMEOUT_US
);
641 req
.type
= QVIRTIO_BLK_T_OUT
;
644 req
.data
= g_malloc0(512);
645 strcpy(req
.data
, "TEST");
647 req_addr
= virtio_blk_request(alloc
, &req
, 512);
651 /* Notify after processing the third request */
652 qvirtqueue_set_used_event(&vqpci
->vq
, 2);
653 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
654 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
655 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
656 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
658 /* No notification expected */
659 status
= qvirtio_wait_status_byte_no_isr(&qvirtio_pci
, &dev
->vdev
,
660 &vqpci
->vq
, req_addr
+ 528,
661 QVIRTIO_BLK_TIMEOUT_US
);
662 g_assert_cmpint(status
, ==, 0);
664 guest_free(alloc
, req_addr
);
667 req
.type
= QVIRTIO_BLK_T_IN
;
670 req
.data
= g_malloc0(512);
672 req_addr
= virtio_blk_request(alloc
, &req
, 512);
676 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
677 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
678 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
680 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
682 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
683 QVIRTIO_BLK_TIMEOUT_US
);
685 status
= readb(req_addr
+ 528);
686 g_assert_cmpint(status
, ==, 0);
688 data
= g_malloc0(512);
689 memread(req_addr
+ 16, data
, 512);
690 g_assert_cmpstr(data
, ==, "TEST");
693 guest_free(alloc
, req_addr
);
696 guest_free(alloc
, vqpci
->vq
.desc
);
697 pc_alloc_uninit(alloc
);
698 qpci_msix_disable(dev
->pdev
);
699 qvirtio_pci_device_disable(dev
);
705 static void pci_hotplug(void)
708 QVirtioPCIDevice
*dev
;
710 bus
= pci_test_start();
712 /* plug secondary disk */
713 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP
,
714 "'drive': 'drive1'");
716 dev
= virtio_blk_pci_init(bus
, PCI_SLOT_HP
);
718 qvirtio_pci_device_disable(dev
);
721 /* unplug secondary disk */
722 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP
);
727 static void mmio_basic(void)
729 QVirtioMMIODevice
*dev
;
731 QGuestAllocator
*alloc
;
732 int n_size
= TEST_IMAGE_SIZE
/ 2;
737 dev
= qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR
, MMIO_PAGE_SIZE
);
738 g_assert(dev
!= NULL
);
739 g_assert_cmphex(dev
->vdev
.device_type
, ==, QVIRTIO_BLK_DEVICE_ID
);
741 qvirtio_reset(&qvirtio_mmio
, &dev
->vdev
);
742 qvirtio_set_acknowledge(&qvirtio_mmio
, &dev
->vdev
);
743 qvirtio_set_driver(&qvirtio_mmio
, &dev
->vdev
);
745 alloc
= generic_alloc_init(MMIO_RAM_ADDR
, MMIO_RAM_SIZE
, MMIO_PAGE_SIZE
);
746 vq
= qvirtqueue_setup(&qvirtio_mmio
, &dev
->vdev
, alloc
, 0);
748 test_basic(&qvirtio_mmio
, &dev
->vdev
, alloc
, vq
,
749 QVIRTIO_MMIO_DEVICE_SPECIFIC
);
751 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
752 " 'size': %d } }", n_size
);
754 qvirtio_wait_queue_isr(&qvirtio_mmio
, &dev
->vdev
, vq
,
755 QVIRTIO_BLK_TIMEOUT_US
);
757 capacity
= qvirtio_config_readq(&qvirtio_mmio
, &dev
->vdev
,
758 QVIRTIO_MMIO_DEVICE_SPECIFIC
);
759 g_assert_cmpint(capacity
, ==, n_size
/ 512);
762 guest_free(alloc
, vq
->desc
);
763 generic_alloc_uninit(alloc
);
768 int main(int argc
, char **argv
)
771 const char *arch
= qtest_get_arch();
773 g_test_init(&argc
, &argv
, NULL
);
775 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
776 qtest_add_func("/virtio/blk/pci/basic", pci_basic
);
777 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect
);
778 qtest_add_func("/virtio/blk/pci/config", pci_config
);
779 qtest_add_func("/virtio/blk/pci/msix", pci_msix
);
780 qtest_add_func("/virtio/blk/pci/idx", pci_idx
);
781 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug
);
782 } else if (strcmp(arch
, "arm") == 0) {
783 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic
);