memory: unify loops to sync dirty log bitmap
[qemu/ar7.git] / tests / virtio-blk-test.c
blob2ac64e5e2559d53f59c8cea66901f472b0786381
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 unlink(tmp_path);
81 g_free(tmp_path);
82 return qs;
85 static void arm_test_start(void)
87 char *tmp_path;
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",
94 tmp_path);
95 unlink(tmp_path);
96 g_free(tmp_path);
99 static void test_end(void)
101 qtest_end();
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);
118 return dev;
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;
125 #else
126 const bool host_is_big_endian = false;
127 #endif
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)
139 uint64_t addr;
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));
151 return addr;
154 static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
155 QVirtQueue *vq)
157 QVirtioBlkReq req;
158 uint64_t req_addr;
159 uint64_t capacity;
160 uint32_t features;
161 uint32_t free_head;
162 uint8_t status;
163 char *data;
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 */
179 /* Write request */
180 req.type = VIRTIO_BLK_T_OUT;
181 req.ioprio = 1;
182 req.sector = 0;
183 req.data = g_malloc0(512);
184 strcpy(req.data, "TEST");
186 req_addr = virtio_blk_request(alloc, dev, &req, 512);
188 g_free(req.data);
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);
202 /* Read request */
203 req.type = VIRTIO_BLK_T_IN;
204 req.ioprio = 1;
205 req.sector = 0;
206 req.data = g_malloc0(512);
208 req_addr = virtio_blk_request(alloc, dev, &req, 512);
210 g_free(req.data);
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");
225 g_free(data);
227 guest_free(alloc, req_addr);
229 if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
230 /* Write and read with 2 descriptor layout */
231 /* Write request */
232 req.type = VIRTIO_BLK_T_OUT;
233 req.ioprio = 1;
234 req.sector = 1;
235 req.data = g_malloc0(512);
236 strcpy(req.data, "TEST");
238 req_addr = virtio_blk_request(alloc, dev, &req, 512);
240 g_free(req.data);
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);
253 /* Read request */
254 req.type = VIRTIO_BLK_T_IN;
255 req.ioprio = 1;
256 req.sector = 1;
257 req.data = g_malloc0(512);
259 req_addr = virtio_blk_request(alloc, dev, &req, 512);
261 g_free(req.data);
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");
276 g_free(data);
278 guest_free(alloc, req_addr);
282 static void pci_basic(void)
284 QVirtioPCIDevice *dev;
285 QOSState *qs;
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);
295 /* End test */
296 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
297 qvirtio_pci_device_disable(dev);
298 qvirtio_pci_device_free(dev);
299 qtest_shutdown(qs);
302 static void pci_indirect(void)
304 QVirtioPCIDevice *dev;
305 QVirtQueuePCI *vqpci;
306 QOSState *qs;
307 QVirtioBlkReq req;
308 QVRingIndirectDesc *indirect;
309 uint64_t req_addr;
310 uint64_t capacity;
311 uint32_t features;
312 uint32_t free_head;
313 uint8_t status;
314 char *data;
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);
333 /* Write request */
334 req.type = VIRTIO_BLK_T_OUT;
335 req.ioprio = 1;
336 req.sector = 0;
337 req.data = g_malloc0(512);
338 strcpy(req.data, "TEST");
340 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
342 g_free(req.data);
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);
355 g_free(indirect);
356 guest_free(qs->alloc, req_addr);
358 /* Read request */
359 req.type = VIRTIO_BLK_T_IN;
360 req.ioprio = 1;
361 req.sector = 0;
362 req.data = g_malloc0(512);
363 strcpy(req.data, "TEST");
365 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
367 g_free(req.data);
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");
383 g_free(data);
385 g_free(indirect);
386 guest_free(qs->alloc, req_addr);
388 /* End test */
389 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
390 qvirtio_pci_device_disable(dev);
391 qvirtio_pci_device_free(dev);
392 qtest_shutdown(qs);
395 static void pci_config(void)
397 QVirtioPCIDevice *dev;
398 QOSState *qs;
399 int n_size = TEST_IMAGE_SIZE / 2;
400 uint64_t capacity;
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);
422 qtest_shutdown(qs);
425 static void pci_msix(void)
427 QVirtioPCIDevice *dev;
428 QOSState *qs;
429 QVirtQueuePCI *vqpci;
430 QVirtioBlkReq req;
431 int n_size = TEST_IMAGE_SIZE / 2;
432 uint64_t req_addr;
433 uint64_t capacity;
434 uint32_t features;
435 uint32_t free_head;
436 uint8_t status;
437 char *data;
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);
470 /* Write request */
471 req.type = VIRTIO_BLK_T_OUT;
472 req.ioprio = 1;
473 req.sector = 0;
474 req.data = g_malloc0(512);
475 strcpy(req.data, "TEST");
477 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
479 g_free(req.data);
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);
494 /* Read request */
495 req.type = VIRTIO_BLK_T_IN;
496 req.ioprio = 1;
497 req.sector = 0;
498 req.data = g_malloc0(512);
500 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
502 g_free(req.data);
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");
520 g_free(data);
522 guest_free(qs->alloc, req_addr);
524 /* End test */
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);
529 qtest_shutdown(qs);
532 static void pci_idx(void)
534 QVirtioPCIDevice *dev;
535 QOSState *qs;
536 QVirtQueuePCI *vqpci;
537 QVirtioBlkReq req;
538 uint64_t req_addr;
539 uint64_t capacity;
540 uint32_t features;
541 uint32_t free_head;
542 uint32_t write_head;
543 uint32_t desc_idx;
544 uint8_t status;
545 char *data;
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);
569 /* Write request */
570 req.type = VIRTIO_BLK_T_OUT;
571 req.ioprio = 1;
572 req.sector = 0;
573 req.data = g_malloc0(512);
574 strcpy(req.data, "TEST");
576 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
578 g_free(req.data);
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);
588 /* Write request */
589 req.type = VIRTIO_BLK_T_OUT;
590 req.ioprio = 1;
591 req.sector = 1;
592 req.data = g_malloc0(512);
593 strcpy(req.data, "TEST");
595 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
597 g_free(req.data);
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);
615 /* Read request */
616 req.type = VIRTIO_BLK_T_IN;
617 req.ioprio = 1;
618 req.sector = 1;
619 req.data = g_malloc0(512);
621 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
623 g_free(req.data);
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");
643 g_free(data);
645 guest_free(qs->alloc, req_addr);
647 /* End test */
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);
652 qtest_shutdown(qs);
655 static void pci_hotplug(void)
657 QVirtioPCIDevice *dev;
658 QOSState *qs;
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);
668 g_assert(dev);
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);
676 qtest_shutdown(qs);
680 * Check that setting the vring addr on a non-existent virtqueue does
681 * not crash.
683 static void test_nonexistent_virtqueue(void)
685 QPCIBar bar0;
686 QOSState *qs;
687 QPCIDevice *dev;
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);
699 g_free(dev);
700 qtest_shutdown(qs);
703 static void mmio_basic(void)
705 QVirtioMMIODevice *dev;
706 QVirtQueue *vq;
707 QGuestAllocator *alloc;
708 int n_size = TEST_IMAGE_SIZE / 2;
709 uint64_t capacity;
711 arm_test_start();
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);
735 /* End test */
736 qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
737 g_free(dev);
738 generic_alloc_uninit(alloc);
739 test_end();
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);
763 return g_test_run();