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"
22 #define QVIRTIO_BLK_F_BARRIER 0x00000001
23 #define QVIRTIO_BLK_F_SIZE_MAX 0x00000002
24 #define QVIRTIO_BLK_F_SEG_MAX 0x00000004
25 #define QVIRTIO_BLK_F_GEOMETRY 0x00000010
26 #define QVIRTIO_BLK_F_RO 0x00000020
27 #define QVIRTIO_BLK_F_BLK_SIZE 0x00000040
28 #define QVIRTIO_BLK_F_SCSI 0x00000080
29 #define QVIRTIO_BLK_F_WCE 0x00000200
30 #define QVIRTIO_BLK_F_TOPOLOGY 0x00000400
31 #define QVIRTIO_BLK_F_CONFIG_WCE 0x00000800
33 #define QVIRTIO_BLK_T_IN 0
34 #define QVIRTIO_BLK_T_OUT 1
35 #define QVIRTIO_BLK_T_SCSI_CMD 2
36 #define QVIRTIO_BLK_T_SCSI_CMD_OUT 3
37 #define QVIRTIO_BLK_T_FLUSH 4
38 #define QVIRTIO_BLK_T_FLUSH_OUT 5
39 #define QVIRTIO_BLK_T_GET_ID 8
41 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
42 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
43 #define PCI_SLOT_HP 0x06
47 #define MMIO_PAGE_SIZE 4096
48 #define MMIO_DEV_BASE_ADDR 0x0A003E00
49 #define MMIO_RAM_ADDR 0x40000000
50 #define MMIO_RAM_SIZE 0x20000000
52 typedef struct QVirtioBlkReq
{
60 static char *drive_create(void)
63 char *tmp_path
= g_strdup("/tmp/qtest.XXXXXX");
65 /* Create a temporary raw image */
66 fd
= mkstemp(tmp_path
);
67 g_assert_cmpint(fd
, >=, 0);
68 ret
= ftruncate(fd
, TEST_IMAGE_SIZE
);
69 g_assert_cmpint(ret
, ==, 0);
75 static QPCIBus
*pci_test_start(void)
80 tmp_path
= drive_create();
82 cmdline
= g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw "
83 "-drive if=none,id=drive1,file=/dev/null,format=raw "
84 "-device virtio-blk-pci,id=drv0,drive=drive0,"
86 tmp_path
, PCI_SLOT
, PCI_FN
);
92 return qpci_init_pc();
95 static void arm_test_start(void)
100 tmp_path
= drive_create();
102 cmdline
= g_strdup_printf("-machine virt "
103 "-drive if=none,id=drive0,file=%s,format=raw "
104 "-device virtio-blk-device,drive=drive0",
106 qtest_start(cmdline
);
112 static void test_end(void)
117 static QVirtioPCIDevice
*virtio_blk_pci_init(QPCIBus
*bus
, int slot
)
119 QVirtioPCIDevice
*dev
;
121 dev
= qvirtio_pci_device_find(bus
, QVIRTIO_BLK_DEVICE_ID
);
122 g_assert(dev
!= NULL
);
123 g_assert_cmphex(dev
->vdev
.device_type
, ==, QVIRTIO_BLK_DEVICE_ID
);
124 g_assert_cmphex(dev
->pdev
->devfn
, ==, ((slot
<< 3) | PCI_FN
));
126 qvirtio_pci_device_enable(dev
);
127 qvirtio_reset(&qvirtio_pci
, &dev
->vdev
);
128 qvirtio_set_acknowledge(&qvirtio_pci
, &dev
->vdev
);
129 qvirtio_set_driver(&qvirtio_pci
, &dev
->vdev
);
134 static inline void virtio_blk_fix_request(QVirtioBlkReq
*req
)
136 #ifdef HOST_WORDS_BIGENDIAN
137 bool host_endian
= true;
139 bool host_endian
= false;
142 if (qtest_big_endian() != host_endian
) {
143 req
->type
= bswap32(req
->type
);
144 req
->ioprio
= bswap32(req
->ioprio
);
145 req
->sector
= bswap64(req
->sector
);
149 static uint64_t virtio_blk_request(QGuestAllocator
*alloc
, QVirtioBlkReq
*req
,
153 uint8_t status
= 0xFF;
155 g_assert_cmpuint(data_size
% 512, ==, 0);
156 addr
= guest_alloc(alloc
, sizeof(*req
) + data_size
);
158 virtio_blk_fix_request(req
);
160 memwrite(addr
, req
, 16);
161 memwrite(addr
+ 16, req
->data
, data_size
);
162 memwrite(addr
+ 16 + data_size
, &status
, sizeof(status
));
167 static void test_basic(const QVirtioBus
*bus
, QVirtioDevice
*dev
,
168 QGuestAllocator
*alloc
, QVirtQueue
*vq
, uint64_t device_specific
)
178 capacity
= qvirtio_config_readq(bus
, dev
, device_specific
);
180 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
182 features
= qvirtio_get_features(bus
, dev
);
183 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
184 QVIRTIO_F_RING_INDIRECT_DESC
| QVIRTIO_F_RING_EVENT_IDX
|
186 qvirtio_set_features(bus
, dev
, features
);
188 qvirtio_set_driver_ok(bus
, dev
);
190 /* Write and read with 3 descriptor layout */
192 req
.type
= QVIRTIO_BLK_T_OUT
;
195 req
.data
= g_malloc0(512);
196 strcpy(req
.data
, "TEST");
198 req_addr
= virtio_blk_request(alloc
, &req
, 512);
202 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
203 qvirtqueue_add(vq
, req_addr
+ 16, 512, false, true);
204 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
206 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
208 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
209 status
= readb(req_addr
+ 528);
210 g_assert_cmpint(status
, ==, 0);
212 guest_free(alloc
, req_addr
);
215 req
.type
= QVIRTIO_BLK_T_IN
;
218 req
.data
= g_malloc0(512);
220 req_addr
= virtio_blk_request(alloc
, &req
, 512);
224 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
225 qvirtqueue_add(vq
, req_addr
+ 16, 512, true, true);
226 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
228 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
230 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
231 status
= readb(req_addr
+ 528);
232 g_assert_cmpint(status
, ==, 0);
234 data
= g_malloc0(512);
235 memread(req_addr
+ 16, data
, 512);
236 g_assert_cmpstr(data
, ==, "TEST");
239 guest_free(alloc
, req_addr
);
241 if (features
& QVIRTIO_F_ANY_LAYOUT
) {
242 /* Write and read with 2 descriptor layout */
244 req
.type
= QVIRTIO_BLK_T_OUT
;
247 req
.data
= g_malloc0(512);
248 strcpy(req
.data
, "TEST");
250 req_addr
= virtio_blk_request(alloc
, &req
, 512);
254 free_head
= qvirtqueue_add(vq
, req_addr
, 528, false, true);
255 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
256 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
258 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
259 status
= readb(req_addr
+ 528);
260 g_assert_cmpint(status
, ==, 0);
262 guest_free(alloc
, req_addr
);
265 req
.type
= QVIRTIO_BLK_T_IN
;
268 req
.data
= g_malloc0(512);
270 req_addr
= virtio_blk_request(alloc
, &req
, 512);
274 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
275 qvirtqueue_add(vq
, req_addr
+ 16, 513, true, false);
277 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
279 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
280 status
= readb(req_addr
+ 528);
281 g_assert_cmpint(status
, ==, 0);
283 data
= g_malloc0(512);
284 memread(req_addr
+ 16, data
, 512);
285 g_assert_cmpstr(data
, ==, "TEST");
288 guest_free(alloc
, req_addr
);
292 static void pci_basic(void)
294 QVirtioPCIDevice
*dev
;
296 QVirtQueuePCI
*vqpci
;
297 QGuestAllocator
*alloc
;
300 bus
= pci_test_start();
301 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
303 alloc
= pc_alloc_init();
304 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
307 /* MSI-X is not enabled */
308 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
310 test_basic(&qvirtio_pci
, &dev
->vdev
, alloc
, &vqpci
->vq
,
311 (uint64_t)(uintptr_t)addr
);
314 guest_free(alloc
, vqpci
->vq
.desc
);
315 pc_alloc_uninit(alloc
);
316 qvirtio_pci_device_disable(dev
);
322 static void pci_indirect(void)
324 QVirtioPCIDevice
*dev
;
326 QVirtQueuePCI
*vqpci
;
327 QGuestAllocator
*alloc
;
329 QVRingIndirectDesc
*indirect
;
338 bus
= pci_test_start();
340 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
342 /* MSI-X is not enabled */
343 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
345 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
346 (uint64_t)(uintptr_t)addr
);
347 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
349 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
350 g_assert_cmphex(features
& QVIRTIO_F_RING_INDIRECT_DESC
, !=, 0);
351 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
| QVIRTIO_F_RING_EVENT_IDX
|
353 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
355 alloc
= pc_alloc_init();
356 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
358 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
361 req
.type
= QVIRTIO_BLK_T_OUT
;
364 req
.data
= g_malloc0(512);
365 strcpy(req
.data
, "TEST");
367 req_addr
= virtio_blk_request(alloc
, &req
, 512);
371 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, alloc
, 2);
372 qvring_indirect_desc_add(indirect
, req_addr
, 528, false);
373 qvring_indirect_desc_add(indirect
, req_addr
+ 528, 1, true);
374 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
375 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
377 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
378 QVIRTIO_BLK_TIMEOUT_US
);
379 status
= readb(req_addr
+ 528);
380 g_assert_cmpint(status
, ==, 0);
383 guest_free(alloc
, req_addr
);
386 req
.type
= QVIRTIO_BLK_T_IN
;
389 req
.data
= g_malloc0(512);
390 strcpy(req
.data
, "TEST");
392 req_addr
= virtio_blk_request(alloc
, &req
, 512);
396 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, alloc
, 2);
397 qvring_indirect_desc_add(indirect
, req_addr
, 16, false);
398 qvring_indirect_desc_add(indirect
, req_addr
+ 16, 513, true);
399 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
400 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
402 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
403 QVIRTIO_BLK_TIMEOUT_US
);
404 status
= readb(req_addr
+ 528);
405 g_assert_cmpint(status
, ==, 0);
407 data
= g_malloc0(512);
408 memread(req_addr
+ 16, data
, 512);
409 g_assert_cmpstr(data
, ==, "TEST");
413 guest_free(alloc
, req_addr
);
416 guest_free(alloc
, vqpci
->vq
.desc
);
417 pc_alloc_uninit(alloc
);
418 qvirtio_pci_device_disable(dev
);
424 static void pci_config(void)
426 QVirtioPCIDevice
*dev
;
428 int n_size
= TEST_IMAGE_SIZE
/ 2;
432 bus
= pci_test_start();
434 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
436 /* MSI-X is not enabled */
437 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
439 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
440 (uint64_t)(uintptr_t)addr
);
441 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
443 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
445 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
446 " 'size': %d } }", n_size
);
447 qvirtio_wait_config_isr(&qvirtio_pci
, &dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
449 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
450 (uint64_t)(uintptr_t)addr
);
451 g_assert_cmpint(capacity
, ==, n_size
/ 512);
453 qvirtio_pci_device_disable(dev
);
459 static void pci_msix(void)
461 QVirtioPCIDevice
*dev
;
463 QVirtQueuePCI
*vqpci
;
464 QGuestAllocator
*alloc
;
466 int n_size
= TEST_IMAGE_SIZE
/ 2;
475 bus
= pci_test_start();
476 alloc
= pc_alloc_init();
478 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
479 qpci_msix_enable(dev
->pdev
);
481 qvirtio_pci_set_msix_configuration_vector(dev
, alloc
, 0);
483 /* MSI-X is enabled */
484 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX
;
486 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
487 (uint64_t)(uintptr_t)addr
);
488 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
490 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
491 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
492 QVIRTIO_F_RING_INDIRECT_DESC
|
493 QVIRTIO_F_RING_EVENT_IDX
| QVIRTIO_BLK_F_SCSI
);
494 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
496 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
498 qvirtqueue_pci_msix_setup(dev
, vqpci
, alloc
, 1);
500 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
502 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
503 " 'size': %d } }", n_size
);
505 qvirtio_wait_config_isr(&qvirtio_pci
, &dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
507 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
508 (uint64_t)(uintptr_t)addr
);
509 g_assert_cmpint(capacity
, ==, n_size
/ 512);
512 req
.type
= QVIRTIO_BLK_T_OUT
;
515 req
.data
= g_malloc0(512);
516 strcpy(req
.data
, "TEST");
518 req_addr
= virtio_blk_request(alloc
, &req
, 512);
522 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
523 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
524 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
525 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
527 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
528 QVIRTIO_BLK_TIMEOUT_US
);
530 status
= readb(req_addr
+ 528);
531 g_assert_cmpint(status
, ==, 0);
533 guest_free(alloc
, req_addr
);
536 req
.type
= QVIRTIO_BLK_T_IN
;
539 req
.data
= g_malloc0(512);
541 req_addr
= virtio_blk_request(alloc
, &req
, 512);
545 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
546 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
547 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
549 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
552 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
553 QVIRTIO_BLK_TIMEOUT_US
);
555 status
= readb(req_addr
+ 528);
556 g_assert_cmpint(status
, ==, 0);
558 data
= g_malloc0(512);
559 memread(req_addr
+ 16, data
, 512);
560 g_assert_cmpstr(data
, ==, "TEST");
563 guest_free(alloc
, req_addr
);
566 guest_free(alloc
, vqpci
->vq
.desc
);
567 pc_alloc_uninit(alloc
);
568 qpci_msix_disable(dev
->pdev
);
569 qvirtio_pci_device_disable(dev
);
575 static void pci_idx(void)
577 QVirtioPCIDevice
*dev
;
579 QVirtQueuePCI
*vqpci
;
580 QGuestAllocator
*alloc
;
590 bus
= pci_test_start();
591 alloc
= pc_alloc_init();
593 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
594 qpci_msix_enable(dev
->pdev
);
596 qvirtio_pci_set_msix_configuration_vector(dev
, alloc
, 0);
598 /* MSI-X is enabled */
599 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX
;
601 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
602 (uint64_t)(uintptr_t)addr
);
603 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
605 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
606 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
607 QVIRTIO_F_RING_INDIRECT_DESC
|
608 QVIRTIO_F_NOTIFY_ON_EMPTY
| QVIRTIO_BLK_F_SCSI
);
609 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
611 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
613 qvirtqueue_pci_msix_setup(dev
, vqpci
, alloc
, 1);
615 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
618 req
.type
= QVIRTIO_BLK_T_OUT
;
621 req
.data
= g_malloc0(512);
622 strcpy(req
.data
, "TEST");
624 req_addr
= virtio_blk_request(alloc
, &req
, 512);
628 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
629 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
630 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
631 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
633 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
634 QVIRTIO_BLK_TIMEOUT_US
);
637 req
.type
= QVIRTIO_BLK_T_OUT
;
640 req
.data
= g_malloc0(512);
641 strcpy(req
.data
, "TEST");
643 req_addr
= virtio_blk_request(alloc
, &req
, 512);
647 /* Notify after processing the third request */
648 qvirtqueue_set_used_event(&vqpci
->vq
, 2);
649 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
650 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
651 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
652 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
654 /* No notification expected */
655 status
= qvirtio_wait_status_byte_no_isr(&qvirtio_pci
, &dev
->vdev
,
656 &vqpci
->vq
, req_addr
+ 528,
657 QVIRTIO_BLK_TIMEOUT_US
);
658 g_assert_cmpint(status
, ==, 0);
660 guest_free(alloc
, req_addr
);
663 req
.type
= QVIRTIO_BLK_T_IN
;
666 req
.data
= g_malloc0(512);
668 req_addr
= virtio_blk_request(alloc
, &req
, 512);
672 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
673 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
674 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
676 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
678 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
679 QVIRTIO_BLK_TIMEOUT_US
);
681 status
= readb(req_addr
+ 528);
682 g_assert_cmpint(status
, ==, 0);
684 data
= g_malloc0(512);
685 memread(req_addr
+ 16, data
, 512);
686 g_assert_cmpstr(data
, ==, "TEST");
689 guest_free(alloc
, req_addr
);
692 guest_free(alloc
, vqpci
->vq
.desc
);
693 pc_alloc_uninit(alloc
);
694 qpci_msix_disable(dev
->pdev
);
695 qvirtio_pci_device_disable(dev
);
701 static void pci_hotplug(void)
704 QVirtioPCIDevice
*dev
;
706 bus
= pci_test_start();
708 /* plug secondary disk */
709 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP
,
710 "'drive': 'drive1'");
712 dev
= virtio_blk_pci_init(bus
, PCI_SLOT_HP
);
714 qvirtio_pci_device_disable(dev
);
717 /* unplug secondary disk */
718 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP
);
723 static void mmio_basic(void)
725 QVirtioMMIODevice
*dev
;
727 QGuestAllocator
*alloc
;
728 int n_size
= TEST_IMAGE_SIZE
/ 2;
733 dev
= qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR
, MMIO_PAGE_SIZE
);
734 g_assert(dev
!= NULL
);
735 g_assert_cmphex(dev
->vdev
.device_type
, ==, QVIRTIO_BLK_DEVICE_ID
);
737 qvirtio_reset(&qvirtio_mmio
, &dev
->vdev
);
738 qvirtio_set_acknowledge(&qvirtio_mmio
, &dev
->vdev
);
739 qvirtio_set_driver(&qvirtio_mmio
, &dev
->vdev
);
741 alloc
= generic_alloc_init(MMIO_RAM_ADDR
, MMIO_RAM_SIZE
, MMIO_PAGE_SIZE
);
742 vq
= qvirtqueue_setup(&qvirtio_mmio
, &dev
->vdev
, alloc
, 0);
744 test_basic(&qvirtio_mmio
, &dev
->vdev
, alloc
, vq
,
745 QVIRTIO_MMIO_DEVICE_SPECIFIC
);
747 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
748 " 'size': %d } }", n_size
);
750 qvirtio_wait_queue_isr(&qvirtio_mmio
, &dev
->vdev
, vq
,
751 QVIRTIO_BLK_TIMEOUT_US
);
753 capacity
= qvirtio_config_readq(&qvirtio_mmio
, &dev
->vdev
,
754 QVIRTIO_MMIO_DEVICE_SPECIFIC
);
755 g_assert_cmpint(capacity
, ==, n_size
/ 512);
758 guest_free(alloc
, vq
->desc
);
759 generic_alloc_uninit(alloc
);
764 int main(int argc
, char **argv
)
767 const char *arch
= qtest_get_arch();
769 g_test_init(&argc
, &argv
, NULL
);
771 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
772 qtest_add_func("/virtio/blk/pci/basic", pci_basic
);
773 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect
);
774 qtest_add_func("/virtio/blk/pci/config", pci_config
);
775 qtest_add_func("/virtio/blk/pci/msix", pci_msix
);
776 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
);