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"
14 #include "libqos/virtio.h"
15 #include "libqos/virtio-pci.h"
16 #include "libqos/virtio-mmio.h"
17 #include "libqos/pci-pc.h"
18 #include "libqos/malloc.h"
19 #include "libqos/malloc-pc.h"
20 #include "libqos/malloc-generic.h"
21 #include "qemu/bswap.h"
23 #define QVIRTIO_BLK_F_BARRIER 0x00000001
24 #define QVIRTIO_BLK_F_SIZE_MAX 0x00000002
25 #define QVIRTIO_BLK_F_SEG_MAX 0x00000004
26 #define QVIRTIO_BLK_F_GEOMETRY 0x00000010
27 #define QVIRTIO_BLK_F_RO 0x00000020
28 #define QVIRTIO_BLK_F_BLK_SIZE 0x00000040
29 #define QVIRTIO_BLK_F_SCSI 0x00000080
30 #define QVIRTIO_BLK_F_WCE 0x00000200
31 #define QVIRTIO_BLK_F_TOPOLOGY 0x00000400
32 #define QVIRTIO_BLK_F_CONFIG_WCE 0x00000800
34 #define QVIRTIO_BLK_T_IN 0
35 #define QVIRTIO_BLK_T_OUT 1
36 #define QVIRTIO_BLK_T_SCSI_CMD 2
37 #define QVIRTIO_BLK_T_SCSI_CMD_OUT 3
38 #define QVIRTIO_BLK_T_FLUSH 4
39 #define QVIRTIO_BLK_T_FLUSH_OUT 5
40 #define QVIRTIO_BLK_T_GET_ID 8
42 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
43 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
44 #define PCI_SLOT_HP 0x06
48 #define MMIO_PAGE_SIZE 4096
49 #define MMIO_DEV_BASE_ADDR 0x0A003E00
50 #define MMIO_RAM_ADDR 0x40000000
51 #define MMIO_RAM_SIZE 0x20000000
53 typedef struct QVirtioBlkReq
{
61 static char *drive_create(void)
64 char *tmp_path
= g_strdup("/tmp/qtest.XXXXXX");
66 /* Create a temporary raw image */
67 fd
= mkstemp(tmp_path
);
68 g_assert_cmpint(fd
, >=, 0);
69 ret
= ftruncate(fd
, TEST_IMAGE_SIZE
);
70 g_assert_cmpint(ret
, ==, 0);
76 static QPCIBus
*pci_test_start(void)
81 tmp_path
= drive_create();
83 cmdline
= g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw "
84 "-drive if=none,id=drive1,file=/dev/null,format=raw "
85 "-device virtio-blk-pci,id=drv0,drive=drive0,"
87 tmp_path
, PCI_SLOT
, PCI_FN
);
93 return qpci_init_pc();
96 static void arm_test_start(void)
101 tmp_path
= drive_create();
103 cmdline
= g_strdup_printf("-machine virt "
104 "-drive if=none,id=drive0,file=%s,format=raw "
105 "-device virtio-blk-device,drive=drive0",
107 qtest_start(cmdline
);
113 static void test_end(void)
118 static QVirtioPCIDevice
*virtio_blk_pci_init(QPCIBus
*bus
, int slot
)
120 QVirtioPCIDevice
*dev
;
122 dev
= qvirtio_pci_device_find(bus
, QVIRTIO_BLK_DEVICE_ID
);
123 g_assert(dev
!= NULL
);
124 g_assert_cmphex(dev
->vdev
.device_type
, ==, QVIRTIO_BLK_DEVICE_ID
);
125 g_assert_cmphex(dev
->pdev
->devfn
, ==, ((slot
<< 3) | PCI_FN
));
127 qvirtio_pci_device_enable(dev
);
128 qvirtio_reset(&qvirtio_pci
, &dev
->vdev
);
129 qvirtio_set_acknowledge(&qvirtio_pci
, &dev
->vdev
);
130 qvirtio_set_driver(&qvirtio_pci
, &dev
->vdev
);
135 static inline void virtio_blk_fix_request(QVirtioBlkReq
*req
)
137 #ifdef HOST_WORDS_BIGENDIAN
138 bool host_endian
= true;
140 bool host_endian
= false;
143 if (qtest_big_endian() != host_endian
) {
144 req
->type
= bswap32(req
->type
);
145 req
->ioprio
= bswap32(req
->ioprio
);
146 req
->sector
= bswap64(req
->sector
);
150 static uint64_t virtio_blk_request(QGuestAllocator
*alloc
, QVirtioBlkReq
*req
,
154 uint8_t status
= 0xFF;
156 g_assert_cmpuint(data_size
% 512, ==, 0);
157 addr
= guest_alloc(alloc
, sizeof(*req
) + data_size
);
159 virtio_blk_fix_request(req
);
161 memwrite(addr
, req
, 16);
162 memwrite(addr
+ 16, req
->data
, data_size
);
163 memwrite(addr
+ 16 + data_size
, &status
, sizeof(status
));
168 static void test_basic(const QVirtioBus
*bus
, QVirtioDevice
*dev
,
169 QGuestAllocator
*alloc
, QVirtQueue
*vq
, uint64_t device_specific
)
179 capacity
= qvirtio_config_readq(bus
, dev
, device_specific
);
181 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
183 features
= qvirtio_get_features(bus
, dev
);
184 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
185 QVIRTIO_F_RING_INDIRECT_DESC
| QVIRTIO_F_RING_EVENT_IDX
|
187 qvirtio_set_features(bus
, dev
, features
);
189 qvirtio_set_driver_ok(bus
, dev
);
191 /* Write and read with 3 descriptor layout */
193 req
.type
= QVIRTIO_BLK_T_OUT
;
196 req
.data
= g_malloc0(512);
197 strcpy(req
.data
, "TEST");
199 req_addr
= virtio_blk_request(alloc
, &req
, 512);
203 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
204 qvirtqueue_add(vq
, req_addr
+ 16, 512, false, true);
205 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
207 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
209 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
210 status
= readb(req_addr
+ 528);
211 g_assert_cmpint(status
, ==, 0);
213 guest_free(alloc
, req_addr
);
216 req
.type
= QVIRTIO_BLK_T_IN
;
219 req
.data
= g_malloc0(512);
221 req_addr
= virtio_blk_request(alloc
, &req
, 512);
225 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
226 qvirtqueue_add(vq
, req_addr
+ 16, 512, true, true);
227 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
229 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
231 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
232 status
= readb(req_addr
+ 528);
233 g_assert_cmpint(status
, ==, 0);
235 data
= g_malloc0(512);
236 memread(req_addr
+ 16, data
, 512);
237 g_assert_cmpstr(data
, ==, "TEST");
240 guest_free(alloc
, req_addr
);
242 if (features
& QVIRTIO_F_ANY_LAYOUT
) {
243 /* Write and read with 2 descriptor layout */
245 req
.type
= QVIRTIO_BLK_T_OUT
;
248 req
.data
= g_malloc0(512);
249 strcpy(req
.data
, "TEST");
251 req_addr
= virtio_blk_request(alloc
, &req
, 512);
255 free_head
= qvirtqueue_add(vq
, req_addr
, 528, false, true);
256 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
257 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
259 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
260 status
= readb(req_addr
+ 528);
261 g_assert_cmpint(status
, ==, 0);
263 guest_free(alloc
, req_addr
);
266 req
.type
= QVIRTIO_BLK_T_IN
;
269 req
.data
= g_malloc0(512);
271 req_addr
= virtio_blk_request(alloc
, &req
, 512);
275 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
276 qvirtqueue_add(vq
, req_addr
+ 16, 513, true, false);
278 qvirtqueue_kick(bus
, dev
, vq
, free_head
);
280 qvirtio_wait_queue_isr(bus
, dev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
281 status
= readb(req_addr
+ 528);
282 g_assert_cmpint(status
, ==, 0);
284 data
= g_malloc0(512);
285 memread(req_addr
+ 16, data
, 512);
286 g_assert_cmpstr(data
, ==, "TEST");
289 guest_free(alloc
, req_addr
);
293 static void pci_basic(void)
295 QVirtioPCIDevice
*dev
;
297 QVirtQueuePCI
*vqpci
;
298 QGuestAllocator
*alloc
;
301 bus
= pci_test_start();
302 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
304 alloc
= pc_alloc_init();
305 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
308 /* MSI-X is not enabled */
309 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
311 test_basic(&qvirtio_pci
, &dev
->vdev
, alloc
, &vqpci
->vq
,
312 (uint64_t)(uintptr_t)addr
);
315 guest_free(alloc
, vqpci
->vq
.desc
);
316 pc_alloc_uninit(alloc
);
317 qvirtio_pci_device_disable(dev
);
323 static void pci_indirect(void)
325 QVirtioPCIDevice
*dev
;
327 QVirtQueuePCI
*vqpci
;
328 QGuestAllocator
*alloc
;
330 QVRingIndirectDesc
*indirect
;
339 bus
= pci_test_start();
341 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
343 /* MSI-X is not enabled */
344 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
346 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
347 (uint64_t)(uintptr_t)addr
);
348 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
350 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
351 g_assert_cmphex(features
& QVIRTIO_F_RING_INDIRECT_DESC
, !=, 0);
352 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
| QVIRTIO_F_RING_EVENT_IDX
|
354 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
356 alloc
= pc_alloc_init();
357 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
359 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
362 req
.type
= QVIRTIO_BLK_T_OUT
;
365 req
.data
= g_malloc0(512);
366 strcpy(req
.data
, "TEST");
368 req_addr
= virtio_blk_request(alloc
, &req
, 512);
372 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, alloc
, 2);
373 qvring_indirect_desc_add(indirect
, req_addr
, 528, false);
374 qvring_indirect_desc_add(indirect
, req_addr
+ 528, 1, true);
375 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
376 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
378 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
379 QVIRTIO_BLK_TIMEOUT_US
);
380 status
= readb(req_addr
+ 528);
381 g_assert_cmpint(status
, ==, 0);
384 guest_free(alloc
, req_addr
);
387 req
.type
= QVIRTIO_BLK_T_IN
;
390 req
.data
= g_malloc0(512);
391 strcpy(req
.data
, "TEST");
393 req_addr
= virtio_blk_request(alloc
, &req
, 512);
397 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, alloc
, 2);
398 qvring_indirect_desc_add(indirect
, req_addr
, 16, false);
399 qvring_indirect_desc_add(indirect
, req_addr
+ 16, 513, true);
400 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
401 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
403 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
404 QVIRTIO_BLK_TIMEOUT_US
);
405 status
= readb(req_addr
+ 528);
406 g_assert_cmpint(status
, ==, 0);
408 data
= g_malloc0(512);
409 memread(req_addr
+ 16, data
, 512);
410 g_assert_cmpstr(data
, ==, "TEST");
414 guest_free(alloc
, req_addr
);
417 guest_free(alloc
, vqpci
->vq
.desc
);
418 pc_alloc_uninit(alloc
);
419 qvirtio_pci_device_disable(dev
);
425 static void pci_config(void)
427 QVirtioPCIDevice
*dev
;
429 int n_size
= TEST_IMAGE_SIZE
/ 2;
433 bus
= pci_test_start();
435 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
437 /* MSI-X is not enabled */
438 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX
;
440 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
441 (uint64_t)(uintptr_t)addr
);
442 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
444 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
446 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
447 " 'size': %d } }", n_size
);
448 qvirtio_wait_config_isr(&qvirtio_pci
, &dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
450 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
451 (uint64_t)(uintptr_t)addr
);
452 g_assert_cmpint(capacity
, ==, n_size
/ 512);
454 qvirtio_pci_device_disable(dev
);
460 static void pci_msix(void)
462 QVirtioPCIDevice
*dev
;
464 QVirtQueuePCI
*vqpci
;
465 QGuestAllocator
*alloc
;
467 int n_size
= TEST_IMAGE_SIZE
/ 2;
476 bus
= pci_test_start();
477 alloc
= pc_alloc_init();
479 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
480 qpci_msix_enable(dev
->pdev
);
482 qvirtio_pci_set_msix_configuration_vector(dev
, alloc
, 0);
484 /* MSI-X is enabled */
485 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX
;
487 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
488 (uint64_t)(uintptr_t)addr
);
489 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
491 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
492 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
493 QVIRTIO_F_RING_INDIRECT_DESC
|
494 QVIRTIO_F_RING_EVENT_IDX
| QVIRTIO_BLK_F_SCSI
);
495 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
497 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
499 qvirtqueue_pci_msix_setup(dev
, vqpci
, alloc
, 1);
501 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
503 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
504 " 'size': %d } }", n_size
);
506 qvirtio_wait_config_isr(&qvirtio_pci
, &dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
508 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
509 (uint64_t)(uintptr_t)addr
);
510 g_assert_cmpint(capacity
, ==, n_size
/ 512);
513 req
.type
= QVIRTIO_BLK_T_OUT
;
516 req
.data
= g_malloc0(512);
517 strcpy(req
.data
, "TEST");
519 req_addr
= virtio_blk_request(alloc
, &req
, 512);
523 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
524 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
525 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
526 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
528 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
529 QVIRTIO_BLK_TIMEOUT_US
);
531 status
= readb(req_addr
+ 528);
532 g_assert_cmpint(status
, ==, 0);
534 guest_free(alloc
, req_addr
);
537 req
.type
= QVIRTIO_BLK_T_IN
;
540 req
.data
= g_malloc0(512);
542 req_addr
= virtio_blk_request(alloc
, &req
, 512);
546 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
547 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
548 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
550 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
553 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
554 QVIRTIO_BLK_TIMEOUT_US
);
556 status
= readb(req_addr
+ 528);
557 g_assert_cmpint(status
, ==, 0);
559 data
= g_malloc0(512);
560 memread(req_addr
+ 16, data
, 512);
561 g_assert_cmpstr(data
, ==, "TEST");
564 guest_free(alloc
, req_addr
);
567 guest_free(alloc
, vqpci
->vq
.desc
);
568 pc_alloc_uninit(alloc
);
569 qpci_msix_disable(dev
->pdev
);
570 qvirtio_pci_device_disable(dev
);
576 static void pci_idx(void)
578 QVirtioPCIDevice
*dev
;
580 QVirtQueuePCI
*vqpci
;
581 QGuestAllocator
*alloc
;
591 bus
= pci_test_start();
592 alloc
= pc_alloc_init();
594 dev
= virtio_blk_pci_init(bus
, PCI_SLOT
);
595 qpci_msix_enable(dev
->pdev
);
597 qvirtio_pci_set_msix_configuration_vector(dev
, alloc
, 0);
599 /* MSI-X is enabled */
600 addr
= dev
->addr
+ QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX
;
602 capacity
= qvirtio_config_readq(&qvirtio_pci
, &dev
->vdev
,
603 (uint64_t)(uintptr_t)addr
);
604 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
606 features
= qvirtio_get_features(&qvirtio_pci
, &dev
->vdev
);
607 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
608 QVIRTIO_F_RING_INDIRECT_DESC
|
609 QVIRTIO_F_NOTIFY_ON_EMPTY
| QVIRTIO_BLK_F_SCSI
);
610 qvirtio_set_features(&qvirtio_pci
, &dev
->vdev
, features
);
612 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&qvirtio_pci
, &dev
->vdev
,
614 qvirtqueue_pci_msix_setup(dev
, vqpci
, alloc
, 1);
616 qvirtio_set_driver_ok(&qvirtio_pci
, &dev
->vdev
);
619 req
.type
= QVIRTIO_BLK_T_OUT
;
622 req
.data
= g_malloc0(512);
623 strcpy(req
.data
, "TEST");
625 req_addr
= virtio_blk_request(alloc
, &req
, 512);
629 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
630 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
631 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
632 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
634 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
635 QVIRTIO_BLK_TIMEOUT_US
);
638 req
.type
= QVIRTIO_BLK_T_OUT
;
641 req
.data
= g_malloc0(512);
642 strcpy(req
.data
, "TEST");
644 req_addr
= virtio_blk_request(alloc
, &req
, 512);
648 /* Notify after processing the third request */
649 qvirtqueue_set_used_event(&vqpci
->vq
, 2);
650 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
651 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
652 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
653 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
655 /* No notification expected */
656 status
= qvirtio_wait_status_byte_no_isr(&qvirtio_pci
, &dev
->vdev
,
657 &vqpci
->vq
, req_addr
+ 528,
658 QVIRTIO_BLK_TIMEOUT_US
);
659 g_assert_cmpint(status
, ==, 0);
661 guest_free(alloc
, req_addr
);
664 req
.type
= QVIRTIO_BLK_T_IN
;
667 req
.data
= g_malloc0(512);
669 req_addr
= virtio_blk_request(alloc
, &req
, 512);
673 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
674 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
675 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
677 qvirtqueue_kick(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
, free_head
);
679 qvirtio_wait_queue_isr(&qvirtio_pci
, &dev
->vdev
, &vqpci
->vq
,
680 QVIRTIO_BLK_TIMEOUT_US
);
682 status
= readb(req_addr
+ 528);
683 g_assert_cmpint(status
, ==, 0);
685 data
= g_malloc0(512);
686 memread(req_addr
+ 16, data
, 512);
687 g_assert_cmpstr(data
, ==, "TEST");
690 guest_free(alloc
, req_addr
);
693 guest_free(alloc
, vqpci
->vq
.desc
);
694 pc_alloc_uninit(alloc
);
695 qpci_msix_disable(dev
->pdev
);
696 qvirtio_pci_device_disable(dev
);
702 static void pci_hotplug(void)
705 QVirtioPCIDevice
*dev
;
707 bus
= pci_test_start();
709 /* plug secondary disk */
710 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP
,
711 "'drive': 'drive1'");
713 dev
= virtio_blk_pci_init(bus
, PCI_SLOT_HP
);
715 qvirtio_pci_device_disable(dev
);
718 /* unplug secondary disk */
719 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP
);
724 static void mmio_basic(void)
726 QVirtioMMIODevice
*dev
;
728 QGuestAllocator
*alloc
;
729 int n_size
= TEST_IMAGE_SIZE
/ 2;
734 dev
= qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR
, MMIO_PAGE_SIZE
);
735 g_assert(dev
!= NULL
);
736 g_assert_cmphex(dev
->vdev
.device_type
, ==, QVIRTIO_BLK_DEVICE_ID
);
738 qvirtio_reset(&qvirtio_mmio
, &dev
->vdev
);
739 qvirtio_set_acknowledge(&qvirtio_mmio
, &dev
->vdev
);
740 qvirtio_set_driver(&qvirtio_mmio
, &dev
->vdev
);
742 alloc
= generic_alloc_init(MMIO_RAM_ADDR
, MMIO_RAM_SIZE
, MMIO_PAGE_SIZE
);
743 vq
= qvirtqueue_setup(&qvirtio_mmio
, &dev
->vdev
, alloc
, 0);
745 test_basic(&qvirtio_mmio
, &dev
->vdev
, alloc
, vq
,
746 QVIRTIO_MMIO_DEVICE_SPECIFIC
);
748 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
749 " 'size': %d } }", n_size
);
751 qvirtio_wait_queue_isr(&qvirtio_mmio
, &dev
->vdev
, vq
,
752 QVIRTIO_BLK_TIMEOUT_US
);
754 capacity
= qvirtio_config_readq(&qvirtio_mmio
, &dev
->vdev
,
755 QVIRTIO_MMIO_DEVICE_SPECIFIC
);
756 g_assert_cmpint(capacity
, ==, n_size
/ 512);
759 guest_free(alloc
, vq
->desc
);
760 generic_alloc_uninit(alloc
);
765 int main(int argc
, char **argv
)
768 const char *arch
= qtest_get_arch();
770 g_test_init(&argc
, &argv
, NULL
);
772 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
773 qtest_add_func("/virtio/blk/pci/basic", pci_basic
);
774 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect
);
775 qtest_add_func("/virtio/blk/pci/config", pci_config
);
776 qtest_add_func("/virtio/blk/pci/msix", pci_msix
);
777 qtest_add_func("/virtio/blk/pci/idx", pci_idx
);
778 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug
);
779 } else if (strcmp(arch
, "arm") == 0) {
780 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic
);