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 "qemu/bswap.h"
20 #include "standard-headers/linux/virtio_ids.h"
21 #include "standard-headers/linux/virtio_config.h"
22 #include "standard-headers/linux/virtio_ring.h"
23 #include "standard-headers/linux/virtio_blk.h"
24 #include "standard-headers/linux/virtio_pci.h"
26 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
27 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
28 #define PCI_SLOT_HP 0x06
32 #define MMIO_PAGE_SIZE 4096
33 #define MMIO_DEV_BASE_ADDR 0x0A003E00
34 #define MMIO_RAM_ADDR 0x40000000
35 #define MMIO_RAM_SIZE 0x20000000
37 typedef struct QVirtioBlkReq
{
45 static char *drive_create(void)
48 char *tmp_path
= g_strdup("/tmp/qtest.XXXXXX");
50 /* Create a temporary raw image */
51 fd
= mkstemp(tmp_path
);
52 g_assert_cmpint(fd
, >=, 0);
53 ret
= ftruncate(fd
, TEST_IMAGE_SIZE
);
54 g_assert_cmpint(ret
, ==, 0);
60 static QOSState
*pci_test_start(void)
63 const char *arch
= qtest_get_arch();
65 const char *cmd
= "-drive if=none,id=drive0,file=%s,format=raw "
66 "-drive if=none,id=drive1,file=null-co://,format=raw "
67 "-device virtio-blk-pci,id=drv0,drive=drive0,"
70 tmp_path
= drive_create();
72 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
73 qs
= qtest_pc_boot(cmd
, tmp_path
, PCI_SLOT
, PCI_FN
);
74 } else if (strcmp(arch
, "ppc64") == 0) {
75 qs
= qtest_spapr_boot(cmd
, tmp_path
, PCI_SLOT
, PCI_FN
);
77 g_printerr("virtio-blk tests are only available on x86 or ppc64\n");
85 static void arm_test_start(void)
89 tmp_path
= drive_create();
91 global_qtest
= qtest_startf("-machine virt "
92 "-drive if=none,id=drive0,file=%s,format=raw "
93 "-device virtio-blk-device,drive=drive0",
99 static void test_end(void)
104 static QVirtioPCIDevice
*virtio_blk_pci_init(QPCIBus
*bus
, int slot
)
106 QVirtioPCIDevice
*dev
;
108 dev
= qvirtio_pci_device_find_slot(bus
, VIRTIO_ID_BLOCK
, slot
);
109 g_assert(dev
!= NULL
);
110 g_assert_cmphex(dev
->vdev
.device_type
, ==, VIRTIO_ID_BLOCK
);
111 g_assert_cmphex(dev
->pdev
->devfn
, ==, ((slot
<< 3) | PCI_FN
));
113 qvirtio_pci_device_enable(dev
);
114 qvirtio_reset(&dev
->vdev
);
115 qvirtio_set_acknowledge(&dev
->vdev
);
116 qvirtio_set_driver(&dev
->vdev
);
121 static inline void virtio_blk_fix_request(QVirtioDevice
*d
, QVirtioBlkReq
*req
)
123 #ifdef HOST_WORDS_BIGENDIAN
124 const bool host_is_big_endian
= true;
126 const bool host_is_big_endian
= false;
129 if (qvirtio_is_big_endian(d
) != host_is_big_endian
) {
130 req
->type
= bswap32(req
->type
);
131 req
->ioprio
= bswap32(req
->ioprio
);
132 req
->sector
= bswap64(req
->sector
);
136 static uint64_t virtio_blk_request(QGuestAllocator
*alloc
, QVirtioDevice
*d
,
137 QVirtioBlkReq
*req
, uint64_t data_size
)
140 uint8_t status
= 0xFF;
142 g_assert_cmpuint(data_size
% 512, ==, 0);
143 addr
= guest_alloc(alloc
, sizeof(*req
) + data_size
);
145 virtio_blk_fix_request(d
, req
);
147 memwrite(addr
, req
, 16);
148 memwrite(addr
+ 16, req
->data
, data_size
);
149 memwrite(addr
+ 16 + data_size
, &status
, sizeof(status
));
154 static void test_basic(QVirtioDevice
*dev
, QGuestAllocator
*alloc
,
165 capacity
= qvirtio_config_readq(dev
, 0);
167 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
169 features
= qvirtio_get_features(dev
);
170 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
171 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
172 (1u << VIRTIO_RING_F_EVENT_IDX
) |
173 (1u << VIRTIO_BLK_F_SCSI
));
174 qvirtio_set_features(dev
, features
);
176 qvirtio_set_driver_ok(dev
);
178 /* Write and read with 3 descriptor layout */
180 req
.type
= VIRTIO_BLK_T_OUT
;
183 req
.data
= g_malloc0(512);
184 strcpy(req
.data
, "TEST");
186 req_addr
= virtio_blk_request(alloc
, dev
, &req
, 512);
190 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
191 qvirtqueue_add(vq
, req_addr
+ 16, 512, false, true);
192 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
194 qvirtqueue_kick(dev
, vq
, free_head
);
196 qvirtio_wait_used_elem(dev
, vq
, free_head
, NULL
, QVIRTIO_BLK_TIMEOUT_US
);
197 status
= readb(req_addr
+ 528);
198 g_assert_cmpint(status
, ==, 0);
200 guest_free(alloc
, req_addr
);
203 req
.type
= VIRTIO_BLK_T_IN
;
206 req
.data
= g_malloc0(512);
208 req_addr
= virtio_blk_request(alloc
, dev
, &req
, 512);
212 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
213 qvirtqueue_add(vq
, req_addr
+ 16, 512, true, true);
214 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
216 qvirtqueue_kick(dev
, vq
, free_head
);
218 qvirtio_wait_used_elem(dev
, vq
, free_head
, NULL
, QVIRTIO_BLK_TIMEOUT_US
);
219 status
= readb(req_addr
+ 528);
220 g_assert_cmpint(status
, ==, 0);
222 data
= g_malloc0(512);
223 memread(req_addr
+ 16, data
, 512);
224 g_assert_cmpstr(data
, ==, "TEST");
227 guest_free(alloc
, req_addr
);
229 if (features
& (1u << VIRTIO_F_ANY_LAYOUT
)) {
230 /* Write and read with 2 descriptor layout */
232 req
.type
= VIRTIO_BLK_T_OUT
;
235 req
.data
= g_malloc0(512);
236 strcpy(req
.data
, "TEST");
238 req_addr
= virtio_blk_request(alloc
, dev
, &req
, 512);
242 free_head
= qvirtqueue_add(vq
, req_addr
, 528, false, true);
243 qvirtqueue_add(vq
, req_addr
+ 528, 1, true, false);
244 qvirtqueue_kick(dev
, vq
, free_head
);
246 qvirtio_wait_used_elem(dev
, vq
, free_head
, NULL
,
247 QVIRTIO_BLK_TIMEOUT_US
);
248 status
= readb(req_addr
+ 528);
249 g_assert_cmpint(status
, ==, 0);
251 guest_free(alloc
, req_addr
);
254 req
.type
= VIRTIO_BLK_T_IN
;
257 req
.data
= g_malloc0(512);
259 req_addr
= virtio_blk_request(alloc
, dev
, &req
, 512);
263 free_head
= qvirtqueue_add(vq
, req_addr
, 16, false, true);
264 qvirtqueue_add(vq
, req_addr
+ 16, 513, true, false);
266 qvirtqueue_kick(dev
, vq
, free_head
);
268 qvirtio_wait_used_elem(dev
, vq
, free_head
, NULL
,
269 QVIRTIO_BLK_TIMEOUT_US
);
270 status
= readb(req_addr
+ 528);
271 g_assert_cmpint(status
, ==, 0);
273 data
= g_malloc0(512);
274 memread(req_addr
+ 16, data
, 512);
275 g_assert_cmpstr(data
, ==, "TEST");
278 guest_free(alloc
, req_addr
);
282 static void pci_basic(void)
284 QVirtioPCIDevice
*dev
;
286 QVirtQueuePCI
*vqpci
;
288 qs
= pci_test_start();
289 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
291 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&dev
->vdev
, qs
->alloc
, 0);
293 test_basic(&dev
->vdev
, qs
->alloc
, &vqpci
->vq
);
296 qvirtqueue_cleanup(dev
->vdev
.bus
, &vqpci
->vq
, qs
->alloc
);
297 qvirtio_pci_device_disable(dev
);
298 qvirtio_pci_device_free(dev
);
302 static void pci_indirect(void)
304 QVirtioPCIDevice
*dev
;
305 QVirtQueuePCI
*vqpci
;
308 QVRingIndirectDesc
*indirect
;
316 qs
= pci_test_start();
318 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
320 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
321 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
323 features
= qvirtio_get_features(&dev
->vdev
);
324 g_assert_cmphex(features
& (1u << VIRTIO_RING_F_INDIRECT_DESC
), !=, 0);
325 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
326 (1u << VIRTIO_RING_F_EVENT_IDX
) |
327 (1u << VIRTIO_BLK_F_SCSI
));
328 qvirtio_set_features(&dev
->vdev
, features
);
330 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&dev
->vdev
, qs
->alloc
, 0);
331 qvirtio_set_driver_ok(&dev
->vdev
);
334 req
.type
= VIRTIO_BLK_T_OUT
;
337 req
.data
= g_malloc0(512);
338 strcpy(req
.data
, "TEST");
340 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
344 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, qs
->alloc
, 2);
345 qvring_indirect_desc_add(indirect
, req_addr
, 528, false);
346 qvring_indirect_desc_add(indirect
, req_addr
+ 528, 1, true);
347 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
348 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
350 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
351 QVIRTIO_BLK_TIMEOUT_US
);
352 status
= readb(req_addr
+ 528);
353 g_assert_cmpint(status
, ==, 0);
356 guest_free(qs
->alloc
, req_addr
);
359 req
.type
= VIRTIO_BLK_T_IN
;
362 req
.data
= g_malloc0(512);
363 strcpy(req
.data
, "TEST");
365 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
369 indirect
= qvring_indirect_desc_setup(&dev
->vdev
, qs
->alloc
, 2);
370 qvring_indirect_desc_add(indirect
, req_addr
, 16, false);
371 qvring_indirect_desc_add(indirect
, req_addr
+ 16, 513, true);
372 free_head
= qvirtqueue_add_indirect(&vqpci
->vq
, indirect
);
373 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
375 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
376 QVIRTIO_BLK_TIMEOUT_US
);
377 status
= readb(req_addr
+ 528);
378 g_assert_cmpint(status
, ==, 0);
380 data
= g_malloc0(512);
381 memread(req_addr
+ 16, data
, 512);
382 g_assert_cmpstr(data
, ==, "TEST");
386 guest_free(qs
->alloc
, req_addr
);
389 qvirtqueue_cleanup(dev
->vdev
.bus
, &vqpci
->vq
, qs
->alloc
);
390 qvirtio_pci_device_disable(dev
);
391 qvirtio_pci_device_free(dev
);
395 static void pci_config(void)
397 QVirtioPCIDevice
*dev
;
399 int n_size
= TEST_IMAGE_SIZE
/ 2;
402 qs
= pci_test_start();
404 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
406 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
407 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
409 qvirtio_set_driver_ok(&dev
->vdev
);
411 qmp_discard_response("{ 'execute': 'block_resize', "
412 " 'arguments': { 'device': 'drive0', "
413 " 'size': %d } }", n_size
);
414 qvirtio_wait_config_isr(&dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
416 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
417 g_assert_cmpint(capacity
, ==, n_size
/ 512);
419 qvirtio_pci_device_disable(dev
);
420 qvirtio_pci_device_free(dev
);
425 static void pci_msix(void)
427 QVirtioPCIDevice
*dev
;
429 QVirtQueuePCI
*vqpci
;
431 int n_size
= TEST_IMAGE_SIZE
/ 2;
439 qs
= pci_test_start();
441 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
442 qpci_msix_enable(dev
->pdev
);
444 qvirtio_pci_set_msix_configuration_vector(dev
, qs
->alloc
, 0);
446 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
447 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
449 features
= qvirtio_get_features(&dev
->vdev
);
450 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
451 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
452 (1u << VIRTIO_RING_F_EVENT_IDX
) |
453 (1u << VIRTIO_BLK_F_SCSI
));
454 qvirtio_set_features(&dev
->vdev
, features
);
456 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&dev
->vdev
, qs
->alloc
, 0);
457 qvirtqueue_pci_msix_setup(dev
, vqpci
, qs
->alloc
, 1);
459 qvirtio_set_driver_ok(&dev
->vdev
);
461 qmp_discard_response("{ 'execute': 'block_resize', "
462 " 'arguments': { 'device': 'drive0', "
463 " 'size': %d } }", n_size
);
465 qvirtio_wait_config_isr(&dev
->vdev
, QVIRTIO_BLK_TIMEOUT_US
);
467 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
468 g_assert_cmpint(capacity
, ==, n_size
/ 512);
471 req
.type
= VIRTIO_BLK_T_OUT
;
474 req
.data
= g_malloc0(512);
475 strcpy(req
.data
, "TEST");
477 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
481 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
482 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
483 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
484 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
486 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
487 QVIRTIO_BLK_TIMEOUT_US
);
489 status
= readb(req_addr
+ 528);
490 g_assert_cmpint(status
, ==, 0);
492 guest_free(qs
->alloc
, req_addr
);
495 req
.type
= VIRTIO_BLK_T_IN
;
498 req
.data
= g_malloc0(512);
500 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
504 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
505 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
506 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
508 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
511 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
512 QVIRTIO_BLK_TIMEOUT_US
);
514 status
= readb(req_addr
+ 528);
515 g_assert_cmpint(status
, ==, 0);
517 data
= g_malloc0(512);
518 memread(req_addr
+ 16, data
, 512);
519 g_assert_cmpstr(data
, ==, "TEST");
522 guest_free(qs
->alloc
, req_addr
);
525 qvirtqueue_cleanup(dev
->vdev
.bus
, &vqpci
->vq
, qs
->alloc
);
526 qpci_msix_disable(dev
->pdev
);
527 qvirtio_pci_device_disable(dev
);
528 qvirtio_pci_device_free(dev
);
532 static void pci_idx(void)
534 QVirtioPCIDevice
*dev
;
536 QVirtQueuePCI
*vqpci
;
547 qs
= pci_test_start();
549 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT
);
550 qpci_msix_enable(dev
->pdev
);
552 qvirtio_pci_set_msix_configuration_vector(dev
, qs
->alloc
, 0);
554 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
555 g_assert_cmpint(capacity
, ==, TEST_IMAGE_SIZE
/ 512);
557 features
= qvirtio_get_features(&dev
->vdev
);
558 features
= features
& ~(QVIRTIO_F_BAD_FEATURE
|
559 (1u << VIRTIO_RING_F_INDIRECT_DESC
) |
560 (1u << VIRTIO_F_NOTIFY_ON_EMPTY
) |
561 (1u << VIRTIO_BLK_F_SCSI
));
562 qvirtio_set_features(&dev
->vdev
, features
);
564 vqpci
= (QVirtQueuePCI
*)qvirtqueue_setup(&dev
->vdev
, qs
->alloc
, 0);
565 qvirtqueue_pci_msix_setup(dev
, vqpci
, qs
->alloc
, 1);
567 qvirtio_set_driver_ok(&dev
->vdev
);
570 req
.type
= VIRTIO_BLK_T_OUT
;
573 req
.data
= g_malloc0(512);
574 strcpy(req
.data
, "TEST");
576 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
580 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
581 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
582 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
583 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
585 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, free_head
, NULL
,
586 QVIRTIO_BLK_TIMEOUT_US
);
589 req
.type
= VIRTIO_BLK_T_OUT
;
592 req
.data
= g_malloc0(512);
593 strcpy(req
.data
, "TEST");
595 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
599 /* Notify after processing the third request */
600 qvirtqueue_set_used_event(&vqpci
->vq
, 2);
601 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
602 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, false, true);
603 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
604 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
605 write_head
= free_head
;
607 /* No notification expected */
608 status
= qvirtio_wait_status_byte_no_isr(&dev
->vdev
,
609 &vqpci
->vq
, req_addr
+ 528,
610 QVIRTIO_BLK_TIMEOUT_US
);
611 g_assert_cmpint(status
, ==, 0);
613 guest_free(qs
->alloc
, req_addr
);
616 req
.type
= VIRTIO_BLK_T_IN
;
619 req
.data
= g_malloc0(512);
621 req_addr
= virtio_blk_request(qs
->alloc
, &dev
->vdev
, &req
, 512);
625 free_head
= qvirtqueue_add(&vqpci
->vq
, req_addr
, 16, false, true);
626 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 16, 512, true, true);
627 qvirtqueue_add(&vqpci
->vq
, req_addr
+ 528, 1, true, false);
629 qvirtqueue_kick(&dev
->vdev
, &vqpci
->vq
, free_head
);
631 /* We get just one notification for both requests */
632 qvirtio_wait_used_elem(&dev
->vdev
, &vqpci
->vq
, write_head
, NULL
,
633 QVIRTIO_BLK_TIMEOUT_US
);
634 g_assert(qvirtqueue_get_buf(&vqpci
->vq
, &desc_idx
, NULL
));
635 g_assert_cmpint(desc_idx
, ==, free_head
);
637 status
= readb(req_addr
+ 528);
638 g_assert_cmpint(status
, ==, 0);
640 data
= g_malloc0(512);
641 memread(req_addr
+ 16, data
, 512);
642 g_assert_cmpstr(data
, ==, "TEST");
645 guest_free(qs
->alloc
, req_addr
);
648 qvirtqueue_cleanup(dev
->vdev
.bus
, &vqpci
->vq
, qs
->alloc
);
649 qpci_msix_disable(dev
->pdev
);
650 qvirtio_pci_device_disable(dev
);
651 qvirtio_pci_device_free(dev
);
655 static void pci_hotplug(void)
657 QVirtioPCIDevice
*dev
;
659 const char *arch
= qtest_get_arch();
661 qs
= pci_test_start();
663 /* plug secondary disk */
664 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP
,
665 "'drive': 'drive1'");
667 dev
= virtio_blk_pci_init(qs
->pcibus
, PCI_SLOT_HP
);
669 qvirtio_pci_device_disable(dev
);
670 qvirtio_pci_device_free(dev
);
672 /* unplug secondary disk */
673 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
674 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP
);
680 * Check that setting the vring addr on a non-existent virtqueue does
683 static void test_nonexistent_virtqueue(void)
689 qs
= pci_test_start();
690 dev
= qpci_device_find(qs
->pcibus
, QPCI_DEVFN(4, 0));
691 g_assert(dev
!= NULL
);
693 qpci_device_enable(dev
);
694 bar0
= qpci_iomap(dev
, 0, NULL
);
696 qpci_io_writeb(dev
, bar0
, VIRTIO_PCI_QUEUE_SEL
, 2);
697 qpci_io_writel(dev
, bar0
, VIRTIO_PCI_QUEUE_PFN
, 1);
703 static void mmio_basic(void)
705 QVirtioMMIODevice
*dev
;
707 QGuestAllocator
*alloc
;
708 int n_size
= TEST_IMAGE_SIZE
/ 2;
713 dev
= qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR
, MMIO_PAGE_SIZE
);
714 g_assert(dev
!= NULL
);
715 g_assert_cmphex(dev
->vdev
.device_type
, ==, VIRTIO_ID_BLOCK
);
717 qvirtio_reset(&dev
->vdev
);
718 qvirtio_set_acknowledge(&dev
->vdev
);
719 qvirtio_set_driver(&dev
->vdev
);
721 alloc
= generic_alloc_init(MMIO_RAM_ADDR
, MMIO_RAM_SIZE
, MMIO_PAGE_SIZE
);
722 vq
= qvirtqueue_setup(&dev
->vdev
, alloc
, 0);
724 test_basic(&dev
->vdev
, alloc
, vq
);
726 qmp_discard_response("{ 'execute': 'block_resize', "
727 " 'arguments': { 'device': 'drive0', "
728 " 'size': %d } }", n_size
);
730 qvirtio_wait_queue_isr(&dev
->vdev
, vq
, QVIRTIO_BLK_TIMEOUT_US
);
732 capacity
= qvirtio_config_readq(&dev
->vdev
, 0);
733 g_assert_cmpint(capacity
, ==, n_size
/ 512);
736 qvirtqueue_cleanup(dev
->vdev
.bus
, vq
, alloc
);
738 generic_alloc_uninit(alloc
);
742 int main(int argc
, char **argv
)
744 const char *arch
= qtest_get_arch();
746 g_test_init(&argc
, &argv
, NULL
);
748 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0 ||
749 strcmp(arch
, "ppc64") == 0) {
750 qtest_add_func("/virtio/blk/pci/basic", pci_basic
);
751 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect
);
752 qtest_add_func("/virtio/blk/pci/config", pci_config
);
753 qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue
);
754 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
755 qtest_add_func("/virtio/blk/pci/msix", pci_msix
);
756 qtest_add_func("/virtio/blk/pci/idx", pci_idx
);
758 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug
);
759 } else if (strcmp(arch
, "arm") == 0) {
760 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic
);