target/arm: Implement VFMAL and VFMSL for aarch32
[qemu/ar7.git] / tests / virtio-blk-test.c
blob8d2fc9c71031733b07d6261ae2f4f66e5199473e
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 "qapi/qmp/qdict.h"
20 #include "qemu/bswap.h"
21 #include "standard-headers/linux/virtio_ids.h"
22 #include "standard-headers/linux/virtio_config.h"
23 #include "standard-headers/linux/virtio_ring.h"
24 #include "standard-headers/linux/virtio_blk.h"
25 #include "standard-headers/linux/virtio_pci.h"
27 /* TODO actually test the results and get rid of this */
28 #define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__))
30 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
31 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
32 #define PCI_SLOT_HP 0x06
33 #define PCI_SLOT 0x04
34 #define PCI_FN 0x00
36 #define MMIO_PAGE_SIZE 4096
37 #define MMIO_DEV_BASE_ADDR 0x0A003E00
38 #define MMIO_RAM_ADDR 0x40000000
39 #define MMIO_RAM_SIZE 0x20000000
41 typedef struct QVirtioBlkReq {
42 uint32_t type;
43 uint32_t ioprio;
44 uint64_t sector;
45 char *data;
46 uint8_t status;
47 } QVirtioBlkReq;
49 #ifdef HOST_WORDS_BIGENDIAN
50 const bool host_is_big_endian = true;
51 #else
52 const bool host_is_big_endian; /* false */
53 #endif
55 static char *drive_create(void)
57 int fd, ret;
58 char *tmp_path = g_strdup("/tmp/qtest.XXXXXX");
60 /* Create a temporary raw image */
61 fd = mkstemp(tmp_path);
62 g_assert_cmpint(fd, >=, 0);
63 ret = ftruncate(fd, TEST_IMAGE_SIZE);
64 g_assert_cmpint(ret, ==, 0);
65 close(fd);
67 return tmp_path;
70 static QOSState *pci_test_start(void)
72 QOSState *qs;
73 const char *arch = qtest_get_arch();
74 char *tmp_path;
75 const char *cmd = "-drive if=none,id=drive0,file=%s,format=raw "
76 "-drive if=none,id=drive1,file=null-co://,format=raw "
77 "-device virtio-blk-pci,id=drv0,drive=drive0,"
78 "addr=%x.%x";
80 tmp_path = drive_create();
82 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
83 qs = qtest_pc_boot(cmd, tmp_path, PCI_SLOT, PCI_FN);
84 } else if (strcmp(arch, "ppc64") == 0) {
85 qs = qtest_spapr_boot(cmd, tmp_path, PCI_SLOT, PCI_FN);
86 } else {
87 g_printerr("virtio-blk tests are only available on x86 or ppc64\n");
88 exit(EXIT_FAILURE);
90 global_qtest = qs->qts;
91 unlink(tmp_path);
92 g_free(tmp_path);
93 return qs;
96 static void arm_test_start(void)
98 char *tmp_path;
100 tmp_path = drive_create();
102 global_qtest = qtest_initf("-machine virt "
103 "-drive if=none,id=drive0,file=%s,format=raw "
104 "-device virtio-blk-device,drive=drive0",
105 tmp_path);
106 unlink(tmp_path);
107 g_free(tmp_path);
110 static void test_end(void)
112 qtest_end();
115 static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
117 QVirtioPCIDevice *dev;
119 dev = qvirtio_pci_device_find_slot(bus, VIRTIO_ID_BLOCK, slot);
120 g_assert(dev != NULL);
121 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
122 g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN));
124 qvirtio_pci_device_enable(dev);
125 qvirtio_reset(&dev->vdev);
126 qvirtio_set_acknowledge(&dev->vdev);
127 qvirtio_set_driver(&dev->vdev);
129 return dev;
132 static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
134 if (qvirtio_is_big_endian(d) != host_is_big_endian) {
135 req->type = bswap32(req->type);
136 req->ioprio = bswap32(req->ioprio);
137 req->sector = bswap64(req->sector);
142 static inline void virtio_blk_fix_dwz_hdr(QVirtioDevice *d,
143 struct virtio_blk_discard_write_zeroes *dwz_hdr)
145 if (qvirtio_is_big_endian(d) != host_is_big_endian) {
146 dwz_hdr->sector = bswap64(dwz_hdr->sector);
147 dwz_hdr->num_sectors = bswap32(dwz_hdr->num_sectors);
148 dwz_hdr->flags = bswap32(dwz_hdr->flags);
152 static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
153 QVirtioBlkReq *req, uint64_t data_size)
155 uint64_t addr;
156 uint8_t status = 0xFF;
158 switch (req->type) {
159 case VIRTIO_BLK_T_IN:
160 case VIRTIO_BLK_T_OUT:
161 g_assert_cmpuint(data_size % 512, ==, 0);
162 break;
163 case VIRTIO_BLK_T_DISCARD:
164 case VIRTIO_BLK_T_WRITE_ZEROES:
165 g_assert_cmpuint(data_size %
166 sizeof(struct virtio_blk_discard_write_zeroes), ==, 0);
167 break;
168 default:
169 g_assert_cmpuint(data_size, ==, 0);
172 addr = guest_alloc(alloc, sizeof(*req) + data_size);
174 virtio_blk_fix_request(d, req);
176 memwrite(addr, req, 16);
177 memwrite(addr + 16, req->data, data_size);
178 memwrite(addr + 16 + data_size, &status, sizeof(status));
180 return addr;
183 static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
184 QVirtQueue *vq)
186 QVirtioBlkReq req;
187 uint64_t req_addr;
188 uint64_t capacity;
189 uint32_t features;
190 uint32_t free_head;
191 uint8_t status;
192 char *data;
194 capacity = qvirtio_config_readq(dev, 0);
196 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
198 features = qvirtio_get_features(dev);
199 features = features & ~(QVIRTIO_F_BAD_FEATURE |
200 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
201 (1u << VIRTIO_RING_F_EVENT_IDX) |
202 (1u << VIRTIO_BLK_F_SCSI));
203 qvirtio_set_features(dev, features);
205 qvirtio_set_driver_ok(dev);
207 /* Write and read with 3 descriptor layout */
208 /* Write request */
209 req.type = VIRTIO_BLK_T_OUT;
210 req.ioprio = 1;
211 req.sector = 0;
212 req.data = g_malloc0(512);
213 strcpy(req.data, "TEST");
215 req_addr = virtio_blk_request(alloc, dev, &req, 512);
217 g_free(req.data);
219 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
220 qvirtqueue_add(vq, req_addr + 16, 512, false, true);
221 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
223 qvirtqueue_kick(dev, vq, free_head);
225 qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
226 status = readb(req_addr + 528);
227 g_assert_cmpint(status, ==, 0);
229 guest_free(alloc, req_addr);
231 /* Read request */
232 req.type = VIRTIO_BLK_T_IN;
233 req.ioprio = 1;
234 req.sector = 0;
235 req.data = g_malloc0(512);
237 req_addr = virtio_blk_request(alloc, dev, &req, 512);
239 g_free(req.data);
241 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
242 qvirtqueue_add(vq, req_addr + 16, 512, true, true);
243 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, QVIRTIO_BLK_TIMEOUT_US);
248 status = readb(req_addr + 528);
249 g_assert_cmpint(status, ==, 0);
251 data = g_malloc0(512);
252 memread(req_addr + 16, data, 512);
253 g_assert_cmpstr(data, ==, "TEST");
254 g_free(data);
256 guest_free(alloc, req_addr);
258 if (features & (1u << VIRTIO_BLK_F_WRITE_ZEROES)) {
259 struct virtio_blk_discard_write_zeroes dwz_hdr;
260 void *expected;
263 * WRITE_ZEROES request on the same sector of previous test where
264 * we wrote "TEST".
266 req.type = VIRTIO_BLK_T_WRITE_ZEROES;
267 req.data = (char *) &dwz_hdr;
268 dwz_hdr.sector = 0;
269 dwz_hdr.num_sectors = 1;
270 dwz_hdr.flags = 0;
272 virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
274 req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
276 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
277 qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
278 qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);
280 qvirtqueue_kick(dev, vq, free_head);
282 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
283 QVIRTIO_BLK_TIMEOUT_US);
284 status = readb(req_addr + 16 + sizeof(dwz_hdr));
285 g_assert_cmpint(status, ==, 0);
287 guest_free(alloc, req_addr);
289 /* Read request to check if the sector contains all zeroes */
290 req.type = VIRTIO_BLK_T_IN;
291 req.ioprio = 1;
292 req.sector = 0;
293 req.data = g_malloc0(512);
295 req_addr = virtio_blk_request(alloc, dev, &req, 512);
297 g_free(req.data);
299 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
300 qvirtqueue_add(vq, req_addr + 16, 512, true, true);
301 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
303 qvirtqueue_kick(dev, vq, free_head);
305 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
306 QVIRTIO_BLK_TIMEOUT_US);
307 status = readb(req_addr + 528);
308 g_assert_cmpint(status, ==, 0);
310 data = g_malloc(512);
311 expected = g_malloc0(512);
312 memread(req_addr + 16, data, 512);
313 g_assert_cmpmem(data, 512, expected, 512);
314 g_free(expected);
315 g_free(data);
317 guest_free(alloc, req_addr);
320 if (features & (1u << VIRTIO_BLK_F_DISCARD)) {
321 struct virtio_blk_discard_write_zeroes dwz_hdr;
323 req.type = VIRTIO_BLK_T_DISCARD;
324 req.data = (char *) &dwz_hdr;
325 dwz_hdr.sector = 0;
326 dwz_hdr.num_sectors = 1;
327 dwz_hdr.flags = 0;
329 virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);
331 req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));
333 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
334 qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
335 qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);
337 qvirtqueue_kick(dev, vq, free_head);
339 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
340 QVIRTIO_BLK_TIMEOUT_US);
341 status = readb(req_addr + 16 + sizeof(dwz_hdr));
342 g_assert_cmpint(status, ==, 0);
344 guest_free(alloc, req_addr);
347 if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
348 /* Write and read with 2 descriptor layout */
349 /* Write request */
350 req.type = VIRTIO_BLK_T_OUT;
351 req.ioprio = 1;
352 req.sector = 1;
353 req.data = g_malloc0(512);
354 strcpy(req.data, "TEST");
356 req_addr = virtio_blk_request(alloc, dev, &req, 512);
358 g_free(req.data);
360 free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
361 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
362 qvirtqueue_kick(dev, vq, free_head);
364 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
365 QVIRTIO_BLK_TIMEOUT_US);
366 status = readb(req_addr + 528);
367 g_assert_cmpint(status, ==, 0);
369 guest_free(alloc, req_addr);
371 /* Read request */
372 req.type = VIRTIO_BLK_T_IN;
373 req.ioprio = 1;
374 req.sector = 1;
375 req.data = g_malloc0(512);
377 req_addr = virtio_blk_request(alloc, dev, &req, 512);
379 g_free(req.data);
381 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
382 qvirtqueue_add(vq, req_addr + 16, 513, true, false);
384 qvirtqueue_kick(dev, vq, free_head);
386 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
387 QVIRTIO_BLK_TIMEOUT_US);
388 status = readb(req_addr + 528);
389 g_assert_cmpint(status, ==, 0);
391 data = g_malloc0(512);
392 memread(req_addr + 16, data, 512);
393 g_assert_cmpstr(data, ==, "TEST");
394 g_free(data);
396 guest_free(alloc, req_addr);
400 static void pci_basic(void)
402 QVirtioPCIDevice *dev;
403 QOSState *qs;
404 QVirtQueuePCI *vqpci;
406 qs = pci_test_start();
407 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
409 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
411 test_basic(&dev->vdev, qs->alloc, &vqpci->vq);
413 /* End test */
414 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
415 qvirtio_pci_device_disable(dev);
416 qvirtio_pci_device_free(dev);
417 qtest_shutdown(qs);
420 static void pci_indirect(void)
422 QVirtioPCIDevice *dev;
423 QVirtQueuePCI *vqpci;
424 QOSState *qs;
425 QVirtioBlkReq req;
426 QVRingIndirectDesc *indirect;
427 uint64_t req_addr;
428 uint64_t capacity;
429 uint32_t features;
430 uint32_t free_head;
431 uint8_t status;
432 char *data;
434 qs = pci_test_start();
436 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
438 capacity = qvirtio_config_readq(&dev->vdev, 0);
439 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
441 features = qvirtio_get_features(&dev->vdev);
442 g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
443 features = features & ~(QVIRTIO_F_BAD_FEATURE |
444 (1u << VIRTIO_RING_F_EVENT_IDX) |
445 (1u << VIRTIO_BLK_F_SCSI));
446 qvirtio_set_features(&dev->vdev, features);
448 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
449 qvirtio_set_driver_ok(&dev->vdev);
451 /* Write request */
452 req.type = VIRTIO_BLK_T_OUT;
453 req.ioprio = 1;
454 req.sector = 0;
455 req.data = g_malloc0(512);
456 strcpy(req.data, "TEST");
458 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
460 g_free(req.data);
462 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
463 qvring_indirect_desc_add(indirect, req_addr, 528, false);
464 qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
465 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
466 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
468 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
469 QVIRTIO_BLK_TIMEOUT_US);
470 status = readb(req_addr + 528);
471 g_assert_cmpint(status, ==, 0);
473 g_free(indirect);
474 guest_free(qs->alloc, req_addr);
476 /* Read request */
477 req.type = VIRTIO_BLK_T_IN;
478 req.ioprio = 1;
479 req.sector = 0;
480 req.data = g_malloc0(512);
481 strcpy(req.data, "TEST");
483 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
485 g_free(req.data);
487 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
488 qvring_indirect_desc_add(indirect, req_addr, 16, false);
489 qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
490 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
491 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
493 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
494 QVIRTIO_BLK_TIMEOUT_US);
495 status = readb(req_addr + 528);
496 g_assert_cmpint(status, ==, 0);
498 data = g_malloc0(512);
499 memread(req_addr + 16, data, 512);
500 g_assert_cmpstr(data, ==, "TEST");
501 g_free(data);
503 g_free(indirect);
504 guest_free(qs->alloc, req_addr);
506 /* End test */
507 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
508 qvirtio_pci_device_disable(dev);
509 qvirtio_pci_device_free(dev);
510 qtest_shutdown(qs);
513 static void pci_config(void)
515 QVirtioPCIDevice *dev;
516 QOSState *qs;
517 int n_size = TEST_IMAGE_SIZE / 2;
518 uint64_t capacity;
520 qs = pci_test_start();
522 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
524 capacity = qvirtio_config_readq(&dev->vdev, 0);
525 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
527 qvirtio_set_driver_ok(&dev->vdev);
529 qmp_discard_response("{ 'execute': 'block_resize', "
530 " 'arguments': { 'device': 'drive0', "
531 " 'size': %d } }", n_size);
532 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
534 capacity = qvirtio_config_readq(&dev->vdev, 0);
535 g_assert_cmpint(capacity, ==, n_size / 512);
537 qvirtio_pci_device_disable(dev);
538 qvirtio_pci_device_free(dev);
540 qtest_shutdown(qs);
543 static void pci_msix(void)
545 QVirtioPCIDevice *dev;
546 QOSState *qs;
547 QVirtQueuePCI *vqpci;
548 QVirtioBlkReq req;
549 int n_size = TEST_IMAGE_SIZE / 2;
550 uint64_t req_addr;
551 uint64_t capacity;
552 uint32_t features;
553 uint32_t free_head;
554 uint8_t status;
555 char *data;
557 qs = pci_test_start();
559 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
560 qpci_msix_enable(dev->pdev);
562 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
564 capacity = qvirtio_config_readq(&dev->vdev, 0);
565 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
567 features = qvirtio_get_features(&dev->vdev);
568 features = features & ~(QVIRTIO_F_BAD_FEATURE |
569 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
570 (1u << VIRTIO_RING_F_EVENT_IDX) |
571 (1u << VIRTIO_BLK_F_SCSI));
572 qvirtio_set_features(&dev->vdev, features);
574 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
575 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
577 qvirtio_set_driver_ok(&dev->vdev);
579 qmp_discard_response("{ 'execute': 'block_resize', "
580 " 'arguments': { 'device': 'drive0', "
581 " 'size': %d } }", n_size);
583 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
585 capacity = qvirtio_config_readq(&dev->vdev, 0);
586 g_assert_cmpint(capacity, ==, n_size / 512);
588 /* Write request */
589 req.type = VIRTIO_BLK_T_OUT;
590 req.ioprio = 1;
591 req.sector = 0;
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 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
600 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
601 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
602 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
604 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
605 QVIRTIO_BLK_TIMEOUT_US);
607 status = readb(req_addr + 528);
608 g_assert_cmpint(status, ==, 0);
610 guest_free(qs->alloc, req_addr);
612 /* Read request */
613 req.type = VIRTIO_BLK_T_IN;
614 req.ioprio = 1;
615 req.sector = 0;
616 req.data = g_malloc0(512);
618 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
620 g_free(req.data);
622 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
623 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
624 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
626 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
629 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
630 QVIRTIO_BLK_TIMEOUT_US);
632 status = readb(req_addr + 528);
633 g_assert_cmpint(status, ==, 0);
635 data = g_malloc0(512);
636 memread(req_addr + 16, data, 512);
637 g_assert_cmpstr(data, ==, "TEST");
638 g_free(data);
640 guest_free(qs->alloc, req_addr);
642 /* End test */
643 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
644 qpci_msix_disable(dev->pdev);
645 qvirtio_pci_device_disable(dev);
646 qvirtio_pci_device_free(dev);
647 qtest_shutdown(qs);
650 static void pci_idx(void)
652 QVirtioPCIDevice *dev;
653 QOSState *qs;
654 QVirtQueuePCI *vqpci;
655 QVirtioBlkReq req;
656 uint64_t req_addr;
657 uint64_t capacity;
658 uint32_t features;
659 uint32_t free_head;
660 uint32_t write_head;
661 uint32_t desc_idx;
662 uint8_t status;
663 char *data;
665 qs = pci_test_start();
667 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
668 qpci_msix_enable(dev->pdev);
670 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
672 capacity = qvirtio_config_readq(&dev->vdev, 0);
673 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
675 features = qvirtio_get_features(&dev->vdev);
676 features = features & ~(QVIRTIO_F_BAD_FEATURE |
677 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
678 (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
679 (1u << VIRTIO_BLK_F_SCSI));
680 qvirtio_set_features(&dev->vdev, features);
682 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
683 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
685 qvirtio_set_driver_ok(&dev->vdev);
687 /* Write request */
688 req.type = VIRTIO_BLK_T_OUT;
689 req.ioprio = 1;
690 req.sector = 0;
691 req.data = g_malloc0(512);
692 strcpy(req.data, "TEST");
694 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
696 g_free(req.data);
698 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
699 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
700 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
701 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
703 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
704 QVIRTIO_BLK_TIMEOUT_US);
706 /* Write request */
707 req.type = VIRTIO_BLK_T_OUT;
708 req.ioprio = 1;
709 req.sector = 1;
710 req.data = g_malloc0(512);
711 strcpy(req.data, "TEST");
713 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
715 g_free(req.data);
717 /* Notify after processing the third request */
718 qvirtqueue_set_used_event(&vqpci->vq, 2);
719 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
720 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
721 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
722 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
723 write_head = free_head;
725 /* No notification expected */
726 status = qvirtio_wait_status_byte_no_isr(&dev->vdev,
727 &vqpci->vq, req_addr + 528,
728 QVIRTIO_BLK_TIMEOUT_US);
729 g_assert_cmpint(status, ==, 0);
731 guest_free(qs->alloc, req_addr);
733 /* Read request */
734 req.type = VIRTIO_BLK_T_IN;
735 req.ioprio = 1;
736 req.sector = 1;
737 req.data = g_malloc0(512);
739 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
741 g_free(req.data);
743 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
744 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
745 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
747 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
749 /* We get just one notification for both requests */
750 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head, NULL,
751 QVIRTIO_BLK_TIMEOUT_US);
752 g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx, NULL));
753 g_assert_cmpint(desc_idx, ==, free_head);
755 status = readb(req_addr + 528);
756 g_assert_cmpint(status, ==, 0);
758 data = g_malloc0(512);
759 memread(req_addr + 16, data, 512);
760 g_assert_cmpstr(data, ==, "TEST");
761 g_free(data);
763 guest_free(qs->alloc, req_addr);
765 /* End test */
766 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
767 qpci_msix_disable(dev->pdev);
768 qvirtio_pci_device_disable(dev);
769 qvirtio_pci_device_free(dev);
770 qtest_shutdown(qs);
773 static void pci_hotplug(void)
775 QVirtioPCIDevice *dev;
776 QOSState *qs;
777 const char *arch = qtest_get_arch();
779 qs = pci_test_start();
781 /* plug secondary disk */
782 qtest_qmp_device_add("virtio-blk-pci", "drv1",
783 "{'addr': %s, 'drive': 'drive1'}",
784 stringify(PCI_SLOT_HP));
786 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT_HP);
787 g_assert(dev);
788 qvirtio_pci_device_disable(dev);
789 qvirtio_pci_device_free(dev);
791 /* unplug secondary disk */
792 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
793 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
795 qtest_shutdown(qs);
799 * Check that setting the vring addr on a non-existent virtqueue does
800 * not crash.
802 static void test_nonexistent_virtqueue(void)
804 QPCIBar bar0;
805 QOSState *qs;
806 QPCIDevice *dev;
808 qs = pci_test_start();
809 dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4, 0));
810 g_assert(dev != NULL);
812 qpci_device_enable(dev);
813 bar0 = qpci_iomap(dev, 0, NULL);
815 qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2);
816 qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1);
818 g_free(dev);
819 qtest_shutdown(qs);
822 static void mmio_basic(void)
824 QVirtioMMIODevice *dev;
825 QVirtQueue *vq;
826 QGuestAllocator *alloc;
827 int n_size = TEST_IMAGE_SIZE / 2;
828 uint64_t capacity;
830 arm_test_start();
832 dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
833 g_assert(dev != NULL);
834 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
836 qvirtio_reset(&dev->vdev);
837 qvirtio_set_acknowledge(&dev->vdev);
838 qvirtio_set_driver(&dev->vdev);
840 alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
841 vq = qvirtqueue_setup(&dev->vdev, alloc, 0);
843 test_basic(&dev->vdev, alloc, vq);
845 qmp_discard_response("{ 'execute': 'block_resize', "
846 " 'arguments': { 'device': 'drive0', "
847 " 'size': %d } }", n_size);
849 qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US);
851 capacity = qvirtio_config_readq(&dev->vdev, 0);
852 g_assert_cmpint(capacity, ==, n_size / 512);
854 /* End test */
855 qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
856 g_free(dev);
857 generic_alloc_uninit(alloc);
858 test_end();
861 int main(int argc, char **argv)
863 const char *arch = qtest_get_arch();
865 g_test_init(&argc, &argv, NULL);
867 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0 ||
868 strcmp(arch, "ppc64") == 0) {
869 qtest_add_func("/virtio/blk/pci/basic", pci_basic);
870 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
871 qtest_add_func("/virtio/blk/pci/config", pci_config);
872 qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue);
873 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
874 qtest_add_func("/virtio/blk/pci/msix", pci_msix);
875 qtest_add_func("/virtio/blk/pci/idx", pci_idx);
877 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
878 } else if (strcmp(arch, "arm") == 0) {
879 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
882 return g_test_run();