Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20180214a' into...
[qemu.git] / tests / virtio-blk-test.c
blob9be9ffb37823bfc09ee0658c935aed77b0c59a6a
1 /*
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.
9 */
11 #include "qemu/osdep.h"
12 #include "libqtest.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
29 #define PCI_SLOT 0x04
30 #define PCI_FN 0x00
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 {
38 uint32_t type;
39 uint32_t ioprio;
40 uint64_t sector;
41 char *data;
42 uint8_t status;
43 } QVirtioBlkReq;
45 static char *drive_create(void)
47 int fd, ret;
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);
55 close(fd);
57 return tmp_path;
60 static QOSState *pci_test_start(void)
62 QOSState *qs;
63 const char *arch = qtest_get_arch();
64 char *tmp_path;
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,"
68 "addr=%x.%x";
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);
76 } else {
77 g_printerr("virtio-blk tests are only available on x86 or ppc64\n");
78 exit(EXIT_FAILURE);
80 global_qtest = qs->qts;
81 unlink(tmp_path);
82 g_free(tmp_path);
83 return qs;
86 static void arm_test_start(void)
88 char *tmp_path;
90 tmp_path = drive_create();
92 global_qtest = qtest_startf("-machine virt "
93 "-drive if=none,id=drive0,file=%s,format=raw "
94 "-device virtio-blk-device,drive=drive0",
95 tmp_path);
96 unlink(tmp_path);
97 g_free(tmp_path);
100 static void test_end(void)
102 qtest_end();
105 static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
107 QVirtioPCIDevice *dev;
109 dev = qvirtio_pci_device_find_slot(bus, VIRTIO_ID_BLOCK, slot);
110 g_assert(dev != NULL);
111 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
112 g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN));
114 qvirtio_pci_device_enable(dev);
115 qvirtio_reset(&dev->vdev);
116 qvirtio_set_acknowledge(&dev->vdev);
117 qvirtio_set_driver(&dev->vdev);
119 return dev;
122 static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
124 #ifdef HOST_WORDS_BIGENDIAN
125 const bool host_is_big_endian = true;
126 #else
127 const bool host_is_big_endian = false;
128 #endif
130 if (qvirtio_is_big_endian(d) != host_is_big_endian) {
131 req->type = bswap32(req->type);
132 req->ioprio = bswap32(req->ioprio);
133 req->sector = bswap64(req->sector);
137 static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
138 QVirtioBlkReq *req, uint64_t data_size)
140 uint64_t addr;
141 uint8_t status = 0xFF;
143 g_assert_cmpuint(data_size % 512, ==, 0);
144 addr = guest_alloc(alloc, sizeof(*req) + data_size);
146 virtio_blk_fix_request(d, req);
148 memwrite(addr, req, 16);
149 memwrite(addr + 16, req->data, data_size);
150 memwrite(addr + 16 + data_size, &status, sizeof(status));
152 return addr;
155 static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
156 QVirtQueue *vq)
158 QVirtioBlkReq req;
159 uint64_t req_addr;
160 uint64_t capacity;
161 uint32_t features;
162 uint32_t free_head;
163 uint8_t status;
164 char *data;
166 capacity = qvirtio_config_readq(dev, 0);
168 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
170 features = qvirtio_get_features(dev);
171 features = features & ~(QVIRTIO_F_BAD_FEATURE |
172 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
173 (1u << VIRTIO_RING_F_EVENT_IDX) |
174 (1u << VIRTIO_BLK_F_SCSI));
175 qvirtio_set_features(dev, features);
177 qvirtio_set_driver_ok(dev);
179 /* Write and read with 3 descriptor layout */
180 /* Write request */
181 req.type = VIRTIO_BLK_T_OUT;
182 req.ioprio = 1;
183 req.sector = 0;
184 req.data = g_malloc0(512);
185 strcpy(req.data, "TEST");
187 req_addr = virtio_blk_request(alloc, dev, &req, 512);
189 g_free(req.data);
191 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
192 qvirtqueue_add(vq, req_addr + 16, 512, false, true);
193 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
195 qvirtqueue_kick(dev, vq, free_head);
197 qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
198 status = readb(req_addr + 528);
199 g_assert_cmpint(status, ==, 0);
201 guest_free(alloc, req_addr);
203 /* Read request */
204 req.type = VIRTIO_BLK_T_IN;
205 req.ioprio = 1;
206 req.sector = 0;
207 req.data = g_malloc0(512);
209 req_addr = virtio_blk_request(alloc, dev, &req, 512);
211 g_free(req.data);
213 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
214 qvirtqueue_add(vq, req_addr + 16, 512, true, true);
215 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
217 qvirtqueue_kick(dev, vq, free_head);
219 qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
220 status = readb(req_addr + 528);
221 g_assert_cmpint(status, ==, 0);
223 data = g_malloc0(512);
224 memread(req_addr + 16, data, 512);
225 g_assert_cmpstr(data, ==, "TEST");
226 g_free(data);
228 guest_free(alloc, req_addr);
230 if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
231 /* Write and read with 2 descriptor layout */
232 /* Write request */
233 req.type = VIRTIO_BLK_T_OUT;
234 req.ioprio = 1;
235 req.sector = 1;
236 req.data = g_malloc0(512);
237 strcpy(req.data, "TEST");
239 req_addr = virtio_blk_request(alloc, dev, &req, 512);
241 g_free(req.data);
243 free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
244 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
245 qvirtqueue_kick(dev, vq, free_head);
247 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
248 QVIRTIO_BLK_TIMEOUT_US);
249 status = readb(req_addr + 528);
250 g_assert_cmpint(status, ==, 0);
252 guest_free(alloc, req_addr);
254 /* Read request */
255 req.type = VIRTIO_BLK_T_IN;
256 req.ioprio = 1;
257 req.sector = 1;
258 req.data = g_malloc0(512);
260 req_addr = virtio_blk_request(alloc, dev, &req, 512);
262 g_free(req.data);
264 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
265 qvirtqueue_add(vq, req_addr + 16, 513, true, false);
267 qvirtqueue_kick(dev, vq, free_head);
269 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
270 QVIRTIO_BLK_TIMEOUT_US);
271 status = readb(req_addr + 528);
272 g_assert_cmpint(status, ==, 0);
274 data = g_malloc0(512);
275 memread(req_addr + 16, data, 512);
276 g_assert_cmpstr(data, ==, "TEST");
277 g_free(data);
279 guest_free(alloc, req_addr);
283 static void pci_basic(void)
285 QVirtioPCIDevice *dev;
286 QOSState *qs;
287 QVirtQueuePCI *vqpci;
289 qs = pci_test_start();
290 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
292 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
294 test_basic(&dev->vdev, qs->alloc, &vqpci->vq);
296 /* End test */
297 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
298 qvirtio_pci_device_disable(dev);
299 qvirtio_pci_device_free(dev);
300 qtest_shutdown(qs);
303 static void pci_indirect(void)
305 QVirtioPCIDevice *dev;
306 QVirtQueuePCI *vqpci;
307 QOSState *qs;
308 QVirtioBlkReq req;
309 QVRingIndirectDesc *indirect;
310 uint64_t req_addr;
311 uint64_t capacity;
312 uint32_t features;
313 uint32_t free_head;
314 uint8_t status;
315 char *data;
317 qs = pci_test_start();
319 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
321 capacity = qvirtio_config_readq(&dev->vdev, 0);
322 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
324 features = qvirtio_get_features(&dev->vdev);
325 g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
326 features = features & ~(QVIRTIO_F_BAD_FEATURE |
327 (1u << VIRTIO_RING_F_EVENT_IDX) |
328 (1u << VIRTIO_BLK_F_SCSI));
329 qvirtio_set_features(&dev->vdev, features);
331 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
332 qvirtio_set_driver_ok(&dev->vdev);
334 /* Write request */
335 req.type = VIRTIO_BLK_T_OUT;
336 req.ioprio = 1;
337 req.sector = 0;
338 req.data = g_malloc0(512);
339 strcpy(req.data, "TEST");
341 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
343 g_free(req.data);
345 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
346 qvring_indirect_desc_add(indirect, req_addr, 528, false);
347 qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
348 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
349 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
351 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
352 QVIRTIO_BLK_TIMEOUT_US);
353 status = readb(req_addr + 528);
354 g_assert_cmpint(status, ==, 0);
356 g_free(indirect);
357 guest_free(qs->alloc, req_addr);
359 /* Read request */
360 req.type = VIRTIO_BLK_T_IN;
361 req.ioprio = 1;
362 req.sector = 0;
363 req.data = g_malloc0(512);
364 strcpy(req.data, "TEST");
366 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
368 g_free(req.data);
370 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
371 qvring_indirect_desc_add(indirect, req_addr, 16, false);
372 qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
373 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
374 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
376 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
377 QVIRTIO_BLK_TIMEOUT_US);
378 status = readb(req_addr + 528);
379 g_assert_cmpint(status, ==, 0);
381 data = g_malloc0(512);
382 memread(req_addr + 16, data, 512);
383 g_assert_cmpstr(data, ==, "TEST");
384 g_free(data);
386 g_free(indirect);
387 guest_free(qs->alloc, req_addr);
389 /* End test */
390 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
391 qvirtio_pci_device_disable(dev);
392 qvirtio_pci_device_free(dev);
393 qtest_shutdown(qs);
396 static void pci_config(void)
398 QVirtioPCIDevice *dev;
399 QOSState *qs;
400 int n_size = TEST_IMAGE_SIZE / 2;
401 uint64_t capacity;
403 qs = pci_test_start();
405 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
407 capacity = qvirtio_config_readq(&dev->vdev, 0);
408 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
410 qvirtio_set_driver_ok(&dev->vdev);
412 qmp_discard_response("{ 'execute': 'block_resize', "
413 " 'arguments': { 'device': 'drive0', "
414 " 'size': %d } }", n_size);
415 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
417 capacity = qvirtio_config_readq(&dev->vdev, 0);
418 g_assert_cmpint(capacity, ==, n_size / 512);
420 qvirtio_pci_device_disable(dev);
421 qvirtio_pci_device_free(dev);
423 qtest_shutdown(qs);
426 static void pci_msix(void)
428 QVirtioPCIDevice *dev;
429 QOSState *qs;
430 QVirtQueuePCI *vqpci;
431 QVirtioBlkReq req;
432 int n_size = TEST_IMAGE_SIZE / 2;
433 uint64_t req_addr;
434 uint64_t capacity;
435 uint32_t features;
436 uint32_t free_head;
437 uint8_t status;
438 char *data;
440 qs = pci_test_start();
442 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
443 qpci_msix_enable(dev->pdev);
445 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
447 capacity = qvirtio_config_readq(&dev->vdev, 0);
448 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
450 features = qvirtio_get_features(&dev->vdev);
451 features = features & ~(QVIRTIO_F_BAD_FEATURE |
452 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
453 (1u << VIRTIO_RING_F_EVENT_IDX) |
454 (1u << VIRTIO_BLK_F_SCSI));
455 qvirtio_set_features(&dev->vdev, features);
457 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
458 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
460 qvirtio_set_driver_ok(&dev->vdev);
462 qmp_discard_response("{ 'execute': 'block_resize', "
463 " 'arguments': { 'device': 'drive0', "
464 " 'size': %d } }", n_size);
466 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
468 capacity = qvirtio_config_readq(&dev->vdev, 0);
469 g_assert_cmpint(capacity, ==, n_size / 512);
471 /* Write request */
472 req.type = VIRTIO_BLK_T_OUT;
473 req.ioprio = 1;
474 req.sector = 0;
475 req.data = g_malloc0(512);
476 strcpy(req.data, "TEST");
478 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
480 g_free(req.data);
482 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
483 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
484 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
485 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
487 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
488 QVIRTIO_BLK_TIMEOUT_US);
490 status = readb(req_addr + 528);
491 g_assert_cmpint(status, ==, 0);
493 guest_free(qs->alloc, req_addr);
495 /* Read request */
496 req.type = VIRTIO_BLK_T_IN;
497 req.ioprio = 1;
498 req.sector = 0;
499 req.data = g_malloc0(512);
501 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
503 g_free(req.data);
505 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
506 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
507 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
509 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
512 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
513 QVIRTIO_BLK_TIMEOUT_US);
515 status = readb(req_addr + 528);
516 g_assert_cmpint(status, ==, 0);
518 data = g_malloc0(512);
519 memread(req_addr + 16, data, 512);
520 g_assert_cmpstr(data, ==, "TEST");
521 g_free(data);
523 guest_free(qs->alloc, req_addr);
525 /* End test */
526 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
527 qpci_msix_disable(dev->pdev);
528 qvirtio_pci_device_disable(dev);
529 qvirtio_pci_device_free(dev);
530 qtest_shutdown(qs);
533 static void pci_idx(void)
535 QVirtioPCIDevice *dev;
536 QOSState *qs;
537 QVirtQueuePCI *vqpci;
538 QVirtioBlkReq req;
539 uint64_t req_addr;
540 uint64_t capacity;
541 uint32_t features;
542 uint32_t free_head;
543 uint32_t write_head;
544 uint32_t desc_idx;
545 uint8_t status;
546 char *data;
548 qs = pci_test_start();
550 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
551 qpci_msix_enable(dev->pdev);
553 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
555 capacity = qvirtio_config_readq(&dev->vdev, 0);
556 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
558 features = qvirtio_get_features(&dev->vdev);
559 features = features & ~(QVIRTIO_F_BAD_FEATURE |
560 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
561 (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
562 (1u << VIRTIO_BLK_F_SCSI));
563 qvirtio_set_features(&dev->vdev, features);
565 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
566 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
568 qvirtio_set_driver_ok(&dev->vdev);
570 /* Write request */
571 req.type = VIRTIO_BLK_T_OUT;
572 req.ioprio = 1;
573 req.sector = 0;
574 req.data = g_malloc0(512);
575 strcpy(req.data, "TEST");
577 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
579 g_free(req.data);
581 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
582 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
583 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
584 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
586 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
587 QVIRTIO_BLK_TIMEOUT_US);
589 /* Write request */
590 req.type = VIRTIO_BLK_T_OUT;
591 req.ioprio = 1;
592 req.sector = 1;
593 req.data = g_malloc0(512);
594 strcpy(req.data, "TEST");
596 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
598 g_free(req.data);
600 /* Notify after processing the third request */
601 qvirtqueue_set_used_event(&vqpci->vq, 2);
602 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
603 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
604 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
605 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
606 write_head = free_head;
608 /* No notification expected */
609 status = qvirtio_wait_status_byte_no_isr(&dev->vdev,
610 &vqpci->vq, req_addr + 528,
611 QVIRTIO_BLK_TIMEOUT_US);
612 g_assert_cmpint(status, ==, 0);
614 guest_free(qs->alloc, req_addr);
616 /* Read request */
617 req.type = VIRTIO_BLK_T_IN;
618 req.ioprio = 1;
619 req.sector = 1;
620 req.data = g_malloc0(512);
622 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
624 g_free(req.data);
626 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
627 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
628 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
630 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
632 /* We get just one notification for both requests */
633 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head, NULL,
634 QVIRTIO_BLK_TIMEOUT_US);
635 g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx, NULL));
636 g_assert_cmpint(desc_idx, ==, free_head);
638 status = readb(req_addr + 528);
639 g_assert_cmpint(status, ==, 0);
641 data = g_malloc0(512);
642 memread(req_addr + 16, data, 512);
643 g_assert_cmpstr(data, ==, "TEST");
644 g_free(data);
646 guest_free(qs->alloc, req_addr);
648 /* End test */
649 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
650 qpci_msix_disable(dev->pdev);
651 qvirtio_pci_device_disable(dev);
652 qvirtio_pci_device_free(dev);
653 qtest_shutdown(qs);
656 static void pci_hotplug(void)
658 QVirtioPCIDevice *dev;
659 QOSState *qs;
660 const char *arch = qtest_get_arch();
662 qs = pci_test_start();
664 /* plug secondary disk */
665 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP,
666 "'drive': 'drive1'");
668 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT_HP);
669 g_assert(dev);
670 qvirtio_pci_device_disable(dev);
671 qvirtio_pci_device_free(dev);
673 /* unplug secondary disk */
674 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
675 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
677 qtest_shutdown(qs);
681 * Check that setting the vring addr on a non-existent virtqueue does
682 * not crash.
684 static void test_nonexistent_virtqueue(void)
686 QPCIBar bar0;
687 QOSState *qs;
688 QPCIDevice *dev;
690 qs = pci_test_start();
691 dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4, 0));
692 g_assert(dev != NULL);
694 qpci_device_enable(dev);
695 bar0 = qpci_iomap(dev, 0, NULL);
697 qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2);
698 qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1);
700 g_free(dev);
701 qtest_shutdown(qs);
704 static void mmio_basic(void)
706 QVirtioMMIODevice *dev;
707 QVirtQueue *vq;
708 QGuestAllocator *alloc;
709 int n_size = TEST_IMAGE_SIZE / 2;
710 uint64_t capacity;
712 arm_test_start();
714 dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
715 g_assert(dev != NULL);
716 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
718 qvirtio_reset(&dev->vdev);
719 qvirtio_set_acknowledge(&dev->vdev);
720 qvirtio_set_driver(&dev->vdev);
722 alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
723 vq = qvirtqueue_setup(&dev->vdev, alloc, 0);
725 test_basic(&dev->vdev, alloc, vq);
727 qmp_discard_response("{ 'execute': 'block_resize', "
728 " 'arguments': { 'device': 'drive0', "
729 " 'size': %d } }", n_size);
731 qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US);
733 capacity = qvirtio_config_readq(&dev->vdev, 0);
734 g_assert_cmpint(capacity, ==, n_size / 512);
736 /* End test */
737 qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
738 g_free(dev);
739 generic_alloc_uninit(alloc);
740 test_end();
743 int main(int argc, char **argv)
745 const char *arch = qtest_get_arch();
747 g_test_init(&argc, &argv, NULL);
749 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0 ||
750 strcmp(arch, "ppc64") == 0) {
751 qtest_add_func("/virtio/blk/pci/basic", pci_basic);
752 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
753 qtest_add_func("/virtio/blk/pci/config", pci_config);
754 qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue);
755 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
756 qtest_add_func("/virtio/blk/pci/msix", pci_msix);
757 qtest_add_func("/virtio/blk/pci/idx", pci_idx);
759 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
760 } else if (strcmp(arch, "arm") == 0) {
761 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
764 return g_test_run();