pc: Eliminate PcGuestInfo struct
[qemu/ar7.git] / tests / virtio-blk-test.c
blob4078321a20c47cb575b4d6db658d2362301e323a
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 <glib.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include "libqtest.h"
17 #include "libqos/virtio.h"
18 #include "libqos/virtio-pci.h"
19 #include "libqos/virtio-mmio.h"
20 #include "libqos/pci-pc.h"
21 #include "libqos/malloc.h"
22 #include "libqos/malloc-pc.h"
23 #include "libqos/malloc-generic.h"
24 #include "qemu/bswap.h"
26 #define QVIRTIO_BLK_F_BARRIER 0x00000001
27 #define QVIRTIO_BLK_F_SIZE_MAX 0x00000002
28 #define QVIRTIO_BLK_F_SEG_MAX 0x00000004
29 #define QVIRTIO_BLK_F_GEOMETRY 0x00000010
30 #define QVIRTIO_BLK_F_RO 0x00000020
31 #define QVIRTIO_BLK_F_BLK_SIZE 0x00000040
32 #define QVIRTIO_BLK_F_SCSI 0x00000080
33 #define QVIRTIO_BLK_F_WCE 0x00000200
34 #define QVIRTIO_BLK_F_TOPOLOGY 0x00000400
35 #define QVIRTIO_BLK_F_CONFIG_WCE 0x00000800
37 #define QVIRTIO_BLK_T_IN 0
38 #define QVIRTIO_BLK_T_OUT 1
39 #define QVIRTIO_BLK_T_SCSI_CMD 2
40 #define QVIRTIO_BLK_T_SCSI_CMD_OUT 3
41 #define QVIRTIO_BLK_T_FLUSH 4
42 #define QVIRTIO_BLK_T_FLUSH_OUT 5
43 #define QVIRTIO_BLK_T_GET_ID 8
45 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
46 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
47 #define PCI_SLOT_HP 0x06
48 #define PCI_SLOT 0x04
49 #define PCI_FN 0x00
51 #define MMIO_PAGE_SIZE 4096
52 #define MMIO_DEV_BASE_ADDR 0x0A003E00
53 #define MMIO_RAM_ADDR 0x40000000
54 #define MMIO_RAM_SIZE 0x20000000
56 typedef struct QVirtioBlkReq {
57 uint32_t type;
58 uint32_t ioprio;
59 uint64_t sector;
60 char *data;
61 uint8_t status;
62 } QVirtioBlkReq;
64 static char *drive_create(void)
66 int fd, ret;
67 char *tmp_path = g_strdup("/tmp/qtest.XXXXXX");
69 /* Create a temporary raw image */
70 fd = mkstemp(tmp_path);
71 g_assert_cmpint(fd, >=, 0);
72 ret = ftruncate(fd, TEST_IMAGE_SIZE);
73 g_assert_cmpint(ret, ==, 0);
74 close(fd);
76 return tmp_path;
79 static QPCIBus *pci_test_start(void)
81 char *cmdline;
82 char *tmp_path;
84 tmp_path = drive_create();
86 cmdline = g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw "
87 "-drive if=none,id=drive1,file=/dev/null,format=raw "
88 "-device virtio-blk-pci,id=drv0,drive=drive0,"
89 "addr=%x.%x",
90 tmp_path, PCI_SLOT, PCI_FN);
91 qtest_start(cmdline);
92 unlink(tmp_path);
93 g_free(tmp_path);
94 g_free(cmdline);
96 return qpci_init_pc();
99 static void arm_test_start(void)
101 char *cmdline;
102 char *tmp_path;
104 tmp_path = drive_create();
106 cmdline = g_strdup_printf("-machine virt "
107 "-drive if=none,id=drive0,file=%s,format=raw "
108 "-device virtio-blk-device,drive=drive0",
109 tmp_path);
110 qtest_start(cmdline);
111 unlink(tmp_path);
112 g_free(tmp_path);
113 g_free(cmdline);
116 static void test_end(void)
118 qtest_end();
121 static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
123 QVirtioPCIDevice *dev;
125 dev = qvirtio_pci_device_find(bus, QVIRTIO_BLK_DEVICE_ID);
126 g_assert(dev != NULL);
127 g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_BLK_DEVICE_ID);
128 g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN));
130 qvirtio_pci_device_enable(dev);
131 qvirtio_reset(&qvirtio_pci, &dev->vdev);
132 qvirtio_set_acknowledge(&qvirtio_pci, &dev->vdev);
133 qvirtio_set_driver(&qvirtio_pci, &dev->vdev);
135 return dev;
138 static inline void virtio_blk_fix_request(QVirtioBlkReq *req)
140 #ifdef HOST_WORDS_BIGENDIAN
141 bool host_endian = true;
142 #else
143 bool host_endian = false;
144 #endif
146 if (qtest_big_endian() != host_endian) {
147 req->type = bswap32(req->type);
148 req->ioprio = bswap32(req->ioprio);
149 req->sector = bswap64(req->sector);
153 static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioBlkReq *req,
154 uint64_t data_size)
156 uint64_t addr;
157 uint8_t status = 0xFF;
159 g_assert_cmpuint(data_size % 512, ==, 0);
160 addr = guest_alloc(alloc, sizeof(*req) + data_size);
162 virtio_blk_fix_request(req);
164 memwrite(addr, req, 16);
165 memwrite(addr + 16, req->data, data_size);
166 memwrite(addr + 16 + data_size, &status, sizeof(status));
168 return addr;
171 static void test_basic(const QVirtioBus *bus, QVirtioDevice *dev,
172 QGuestAllocator *alloc, QVirtQueue *vq, uint64_t device_specific)
174 QVirtioBlkReq req;
175 uint64_t req_addr;
176 uint64_t capacity;
177 uint32_t features;
178 uint32_t free_head;
179 uint8_t status;
180 char *data;
182 capacity = qvirtio_config_readq(bus, dev, device_specific);
184 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
186 features = qvirtio_get_features(bus, dev);
187 features = features & ~(QVIRTIO_F_BAD_FEATURE |
188 QVIRTIO_F_RING_INDIRECT_DESC | QVIRTIO_F_RING_EVENT_IDX |
189 QVIRTIO_BLK_F_SCSI);
190 qvirtio_set_features(bus, dev, features);
192 qvirtio_set_driver_ok(bus, dev);
194 /* Write and read with 3 descriptor layout */
195 /* Write request */
196 req.type = QVIRTIO_BLK_T_OUT;
197 req.ioprio = 1;
198 req.sector = 0;
199 req.data = g_malloc0(512);
200 strcpy(req.data, "TEST");
202 req_addr = virtio_blk_request(alloc, &req, 512);
204 g_free(req.data);
206 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
207 qvirtqueue_add(vq, req_addr + 16, 512, false, true);
208 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
210 qvirtqueue_kick(bus, dev, vq, free_head);
212 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
213 status = readb(req_addr + 528);
214 g_assert_cmpint(status, ==, 0);
216 guest_free(alloc, req_addr);
218 /* Read request */
219 req.type = QVIRTIO_BLK_T_IN;
220 req.ioprio = 1;
221 req.sector = 0;
222 req.data = g_malloc0(512);
224 req_addr = virtio_blk_request(alloc, &req, 512);
226 g_free(req.data);
228 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
229 qvirtqueue_add(vq, req_addr + 16, 512, true, true);
230 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
232 qvirtqueue_kick(bus, dev, vq, free_head);
234 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
235 status = readb(req_addr + 528);
236 g_assert_cmpint(status, ==, 0);
238 data = g_malloc0(512);
239 memread(req_addr + 16, data, 512);
240 g_assert_cmpstr(data, ==, "TEST");
241 g_free(data);
243 guest_free(alloc, req_addr);
245 if (features & QVIRTIO_F_ANY_LAYOUT) {
246 /* Write and read with 2 descriptor layout */
247 /* Write request */
248 req.type = QVIRTIO_BLK_T_OUT;
249 req.ioprio = 1;
250 req.sector = 1;
251 req.data = g_malloc0(512);
252 strcpy(req.data, "TEST");
254 req_addr = virtio_blk_request(alloc, &req, 512);
256 g_free(req.data);
258 free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
259 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
260 qvirtqueue_kick(bus, dev, vq, free_head);
262 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
263 status = readb(req_addr + 528);
264 g_assert_cmpint(status, ==, 0);
266 guest_free(alloc, req_addr);
268 /* Read request */
269 req.type = QVIRTIO_BLK_T_IN;
270 req.ioprio = 1;
271 req.sector = 1;
272 req.data = g_malloc0(512);
274 req_addr = virtio_blk_request(alloc, &req, 512);
276 g_free(req.data);
278 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
279 qvirtqueue_add(vq, req_addr + 16, 513, true, false);
281 qvirtqueue_kick(bus, dev, vq, free_head);
283 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
284 status = readb(req_addr + 528);
285 g_assert_cmpint(status, ==, 0);
287 data = g_malloc0(512);
288 memread(req_addr + 16, data, 512);
289 g_assert_cmpstr(data, ==, "TEST");
290 g_free(data);
292 guest_free(alloc, req_addr);
296 static void pci_basic(void)
298 QVirtioPCIDevice *dev;
299 QPCIBus *bus;
300 QVirtQueuePCI *vqpci;
301 QGuestAllocator *alloc;
302 void *addr;
304 bus = pci_test_start();
305 dev = virtio_blk_pci_init(bus, PCI_SLOT);
307 alloc = pc_alloc_init();
308 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
309 alloc, 0);
311 /* MSI-X is not enabled */
312 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
314 test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq,
315 (uint64_t)(uintptr_t)addr);
317 /* End test */
318 guest_free(alloc, vqpci->vq.desc);
319 pc_alloc_uninit(alloc);
320 qvirtio_pci_device_disable(dev);
321 g_free(dev);
322 qpci_free_pc(bus);
323 test_end();
326 static void pci_indirect(void)
328 QVirtioPCIDevice *dev;
329 QPCIBus *bus;
330 QVirtQueuePCI *vqpci;
331 QGuestAllocator *alloc;
332 QVirtioBlkReq req;
333 QVRingIndirectDesc *indirect;
334 void *addr;
335 uint64_t req_addr;
336 uint64_t capacity;
337 uint32_t features;
338 uint32_t free_head;
339 uint8_t status;
340 char *data;
342 bus = pci_test_start();
344 dev = virtio_blk_pci_init(bus, PCI_SLOT);
346 /* MSI-X is not enabled */
347 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
349 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
350 (uint64_t)(uintptr_t)addr);
351 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
353 features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
354 g_assert_cmphex(features & QVIRTIO_F_RING_INDIRECT_DESC, !=, 0);
355 features = features & ~(QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_EVENT_IDX |
356 QVIRTIO_BLK_F_SCSI);
357 qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
359 alloc = pc_alloc_init();
360 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
361 alloc, 0);
362 qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
364 /* Write request */
365 req.type = QVIRTIO_BLK_T_OUT;
366 req.ioprio = 1;
367 req.sector = 0;
368 req.data = g_malloc0(512);
369 strcpy(req.data, "TEST");
371 req_addr = virtio_blk_request(alloc, &req, 512);
373 g_free(req.data);
375 indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);
376 qvring_indirect_desc_add(indirect, req_addr, 528, false);
377 qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
378 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
379 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
381 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
382 QVIRTIO_BLK_TIMEOUT_US);
383 status = readb(req_addr + 528);
384 g_assert_cmpint(status, ==, 0);
386 g_free(indirect);
387 guest_free(alloc, req_addr);
389 /* Read request */
390 req.type = QVIRTIO_BLK_T_IN;
391 req.ioprio = 1;
392 req.sector = 0;
393 req.data = g_malloc0(512);
394 strcpy(req.data, "TEST");
396 req_addr = virtio_blk_request(alloc, &req, 512);
398 g_free(req.data);
400 indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);
401 qvring_indirect_desc_add(indirect, req_addr, 16, false);
402 qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
403 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
404 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
406 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
407 QVIRTIO_BLK_TIMEOUT_US);
408 status = readb(req_addr + 528);
409 g_assert_cmpint(status, ==, 0);
411 data = g_malloc0(512);
412 memread(req_addr + 16, data, 512);
413 g_assert_cmpstr(data, ==, "TEST");
414 g_free(data);
416 g_free(indirect);
417 guest_free(alloc, req_addr);
419 /* End test */
420 guest_free(alloc, vqpci->vq.desc);
421 pc_alloc_uninit(alloc);
422 qvirtio_pci_device_disable(dev);
423 g_free(dev);
424 qpci_free_pc(bus);
425 test_end();
428 static void pci_config(void)
430 QVirtioPCIDevice *dev;
431 QPCIBus *bus;
432 int n_size = TEST_IMAGE_SIZE / 2;
433 void *addr;
434 uint64_t capacity;
436 bus = pci_test_start();
438 dev = virtio_blk_pci_init(bus, PCI_SLOT);
440 /* MSI-X is not enabled */
441 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
443 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
444 (uint64_t)(uintptr_t)addr);
445 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
447 qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
449 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
450 " 'size': %d } }", n_size);
451 qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
453 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
454 (uint64_t)(uintptr_t)addr);
455 g_assert_cmpint(capacity, ==, n_size / 512);
457 qvirtio_pci_device_disable(dev);
458 g_free(dev);
459 qpci_free_pc(bus);
460 test_end();
463 static void pci_msix(void)
465 QVirtioPCIDevice *dev;
466 QPCIBus *bus;
467 QVirtQueuePCI *vqpci;
468 QGuestAllocator *alloc;
469 QVirtioBlkReq req;
470 int n_size = TEST_IMAGE_SIZE / 2;
471 void *addr;
472 uint64_t req_addr;
473 uint64_t capacity;
474 uint32_t features;
475 uint32_t free_head;
476 uint8_t status;
477 char *data;
479 bus = pci_test_start();
480 alloc = pc_alloc_init();
482 dev = virtio_blk_pci_init(bus, PCI_SLOT);
483 qpci_msix_enable(dev->pdev);
485 qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
487 /* MSI-X is enabled */
488 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX;
490 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
491 (uint64_t)(uintptr_t)addr);
492 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
494 features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
495 features = features & ~(QVIRTIO_F_BAD_FEATURE |
496 QVIRTIO_F_RING_INDIRECT_DESC |
497 QVIRTIO_F_RING_EVENT_IDX | QVIRTIO_BLK_F_SCSI);
498 qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
500 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
501 alloc, 0);
502 qvirtqueue_pci_msix_setup(dev, vqpci, alloc, 1);
504 qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
506 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
507 " 'size': %d } }", n_size);
509 qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
511 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
512 (uint64_t)(uintptr_t)addr);
513 g_assert_cmpint(capacity, ==, n_size / 512);
515 /* Write request */
516 req.type = QVIRTIO_BLK_T_OUT;
517 req.ioprio = 1;
518 req.sector = 0;
519 req.data = g_malloc0(512);
520 strcpy(req.data, "TEST");
522 req_addr = virtio_blk_request(alloc, &req, 512);
524 g_free(req.data);
526 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
527 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
528 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
529 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
531 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
532 QVIRTIO_BLK_TIMEOUT_US);
534 status = readb(req_addr + 528);
535 g_assert_cmpint(status, ==, 0);
537 guest_free(alloc, req_addr);
539 /* Read request */
540 req.type = QVIRTIO_BLK_T_IN;
541 req.ioprio = 1;
542 req.sector = 0;
543 req.data = g_malloc0(512);
545 req_addr = virtio_blk_request(alloc, &req, 512);
547 g_free(req.data);
549 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
550 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
551 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
553 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
556 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
557 QVIRTIO_BLK_TIMEOUT_US);
559 status = readb(req_addr + 528);
560 g_assert_cmpint(status, ==, 0);
562 data = g_malloc0(512);
563 memread(req_addr + 16, data, 512);
564 g_assert_cmpstr(data, ==, "TEST");
565 g_free(data);
567 guest_free(alloc, req_addr);
569 /* End test */
570 guest_free(alloc, vqpci->vq.desc);
571 pc_alloc_uninit(alloc);
572 qpci_msix_disable(dev->pdev);
573 qvirtio_pci_device_disable(dev);
574 g_free(dev);
575 qpci_free_pc(bus);
576 test_end();
579 static void pci_idx(void)
581 QVirtioPCIDevice *dev;
582 QPCIBus *bus;
583 QVirtQueuePCI *vqpci;
584 QGuestAllocator *alloc;
585 QVirtioBlkReq req;
586 void *addr;
587 uint64_t req_addr;
588 uint64_t capacity;
589 uint32_t features;
590 uint32_t free_head;
591 uint8_t status;
592 char *data;
594 bus = pci_test_start();
595 alloc = pc_alloc_init();
597 dev = virtio_blk_pci_init(bus, PCI_SLOT);
598 qpci_msix_enable(dev->pdev);
600 qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
602 /* MSI-X is enabled */
603 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX;
605 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
606 (uint64_t)(uintptr_t)addr);
607 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
609 features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
610 features = features & ~(QVIRTIO_F_BAD_FEATURE |
611 QVIRTIO_F_RING_INDIRECT_DESC |
612 QVIRTIO_F_NOTIFY_ON_EMPTY | QVIRTIO_BLK_F_SCSI);
613 qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
615 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
616 alloc, 0);
617 qvirtqueue_pci_msix_setup(dev, vqpci, alloc, 1);
619 qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
621 /* Write request */
622 req.type = QVIRTIO_BLK_T_OUT;
623 req.ioprio = 1;
624 req.sector = 0;
625 req.data = g_malloc0(512);
626 strcpy(req.data, "TEST");
628 req_addr = virtio_blk_request(alloc, &req, 512);
630 g_free(req.data);
632 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
633 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
634 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
635 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
637 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
638 QVIRTIO_BLK_TIMEOUT_US);
640 /* Write request */
641 req.type = QVIRTIO_BLK_T_OUT;
642 req.ioprio = 1;
643 req.sector = 1;
644 req.data = g_malloc0(512);
645 strcpy(req.data, "TEST");
647 req_addr = virtio_blk_request(alloc, &req, 512);
649 g_free(req.data);
651 /* Notify after processing the third request */
652 qvirtqueue_set_used_event(&vqpci->vq, 2);
653 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
654 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
655 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
656 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
658 /* No notification expected */
659 status = qvirtio_wait_status_byte_no_isr(&qvirtio_pci, &dev->vdev,
660 &vqpci->vq, req_addr + 528,
661 QVIRTIO_BLK_TIMEOUT_US);
662 g_assert_cmpint(status, ==, 0);
664 guest_free(alloc, req_addr);
666 /* Read request */
667 req.type = QVIRTIO_BLK_T_IN;
668 req.ioprio = 1;
669 req.sector = 1;
670 req.data = g_malloc0(512);
672 req_addr = virtio_blk_request(alloc, &req, 512);
674 g_free(req.data);
676 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
677 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
678 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
680 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
682 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
683 QVIRTIO_BLK_TIMEOUT_US);
685 status = readb(req_addr + 528);
686 g_assert_cmpint(status, ==, 0);
688 data = g_malloc0(512);
689 memread(req_addr + 16, data, 512);
690 g_assert_cmpstr(data, ==, "TEST");
691 g_free(data);
693 guest_free(alloc, req_addr);
695 /* End test */
696 guest_free(alloc, vqpci->vq.desc);
697 pc_alloc_uninit(alloc);
698 qpci_msix_disable(dev->pdev);
699 qvirtio_pci_device_disable(dev);
700 g_free(dev);
701 qpci_free_pc(bus);
702 test_end();
705 static void pci_hotplug(void)
707 QPCIBus *bus;
708 QVirtioPCIDevice *dev;
710 bus = pci_test_start();
712 /* plug secondary disk */
713 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP,
714 "'drive': 'drive1'");
716 dev = virtio_blk_pci_init(bus, PCI_SLOT_HP);
717 g_assert(dev);
718 qvirtio_pci_device_disable(dev);
719 g_free(dev);
721 /* unplug secondary disk */
722 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
723 qpci_free_pc(bus);
724 test_end();
727 static void mmio_basic(void)
729 QVirtioMMIODevice *dev;
730 QVirtQueue *vq;
731 QGuestAllocator *alloc;
732 int n_size = TEST_IMAGE_SIZE / 2;
733 uint64_t capacity;
735 arm_test_start();
737 dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
738 g_assert(dev != NULL);
739 g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_BLK_DEVICE_ID);
741 qvirtio_reset(&qvirtio_mmio, &dev->vdev);
742 qvirtio_set_acknowledge(&qvirtio_mmio, &dev->vdev);
743 qvirtio_set_driver(&qvirtio_mmio, &dev->vdev);
745 alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
746 vq = qvirtqueue_setup(&qvirtio_mmio, &dev->vdev, alloc, 0);
748 test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq,
749 QVIRTIO_MMIO_DEVICE_SPECIFIC);
751 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
752 " 'size': %d } }", n_size);
754 qvirtio_wait_queue_isr(&qvirtio_mmio, &dev->vdev, vq,
755 QVIRTIO_BLK_TIMEOUT_US);
757 capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev,
758 QVIRTIO_MMIO_DEVICE_SPECIFIC);
759 g_assert_cmpint(capacity, ==, n_size / 512);
761 /* End test */
762 guest_free(alloc, vq->desc);
763 generic_alloc_uninit(alloc);
764 g_free(dev);
765 test_end();
768 int main(int argc, char **argv)
770 int ret;
771 const char *arch = qtest_get_arch();
773 g_test_init(&argc, &argv, NULL);
775 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
776 qtest_add_func("/virtio/blk/pci/basic", pci_basic);
777 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
778 qtest_add_func("/virtio/blk/pci/config", pci_config);
779 qtest_add_func("/virtio/blk/pci/msix", pci_msix);
780 qtest_add_func("/virtio/blk/pci/idx", pci_idx);
781 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
782 } else if (strcmp(arch, "arm") == 0) {
783 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
786 ret = g_test_run();
788 return ret;