]> git.proxmox.com Git - mirror_qemu.git/blob - tests/virtio-blk-test.c
tests/virtio-blk: add virtio_blk_fix_dwz_hdr() function
[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/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"
26
27 /* TODO actually test the results and get rid of this */
28 #define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__))
29
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
35
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
40
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;
48
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
54
55 static char *drive_create(void)
56 {
57 int fd, ret;
58 char *tmp_path = g_strdup("/tmp/qtest.XXXXXX");
59
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);
66
67 return tmp_path;
68 }
69
70 static QOSState *pci_test_start(void)
71 {
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";
79
80 tmp_path = drive_create();
81
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);
89 }
90 global_qtest = qs->qts;
91 unlink(tmp_path);
92 g_free(tmp_path);
93 return qs;
94 }
95
96 static void arm_test_start(void)
97 {
98 char *tmp_path;
99
100 tmp_path = drive_create();
101
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);
108 }
109
110 static void test_end(void)
111 {
112 qtest_end();
113 }
114
115 static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
116 {
117 QVirtioPCIDevice *dev;
118
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));
123
124 qvirtio_pci_device_enable(dev);
125 qvirtio_reset(&dev->vdev);
126 qvirtio_set_acknowledge(&dev->vdev);
127 qvirtio_set_driver(&dev->vdev);
128
129 return dev;
130 }
131
132 static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
133 {
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);
138 }
139 }
140
141
142 static inline void virtio_blk_fix_dwz_hdr(QVirtioDevice *d,
143 struct virtio_blk_discard_write_zeroes *dwz_hdr)
144 {
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);
149 }
150 }
151
152 static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
153 QVirtioBlkReq *req, uint64_t data_size)
154 {
155 uint64_t addr;
156 uint8_t status = 0xFF;
157
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);
170 }
171
172 addr = guest_alloc(alloc, sizeof(*req) + data_size);
173
174 virtio_blk_fix_request(d, req);
175
176 memwrite(addr, req, 16);
177 memwrite(addr + 16, req->data, data_size);
178 memwrite(addr + 16 + data_size, &status, sizeof(status));
179
180 return addr;
181 }
182
183 static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
184 QVirtQueue *vq)
185 {
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;
193
194 capacity = qvirtio_config_readq(dev, 0);
195
196 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
197
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);
204
205 qvirtio_set_driver_ok(dev);
206
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");
214
215 req_addr = virtio_blk_request(alloc, dev, &req, 512);
216
217 g_free(req.data);
218
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);
222
223 qvirtqueue_kick(dev, vq, free_head);
224
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);
228
229 guest_free(alloc, req_addr);
230
231 /* Read request */
232 req.type = VIRTIO_BLK_T_IN;
233 req.ioprio = 1;
234 req.sector = 0;
235 req.data = g_malloc0(512);
236
237 req_addr = virtio_blk_request(alloc, dev, &req, 512);
238
239 g_free(req.data);
240
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);
244
245 qvirtqueue_kick(dev, vq, free_head);
246
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);
250
251 data = g_malloc0(512);
252 memread(req_addr + 16, data, 512);
253 g_assert_cmpstr(data, ==, "TEST");
254 g_free(data);
255
256 guest_free(alloc, req_addr);
257
258 if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
259 /* Write and read with 2 descriptor layout */
260 /* Write request */
261 req.type = VIRTIO_BLK_T_OUT;
262 req.ioprio = 1;
263 req.sector = 1;
264 req.data = g_malloc0(512);
265 strcpy(req.data, "TEST");
266
267 req_addr = virtio_blk_request(alloc, dev, &req, 512);
268
269 g_free(req.data);
270
271 free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
272 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
273 qvirtqueue_kick(dev, vq, free_head);
274
275 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
276 QVIRTIO_BLK_TIMEOUT_US);
277 status = readb(req_addr + 528);
278 g_assert_cmpint(status, ==, 0);
279
280 guest_free(alloc, req_addr);
281
282 /* Read request */
283 req.type = VIRTIO_BLK_T_IN;
284 req.ioprio = 1;
285 req.sector = 1;
286 req.data = g_malloc0(512);
287
288 req_addr = virtio_blk_request(alloc, dev, &req, 512);
289
290 g_free(req.data);
291
292 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
293 qvirtqueue_add(vq, req_addr + 16, 513, true, false);
294
295 qvirtqueue_kick(dev, vq, free_head);
296
297 qvirtio_wait_used_elem(dev, vq, free_head, NULL,
298 QVIRTIO_BLK_TIMEOUT_US);
299 status = readb(req_addr + 528);
300 g_assert_cmpint(status, ==, 0);
301
302 data = g_malloc0(512);
303 memread(req_addr + 16, data, 512);
304 g_assert_cmpstr(data, ==, "TEST");
305 g_free(data);
306
307 guest_free(alloc, req_addr);
308 }
309 }
310
311 static void pci_basic(void)
312 {
313 QVirtioPCIDevice *dev;
314 QOSState *qs;
315 QVirtQueuePCI *vqpci;
316
317 qs = pci_test_start();
318 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
319
320 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
321
322 test_basic(&dev->vdev, qs->alloc, &vqpci->vq);
323
324 /* End test */
325 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
326 qvirtio_pci_device_disable(dev);
327 qvirtio_pci_device_free(dev);
328 qtest_shutdown(qs);
329 }
330
331 static void pci_indirect(void)
332 {
333 QVirtioPCIDevice *dev;
334 QVirtQueuePCI *vqpci;
335 QOSState *qs;
336 QVirtioBlkReq req;
337 QVRingIndirectDesc *indirect;
338 uint64_t req_addr;
339 uint64_t capacity;
340 uint32_t features;
341 uint32_t free_head;
342 uint8_t status;
343 char *data;
344
345 qs = pci_test_start();
346
347 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
348
349 capacity = qvirtio_config_readq(&dev->vdev, 0);
350 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
351
352 features = qvirtio_get_features(&dev->vdev);
353 g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
354 features = features & ~(QVIRTIO_F_BAD_FEATURE |
355 (1u << VIRTIO_RING_F_EVENT_IDX) |
356 (1u << VIRTIO_BLK_F_SCSI));
357 qvirtio_set_features(&dev->vdev, features);
358
359 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
360 qvirtio_set_driver_ok(&dev->vdev);
361
362 /* Write request */
363 req.type = VIRTIO_BLK_T_OUT;
364 req.ioprio = 1;
365 req.sector = 0;
366 req.data = g_malloc0(512);
367 strcpy(req.data, "TEST");
368
369 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
370
371 g_free(req.data);
372
373 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
374 qvring_indirect_desc_add(indirect, req_addr, 528, false);
375 qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
376 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
377 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
378
379 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
380 QVIRTIO_BLK_TIMEOUT_US);
381 status = readb(req_addr + 528);
382 g_assert_cmpint(status, ==, 0);
383
384 g_free(indirect);
385 guest_free(qs->alloc, req_addr);
386
387 /* Read request */
388 req.type = VIRTIO_BLK_T_IN;
389 req.ioprio = 1;
390 req.sector = 0;
391 req.data = g_malloc0(512);
392 strcpy(req.data, "TEST");
393
394 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
395
396 g_free(req.data);
397
398 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
399 qvring_indirect_desc_add(indirect, req_addr, 16, false);
400 qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
401 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
402 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
403
404 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
405 QVIRTIO_BLK_TIMEOUT_US);
406 status = readb(req_addr + 528);
407 g_assert_cmpint(status, ==, 0);
408
409 data = g_malloc0(512);
410 memread(req_addr + 16, data, 512);
411 g_assert_cmpstr(data, ==, "TEST");
412 g_free(data);
413
414 g_free(indirect);
415 guest_free(qs->alloc, req_addr);
416
417 /* End test */
418 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
419 qvirtio_pci_device_disable(dev);
420 qvirtio_pci_device_free(dev);
421 qtest_shutdown(qs);
422 }
423
424 static void pci_config(void)
425 {
426 QVirtioPCIDevice *dev;
427 QOSState *qs;
428 int n_size = TEST_IMAGE_SIZE / 2;
429 uint64_t capacity;
430
431 qs = pci_test_start();
432
433 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
434
435 capacity = qvirtio_config_readq(&dev->vdev, 0);
436 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
437
438 qvirtio_set_driver_ok(&dev->vdev);
439
440 qmp_discard_response("{ 'execute': 'block_resize', "
441 " 'arguments': { 'device': 'drive0', "
442 " 'size': %d } }", n_size);
443 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
444
445 capacity = qvirtio_config_readq(&dev->vdev, 0);
446 g_assert_cmpint(capacity, ==, n_size / 512);
447
448 qvirtio_pci_device_disable(dev);
449 qvirtio_pci_device_free(dev);
450
451 qtest_shutdown(qs);
452 }
453
454 static void pci_msix(void)
455 {
456 QVirtioPCIDevice *dev;
457 QOSState *qs;
458 QVirtQueuePCI *vqpci;
459 QVirtioBlkReq req;
460 int n_size = TEST_IMAGE_SIZE / 2;
461 uint64_t req_addr;
462 uint64_t capacity;
463 uint32_t features;
464 uint32_t free_head;
465 uint8_t status;
466 char *data;
467
468 qs = pci_test_start();
469
470 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
471 qpci_msix_enable(dev->pdev);
472
473 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
474
475 capacity = qvirtio_config_readq(&dev->vdev, 0);
476 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
477
478 features = qvirtio_get_features(&dev->vdev);
479 features = features & ~(QVIRTIO_F_BAD_FEATURE |
480 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
481 (1u << VIRTIO_RING_F_EVENT_IDX) |
482 (1u << VIRTIO_BLK_F_SCSI));
483 qvirtio_set_features(&dev->vdev, features);
484
485 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
486 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
487
488 qvirtio_set_driver_ok(&dev->vdev);
489
490 qmp_discard_response("{ 'execute': 'block_resize', "
491 " 'arguments': { 'device': 'drive0', "
492 " 'size': %d } }", n_size);
493
494 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
495
496 capacity = qvirtio_config_readq(&dev->vdev, 0);
497 g_assert_cmpint(capacity, ==, n_size / 512);
498
499 /* Write request */
500 req.type = VIRTIO_BLK_T_OUT;
501 req.ioprio = 1;
502 req.sector = 0;
503 req.data = g_malloc0(512);
504 strcpy(req.data, "TEST");
505
506 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
507
508 g_free(req.data);
509
510 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
511 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
512 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
513 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
514
515 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
516 QVIRTIO_BLK_TIMEOUT_US);
517
518 status = readb(req_addr + 528);
519 g_assert_cmpint(status, ==, 0);
520
521 guest_free(qs->alloc, req_addr);
522
523 /* Read request */
524 req.type = VIRTIO_BLK_T_IN;
525 req.ioprio = 1;
526 req.sector = 0;
527 req.data = g_malloc0(512);
528
529 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
530
531 g_free(req.data);
532
533 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
534 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
535 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
536
537 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
538
539
540 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
541 QVIRTIO_BLK_TIMEOUT_US);
542
543 status = readb(req_addr + 528);
544 g_assert_cmpint(status, ==, 0);
545
546 data = g_malloc0(512);
547 memread(req_addr + 16, data, 512);
548 g_assert_cmpstr(data, ==, "TEST");
549 g_free(data);
550
551 guest_free(qs->alloc, req_addr);
552
553 /* End test */
554 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
555 qpci_msix_disable(dev->pdev);
556 qvirtio_pci_device_disable(dev);
557 qvirtio_pci_device_free(dev);
558 qtest_shutdown(qs);
559 }
560
561 static void pci_idx(void)
562 {
563 QVirtioPCIDevice *dev;
564 QOSState *qs;
565 QVirtQueuePCI *vqpci;
566 QVirtioBlkReq req;
567 uint64_t req_addr;
568 uint64_t capacity;
569 uint32_t features;
570 uint32_t free_head;
571 uint32_t write_head;
572 uint32_t desc_idx;
573 uint8_t status;
574 char *data;
575
576 qs = pci_test_start();
577
578 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
579 qpci_msix_enable(dev->pdev);
580
581 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
582
583 capacity = qvirtio_config_readq(&dev->vdev, 0);
584 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
585
586 features = qvirtio_get_features(&dev->vdev);
587 features = features & ~(QVIRTIO_F_BAD_FEATURE |
588 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
589 (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
590 (1u << VIRTIO_BLK_F_SCSI));
591 qvirtio_set_features(&dev->vdev, features);
592
593 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
594 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
595
596 qvirtio_set_driver_ok(&dev->vdev);
597
598 /* Write request */
599 req.type = VIRTIO_BLK_T_OUT;
600 req.ioprio = 1;
601 req.sector = 0;
602 req.data = g_malloc0(512);
603 strcpy(req.data, "TEST");
604
605 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
606
607 g_free(req.data);
608
609 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
610 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
611 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
612 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
613
614 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
615 QVIRTIO_BLK_TIMEOUT_US);
616
617 /* Write request */
618 req.type = VIRTIO_BLK_T_OUT;
619 req.ioprio = 1;
620 req.sector = 1;
621 req.data = g_malloc0(512);
622 strcpy(req.data, "TEST");
623
624 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
625
626 g_free(req.data);
627
628 /* Notify after processing the third request */
629 qvirtqueue_set_used_event(&vqpci->vq, 2);
630 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
631 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
632 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
633 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
634 write_head = free_head;
635
636 /* No notification expected */
637 status = qvirtio_wait_status_byte_no_isr(&dev->vdev,
638 &vqpci->vq, req_addr + 528,
639 QVIRTIO_BLK_TIMEOUT_US);
640 g_assert_cmpint(status, ==, 0);
641
642 guest_free(qs->alloc, req_addr);
643
644 /* Read request */
645 req.type = VIRTIO_BLK_T_IN;
646 req.ioprio = 1;
647 req.sector = 1;
648 req.data = g_malloc0(512);
649
650 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
651
652 g_free(req.data);
653
654 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
655 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
656 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
657
658 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
659
660 /* We get just one notification for both requests */
661 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head, NULL,
662 QVIRTIO_BLK_TIMEOUT_US);
663 g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx, NULL));
664 g_assert_cmpint(desc_idx, ==, free_head);
665
666 status = readb(req_addr + 528);
667 g_assert_cmpint(status, ==, 0);
668
669 data = g_malloc0(512);
670 memread(req_addr + 16, data, 512);
671 g_assert_cmpstr(data, ==, "TEST");
672 g_free(data);
673
674 guest_free(qs->alloc, req_addr);
675
676 /* End test */
677 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
678 qpci_msix_disable(dev->pdev);
679 qvirtio_pci_device_disable(dev);
680 qvirtio_pci_device_free(dev);
681 qtest_shutdown(qs);
682 }
683
684 static void pci_hotplug(void)
685 {
686 QVirtioPCIDevice *dev;
687 QOSState *qs;
688 const char *arch = qtest_get_arch();
689
690 qs = pci_test_start();
691
692 /* plug secondary disk */
693 qtest_qmp_device_add("virtio-blk-pci", "drv1",
694 "{'addr': %s, 'drive': 'drive1'}",
695 stringify(PCI_SLOT_HP));
696
697 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT_HP);
698 g_assert(dev);
699 qvirtio_pci_device_disable(dev);
700 qvirtio_pci_device_free(dev);
701
702 /* unplug secondary disk */
703 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
704 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
705 }
706 qtest_shutdown(qs);
707 }
708
709 /*
710 * Check that setting the vring addr on a non-existent virtqueue does
711 * not crash.
712 */
713 static void test_nonexistent_virtqueue(void)
714 {
715 QPCIBar bar0;
716 QOSState *qs;
717 QPCIDevice *dev;
718
719 qs = pci_test_start();
720 dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4, 0));
721 g_assert(dev != NULL);
722
723 qpci_device_enable(dev);
724 bar0 = qpci_iomap(dev, 0, NULL);
725
726 qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2);
727 qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1);
728
729 g_free(dev);
730 qtest_shutdown(qs);
731 }
732
733 static void mmio_basic(void)
734 {
735 QVirtioMMIODevice *dev;
736 QVirtQueue *vq;
737 QGuestAllocator *alloc;
738 int n_size = TEST_IMAGE_SIZE / 2;
739 uint64_t capacity;
740
741 arm_test_start();
742
743 dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
744 g_assert(dev != NULL);
745 g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
746
747 qvirtio_reset(&dev->vdev);
748 qvirtio_set_acknowledge(&dev->vdev);
749 qvirtio_set_driver(&dev->vdev);
750
751 alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
752 vq = qvirtqueue_setup(&dev->vdev, alloc, 0);
753
754 test_basic(&dev->vdev, alloc, vq);
755
756 qmp_discard_response("{ 'execute': 'block_resize', "
757 " 'arguments': { 'device': 'drive0', "
758 " 'size': %d } }", n_size);
759
760 qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US);
761
762 capacity = qvirtio_config_readq(&dev->vdev, 0);
763 g_assert_cmpint(capacity, ==, n_size / 512);
764
765 /* End test */
766 qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
767 g_free(dev);
768 generic_alloc_uninit(alloc);
769 test_end();
770 }
771
772 int main(int argc, char **argv)
773 {
774 const char *arch = qtest_get_arch();
775
776 g_test_init(&argc, &argv, NULL);
777
778 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0 ||
779 strcmp(arch, "ppc64") == 0) {
780 qtest_add_func("/virtio/blk/pci/basic", pci_basic);
781 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
782 qtest_add_func("/virtio/blk/pci/config", pci_config);
783 qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue);
784 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
785 qtest_add_func("/virtio/blk/pci/msix", pci_msix);
786 qtest_add_func("/virtio/blk/pci/idx", pci_idx);
787 }
788 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
789 } else if (strcmp(arch, "arm") == 0) {
790 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
791 }
792
793 return g_test_run();
794 }