]> git.proxmox.com Git - mirror_qemu.git/blob - tests/virtio-blk-test.c
tests: move QVirtioBus pointer into QVirtioDevice
[mirror_qemu.git] / tests / virtio-blk-test.c
1 /*
2 * QTest testcase for VirtIO Block Device
3 *
4 * Copyright (c) 2014 SUSE LINUX Products GmbH
5 * Copyright (c) 2014 Marc MarĂ­
6 *
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 */
10
11 #include "qemu/osdep.h"
12 #include "libqtest.h"
13 #include "libqos/virtio.h"
14 #include "libqos/virtio-pci.h"
15 #include "libqos/virtio-mmio.h"
16 #include "libqos/pci-pc.h"
17 #include "libqos/malloc.h"
18 #include "libqos/malloc-pc.h"
19 #include "libqos/malloc-generic.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"
26
27 #define TEST_IMAGE_SIZE (64 * 1024 * 1024)
28 #define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
29 #define PCI_SLOT_HP 0x06
30 #define PCI_SLOT 0x04
31 #define PCI_FN 0x00
32
33 #define MMIO_PAGE_SIZE 4096
34 #define MMIO_DEV_BASE_ADDR 0x0A003E00
35 #define MMIO_RAM_ADDR 0x40000000
36 #define MMIO_RAM_SIZE 0x20000000
37
38 typedef struct QVirtioBlkReq {
39 uint32_t type;
40 uint32_t ioprio;
41 uint64_t sector;
42 char *data;
43 uint8_t status;
44 } QVirtioBlkReq;
45
46 static char *drive_create(void)
47 {
48 int fd, ret;
49 char *tmp_path = g_strdup("/tmp/qtest.XXXXXX");
50
51 /* Create a temporary raw image */
52 fd = mkstemp(tmp_path);
53 g_assert_cmpint(fd, >=, 0);
54 ret = ftruncate(fd, TEST_IMAGE_SIZE);
55 g_assert_cmpint(ret, ==, 0);
56 close(fd);
57
58 return tmp_path;
59 }
60
61 static QPCIBus *pci_test_start(void)
62 {
63 char *cmdline;
64 char *tmp_path;
65
66 tmp_path = drive_create();
67
68 cmdline = g_strdup_printf("-drive if=none,id=drive0,file=%s,format=raw "
69 "-drive if=none,id=drive1,file=/dev/null,format=raw "
70 "-device virtio-blk-pci,id=drv0,drive=drive0,"
71 "addr=%x.%x",
72 tmp_path, PCI_SLOT, PCI_FN);
73 qtest_start(cmdline);
74 unlink(tmp_path);
75 g_free(tmp_path);
76 g_free(cmdline);
77
78 return qpci_init_pc(NULL);
79 }
80
81 static void arm_test_start(void)
82 {
83 char *cmdline;
84 char *tmp_path;
85
86 tmp_path = drive_create();
87
88 cmdline = g_strdup_printf("-machine virt "
89 "-drive if=none,id=drive0,file=%s,format=raw "
90 "-device virtio-blk-device,drive=drive0",
91 tmp_path);
92 qtest_start(cmdline);
93 unlink(tmp_path);
94 g_free(tmp_path);
95 g_free(cmdline);
96 }
97
98 static void test_end(void)
99 {
100 qtest_end();
101 }
102
103 static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
104 {
105 QVirtioPCIDevice *dev;
106
107 dev = qvirtio_pci_device_find(bus, VIRTIO_ID_BLOCK);
108 g_assert(dev != NULL);
109 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
110 g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN));
111
112 qvirtio_pci_device_enable(dev);
113 qvirtio_reset(&dev->vdev);
114 qvirtio_set_acknowledge(&dev->vdev);
115 qvirtio_set_driver(&dev->vdev);
116
117 return dev;
118 }
119
120 static inline void virtio_blk_fix_request(QVirtioBlkReq *req)
121 {
122 #ifdef HOST_WORDS_BIGENDIAN
123 bool host_endian = true;
124 #else
125 bool host_endian = false;
126 #endif
127
128 if (target_big_endian() != host_endian) {
129 req->type = bswap32(req->type);
130 req->ioprio = bswap32(req->ioprio);
131 req->sector = bswap64(req->sector);
132 }
133 }
134
135 static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioBlkReq *req,
136 uint64_t data_size)
137 {
138 uint64_t addr;
139 uint8_t status = 0xFF;
140
141 g_assert_cmpuint(data_size % 512, ==, 0);
142 addr = guest_alloc(alloc, sizeof(*req) + data_size);
143
144 virtio_blk_fix_request(req);
145
146 memwrite(addr, req, 16);
147 memwrite(addr + 16, req->data, data_size);
148 memwrite(addr + 16 + data_size, &status, sizeof(status));
149
150 return addr;
151 }
152
153 static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
154 QVirtQueue *vq, uint64_t device_specific)
155 {
156 QVirtioBlkReq req;
157 uint64_t req_addr;
158 uint64_t capacity;
159 uint32_t features;
160 uint32_t free_head;
161 uint8_t status;
162 char *data;
163
164 capacity = qvirtio_config_readq(dev, device_specific);
165
166 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
167
168 features = qvirtio_get_features(dev);
169 features = features & ~(QVIRTIO_F_BAD_FEATURE |
170 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
171 (1u << VIRTIO_RING_F_EVENT_IDX) |
172 (1u << VIRTIO_BLK_F_SCSI));
173 qvirtio_set_features(dev, features);
174
175 qvirtio_set_driver_ok(dev);
176
177 /* Write and read with 3 descriptor layout */
178 /* Write request */
179 req.type = VIRTIO_BLK_T_OUT;
180 req.ioprio = 1;
181 req.sector = 0;
182 req.data = g_malloc0(512);
183 strcpy(req.data, "TEST");
184
185 req_addr = virtio_blk_request(alloc, &req, 512);
186
187 g_free(req.data);
188
189 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
190 qvirtqueue_add(vq, req_addr + 16, 512, false, true);
191 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
192
193 qvirtqueue_kick(dev, vq, free_head);
194
195 qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
196 status = readb(req_addr + 528);
197 g_assert_cmpint(status, ==, 0);
198
199 guest_free(alloc, req_addr);
200
201 /* Read request */
202 req.type = VIRTIO_BLK_T_IN;
203 req.ioprio = 1;
204 req.sector = 0;
205 req.data = g_malloc0(512);
206
207 req_addr = virtio_blk_request(alloc, &req, 512);
208
209 g_free(req.data);
210
211 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
212 qvirtqueue_add(vq, req_addr + 16, 512, true, true);
213 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
214
215 qvirtqueue_kick(dev, vq, free_head);
216
217 qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
218 status = readb(req_addr + 528);
219 g_assert_cmpint(status, ==, 0);
220
221 data = g_malloc0(512);
222 memread(req_addr + 16, data, 512);
223 g_assert_cmpstr(data, ==, "TEST");
224 g_free(data);
225
226 guest_free(alloc, req_addr);
227
228 if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
229 /* Write and read with 2 descriptor layout */
230 /* Write request */
231 req.type = VIRTIO_BLK_T_OUT;
232 req.ioprio = 1;
233 req.sector = 1;
234 req.data = g_malloc0(512);
235 strcpy(req.data, "TEST");
236
237 req_addr = virtio_blk_request(alloc, &req, 512);
238
239 g_free(req.data);
240
241 free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
242 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
243 qvirtqueue_kick(dev, vq, free_head);
244
245 qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
246 status = readb(req_addr + 528);
247 g_assert_cmpint(status, ==, 0);
248
249 guest_free(alloc, req_addr);
250
251 /* Read request */
252 req.type = VIRTIO_BLK_T_IN;
253 req.ioprio = 1;
254 req.sector = 1;
255 req.data = g_malloc0(512);
256
257 req_addr = virtio_blk_request(alloc, &req, 512);
258
259 g_free(req.data);
260
261 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
262 qvirtqueue_add(vq, req_addr + 16, 513, true, false);
263
264 qvirtqueue_kick(dev, vq, free_head);
265
266 qvirtio_wait_queue_isr(dev, vq, QVIRTIO_BLK_TIMEOUT_US);
267 status = readb(req_addr + 528);
268 g_assert_cmpint(status, ==, 0);
269
270 data = g_malloc0(512);
271 memread(req_addr + 16, data, 512);
272 g_assert_cmpstr(data, ==, "TEST");
273 g_free(data);
274
275 guest_free(alloc, req_addr);
276 }
277 }
278
279 static void pci_basic(void)
280 {
281 QVirtioPCIDevice *dev;
282 QPCIBus *bus;
283 QVirtQueuePCI *vqpci;
284 QGuestAllocator *alloc;
285 void *addr;
286
287 bus = pci_test_start();
288 dev = virtio_blk_pci_init(bus, PCI_SLOT);
289
290 alloc = pc_alloc_init();
291 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, alloc, 0);
292
293 /* MSI-X is not enabled */
294 addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
295
296 test_basic(&dev->vdev, alloc, &vqpci->vq, (uint64_t)(uintptr_t)addr);
297
298 /* End test */
299 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, alloc);
300 pc_alloc_uninit(alloc);
301 qvirtio_pci_device_disable(dev);
302 g_free(dev);
303 qpci_free_pc(bus);
304 test_end();
305 }
306
307 static void pci_indirect(void)
308 {
309 QVirtioPCIDevice *dev;
310 QPCIBus *bus;
311 QVirtQueuePCI *vqpci;
312 QGuestAllocator *alloc;
313 QVirtioBlkReq req;
314 QVRingIndirectDesc *indirect;
315 void *addr;
316 uint64_t req_addr;
317 uint64_t capacity;
318 uint32_t features;
319 uint32_t free_head;
320 uint8_t status;
321 char *data;
322
323 bus = pci_test_start();
324
325 dev = virtio_blk_pci_init(bus, PCI_SLOT);
326
327 /* MSI-X is not enabled */
328 addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
329
330 capacity = qvirtio_config_readq(&dev->vdev, (uint64_t)(uintptr_t)addr);
331 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
332
333 features = qvirtio_get_features(&dev->vdev);
334 g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
335 features = features & ~(QVIRTIO_F_BAD_FEATURE |
336 (1u << VIRTIO_RING_F_EVENT_IDX) |
337 (1u << VIRTIO_BLK_F_SCSI));
338 qvirtio_set_features(&dev->vdev, features);
339
340 alloc = pc_alloc_init();
341 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, alloc, 0);
342 qvirtio_set_driver_ok(&dev->vdev);
343
344 /* Write request */
345 req.type = VIRTIO_BLK_T_OUT;
346 req.ioprio = 1;
347 req.sector = 0;
348 req.data = g_malloc0(512);
349 strcpy(req.data, "TEST");
350
351 req_addr = virtio_blk_request(alloc, &req, 512);
352
353 g_free(req.data);
354
355 indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);
356 qvring_indirect_desc_add(indirect, req_addr, 528, false);
357 qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
358 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
359 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
360
361 qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
362 QVIRTIO_BLK_TIMEOUT_US);
363 status = readb(req_addr + 528);
364 g_assert_cmpint(status, ==, 0);
365
366 g_free(indirect);
367 guest_free(alloc, req_addr);
368
369 /* Read request */
370 req.type = VIRTIO_BLK_T_IN;
371 req.ioprio = 1;
372 req.sector = 0;
373 req.data = g_malloc0(512);
374 strcpy(req.data, "TEST");
375
376 req_addr = virtio_blk_request(alloc, &req, 512);
377
378 g_free(req.data);
379
380 indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);
381 qvring_indirect_desc_add(indirect, req_addr, 16, false);
382 qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
383 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
384 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
385
386 qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
387 QVIRTIO_BLK_TIMEOUT_US);
388 status = readb(req_addr + 528);
389 g_assert_cmpint(status, ==, 0);
390
391 data = g_malloc0(512);
392 memread(req_addr + 16, data, 512);
393 g_assert_cmpstr(data, ==, "TEST");
394 g_free(data);
395
396 g_free(indirect);
397 guest_free(alloc, req_addr);
398
399 /* End test */
400 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, alloc);
401 pc_alloc_uninit(alloc);
402 qvirtio_pci_device_disable(dev);
403 g_free(dev);
404 qpci_free_pc(bus);
405 test_end();
406 }
407
408 static void pci_config(void)
409 {
410 QVirtioPCIDevice *dev;
411 QPCIBus *bus;
412 int n_size = TEST_IMAGE_SIZE / 2;
413 void *addr;
414 uint64_t capacity;
415
416 bus = pci_test_start();
417
418 dev = virtio_blk_pci_init(bus, PCI_SLOT);
419
420 /* MSI-X is not enabled */
421 addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(false);
422
423 capacity = qvirtio_config_readq(&dev->vdev, (uint64_t)(uintptr_t)addr);
424 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
425
426 qvirtio_set_driver_ok(&dev->vdev);
427
428 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
429 " 'size': %d } }", n_size);
430 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
431
432 capacity = qvirtio_config_readq(&dev->vdev, (uint64_t)(uintptr_t)addr);
433 g_assert_cmpint(capacity, ==, n_size / 512);
434
435 qvirtio_pci_device_disable(dev);
436 g_free(dev);
437 qpci_free_pc(bus);
438 test_end();
439 }
440
441 static void pci_msix(void)
442 {
443 QVirtioPCIDevice *dev;
444 QPCIBus *bus;
445 QVirtQueuePCI *vqpci;
446 QGuestAllocator *alloc;
447 QVirtioBlkReq req;
448 int n_size = TEST_IMAGE_SIZE / 2;
449 void *addr;
450 uint64_t req_addr;
451 uint64_t capacity;
452 uint32_t features;
453 uint32_t free_head;
454 uint8_t status;
455 char *data;
456
457 bus = pci_test_start();
458 alloc = pc_alloc_init();
459
460 dev = virtio_blk_pci_init(bus, PCI_SLOT);
461 qpci_msix_enable(dev->pdev);
462
463 qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
464
465 /* MSI-X is enabled */
466 addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
467
468 capacity = qvirtio_config_readq(&dev->vdev, (uint64_t)(uintptr_t)addr);
469 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
470
471 features = qvirtio_get_features(&dev->vdev);
472 features = features & ~(QVIRTIO_F_BAD_FEATURE |
473 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
474 (1u << VIRTIO_RING_F_EVENT_IDX) |
475 (1u << VIRTIO_BLK_F_SCSI));
476 qvirtio_set_features(&dev->vdev, features);
477
478 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, alloc, 0);
479 qvirtqueue_pci_msix_setup(dev, vqpci, alloc, 1);
480
481 qvirtio_set_driver_ok(&dev->vdev);
482
483 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
484 " 'size': %d } }", n_size);
485
486 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
487
488 capacity = qvirtio_config_readq(&dev->vdev, (uintptr_t)addr);
489 g_assert_cmpint(capacity, ==, n_size / 512);
490
491 /* Write request */
492 req.type = VIRTIO_BLK_T_OUT;
493 req.ioprio = 1;
494 req.sector = 0;
495 req.data = g_malloc0(512);
496 strcpy(req.data, "TEST");
497
498 req_addr = virtio_blk_request(alloc, &req, 512);
499
500 g_free(req.data);
501
502 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
503 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
504 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
505 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
506
507 qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
508 QVIRTIO_BLK_TIMEOUT_US);
509
510 status = readb(req_addr + 528);
511 g_assert_cmpint(status, ==, 0);
512
513 guest_free(alloc, req_addr);
514
515 /* Read request */
516 req.type = VIRTIO_BLK_T_IN;
517 req.ioprio = 1;
518 req.sector = 0;
519 req.data = g_malloc0(512);
520
521 req_addr = virtio_blk_request(alloc, &req, 512);
522
523 g_free(req.data);
524
525 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
526 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
527 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
528
529 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
530
531
532 qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
533 QVIRTIO_BLK_TIMEOUT_US);
534
535 status = readb(req_addr + 528);
536 g_assert_cmpint(status, ==, 0);
537
538 data = g_malloc0(512);
539 memread(req_addr + 16, data, 512);
540 g_assert_cmpstr(data, ==, "TEST");
541 g_free(data);
542
543 guest_free(alloc, req_addr);
544
545 /* End test */
546 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, alloc);
547 pc_alloc_uninit(alloc);
548 qpci_msix_disable(dev->pdev);
549 qvirtio_pci_device_disable(dev);
550 g_free(dev);
551 qpci_free_pc(bus);
552 test_end();
553 }
554
555 static void pci_idx(void)
556 {
557 QVirtioPCIDevice *dev;
558 QPCIBus *bus;
559 QVirtQueuePCI *vqpci;
560 QGuestAllocator *alloc;
561 QVirtioBlkReq req;
562 void *addr;
563 uint64_t req_addr;
564 uint64_t capacity;
565 uint32_t features;
566 uint32_t free_head;
567 uint8_t status;
568 char *data;
569
570 bus = pci_test_start();
571 alloc = pc_alloc_init();
572
573 dev = virtio_blk_pci_init(bus, PCI_SLOT);
574 qpci_msix_enable(dev->pdev);
575
576 qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
577
578 /* MSI-X is enabled */
579 addr = dev->addr + VIRTIO_PCI_CONFIG_OFF(true);
580
581 capacity = qvirtio_config_readq(&dev->vdev, (uint64_t)(uintptr_t)addr);
582 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
583
584 features = qvirtio_get_features(&dev->vdev);
585 features = features & ~(QVIRTIO_F_BAD_FEATURE |
586 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
587 (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
588 (1u << VIRTIO_BLK_F_SCSI));
589 qvirtio_set_features(&dev->vdev, features);
590
591 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, alloc, 0);
592 qvirtqueue_pci_msix_setup(dev, vqpci, alloc, 1);
593
594 qvirtio_set_driver_ok(&dev->vdev);
595
596 /* Write request */
597 req.type = VIRTIO_BLK_T_OUT;
598 req.ioprio = 1;
599 req.sector = 0;
600 req.data = g_malloc0(512);
601 strcpy(req.data, "TEST");
602
603 req_addr = virtio_blk_request(alloc, &req, 512);
604
605 g_free(req.data);
606
607 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
608 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
609 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
610 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
611
612 qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq, QVIRTIO_BLK_TIMEOUT_US);
613
614 /* Write request */
615 req.type = VIRTIO_BLK_T_OUT;
616 req.ioprio = 1;
617 req.sector = 1;
618 req.data = g_malloc0(512);
619 strcpy(req.data, "TEST");
620
621 req_addr = virtio_blk_request(alloc, &req, 512);
622
623 g_free(req.data);
624
625 /* Notify after processing the third request */
626 qvirtqueue_set_used_event(&vqpci->vq, 2);
627 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
628 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
629 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
630 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
631
632 /* No notification expected */
633 status = qvirtio_wait_status_byte_no_isr(&dev->vdev,
634 &vqpci->vq, req_addr + 528,
635 QVIRTIO_BLK_TIMEOUT_US);
636 g_assert_cmpint(status, ==, 0);
637
638 guest_free(alloc, req_addr);
639
640 /* Read request */
641 req.type = VIRTIO_BLK_T_IN;
642 req.ioprio = 1;
643 req.sector = 1;
644 req.data = g_malloc0(512);
645
646 req_addr = virtio_blk_request(alloc, &req, 512);
647
648 g_free(req.data);
649
650 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
651 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
652 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
653
654 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
655
656 qvirtio_wait_queue_isr(&dev->vdev, &vqpci->vq,
657 QVIRTIO_BLK_TIMEOUT_US);
658
659 status = readb(req_addr + 528);
660 g_assert_cmpint(status, ==, 0);
661
662 data = g_malloc0(512);
663 memread(req_addr + 16, data, 512);
664 g_assert_cmpstr(data, ==, "TEST");
665 g_free(data);
666
667 guest_free(alloc, req_addr);
668
669 /* End test */
670 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, alloc);
671 pc_alloc_uninit(alloc);
672 qpci_msix_disable(dev->pdev);
673 qvirtio_pci_device_disable(dev);
674 g_free(dev);
675 qpci_free_pc(bus);
676 test_end();
677 }
678
679 static void pci_hotplug(void)
680 {
681 QPCIBus *bus;
682 QVirtioPCIDevice *dev;
683
684 bus = pci_test_start();
685
686 /* plug secondary disk */
687 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP,
688 "'drive': 'drive1'");
689
690 dev = virtio_blk_pci_init(bus, PCI_SLOT_HP);
691 g_assert(dev);
692 qvirtio_pci_device_disable(dev);
693 g_free(dev);
694
695 /* unplug secondary disk */
696 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
697 qpci_free_pc(bus);
698 test_end();
699 }
700
701 static void mmio_basic(void)
702 {
703 QVirtioMMIODevice *dev;
704 QVirtQueue *vq;
705 QGuestAllocator *alloc;
706 int n_size = TEST_IMAGE_SIZE / 2;
707 uint64_t capacity;
708
709 arm_test_start();
710
711 dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
712 g_assert(dev != NULL);
713 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
714
715 qvirtio_reset(&dev->vdev);
716 qvirtio_set_acknowledge(&dev->vdev);
717 qvirtio_set_driver(&dev->vdev);
718
719 alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
720 vq = qvirtqueue_setup(&dev->vdev, alloc, 0);
721
722 test_basic(&dev->vdev, alloc, vq, QVIRTIO_MMIO_DEVICE_SPECIFIC);
723
724 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
725 " 'size': %d } }", n_size);
726
727 qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US);
728
729 capacity = qvirtio_config_readq(&dev->vdev, QVIRTIO_MMIO_DEVICE_SPECIFIC);
730 g_assert_cmpint(capacity, ==, n_size / 512);
731
732 /* End test */
733 qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
734 generic_alloc_uninit(alloc);
735 g_free(dev);
736 test_end();
737 }
738
739 int main(int argc, char **argv)
740 {
741 const char *arch = qtest_get_arch();
742
743 g_test_init(&argc, &argv, NULL);
744
745 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
746 qtest_add_func("/virtio/blk/pci/basic", pci_basic);
747 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
748 qtest_add_func("/virtio/blk/pci/config", pci_config);
749 qtest_add_func("/virtio/blk/pci/msix", pci_msix);
750 qtest_add_func("/virtio/blk/pci/idx", pci_idx);
751 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
752 } else if (strcmp(arch, "arm") == 0) {
753 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
754 }
755
756 return g_test_run();
757 }