]> git.proxmox.com Git - mirror_qemu.git/blob - tests/virtio-blk-test.c
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20180112-pull-request' into...
[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 "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"
25
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
31
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
36
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;
44
45 static char *drive_create(void)
46 {
47 int fd, ret;
48 char *tmp_path = g_strdup("/tmp/qtest.XXXXXX");
49
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);
56
57 return tmp_path;
58 }
59
60 static QOSState *pci_test_start(void)
61 {
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";
69
70 tmp_path = drive_create();
71
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);
79 }
80 unlink(tmp_path);
81 g_free(tmp_path);
82 return qs;
83 }
84
85 static void arm_test_start(void)
86 {
87 char *tmp_path;
88
89 tmp_path = drive_create();
90
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);
97 }
98
99 static void test_end(void)
100 {
101 qtest_end();
102 }
103
104 static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
105 {
106 QVirtioPCIDevice *dev;
107
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));
112
113 qvirtio_pci_device_enable(dev);
114 qvirtio_reset(&dev->vdev);
115 qvirtio_set_acknowledge(&dev->vdev);
116 qvirtio_set_driver(&dev->vdev);
117
118 return dev;
119 }
120
121 static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
122 {
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
128
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);
133 }
134 }
135
136 static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
137 QVirtioBlkReq *req, uint64_t data_size)
138 {
139 uint64_t addr;
140 uint8_t status = 0xFF;
141
142 g_assert_cmpuint(data_size % 512, ==, 0);
143 addr = guest_alloc(alloc, sizeof(*req) + data_size);
144
145 virtio_blk_fix_request(d, req);
146
147 memwrite(addr, req, 16);
148 memwrite(addr + 16, req->data, data_size);
149 memwrite(addr + 16 + data_size, &status, sizeof(status));
150
151 return addr;
152 }
153
154 static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
155 QVirtQueue *vq)
156 {
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;
164
165 capacity = qvirtio_config_readq(dev, 0);
166
167 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
168
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);
175
176 qvirtio_set_driver_ok(dev);
177
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");
185
186 req_addr = virtio_blk_request(alloc, dev, &req, 512);
187
188 g_free(req.data);
189
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);
193
194 qvirtqueue_kick(dev, vq, free_head);
195
196 qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
197 status = readb(req_addr + 528);
198 g_assert_cmpint(status, ==, 0);
199
200 guest_free(alloc, req_addr);
201
202 /* Read request */
203 req.type = VIRTIO_BLK_T_IN;
204 req.ioprio = 1;
205 req.sector = 0;
206 req.data = g_malloc0(512);
207
208 req_addr = virtio_blk_request(alloc, dev, &req, 512);
209
210 g_free(req.data);
211
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);
215
216 qvirtqueue_kick(dev, vq, free_head);
217
218 qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
219 status = readb(req_addr + 528);
220 g_assert_cmpint(status, ==, 0);
221
222 data = g_malloc0(512);
223 memread(req_addr + 16, data, 512);
224 g_assert_cmpstr(data, ==, "TEST");
225 g_free(data);
226
227 guest_free(alloc, req_addr);
228
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");
237
238 req_addr = virtio_blk_request(alloc, dev, &req, 512);
239
240 g_free(req.data);
241
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);
245
246 qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
247 status = readb(req_addr + 528);
248 g_assert_cmpint(status, ==, 0);
249
250 guest_free(alloc, req_addr);
251
252 /* Read request */
253 req.type = VIRTIO_BLK_T_IN;
254 req.ioprio = 1;
255 req.sector = 1;
256 req.data = g_malloc0(512);
257
258 req_addr = virtio_blk_request(alloc, dev, &req, 512);
259
260 g_free(req.data);
261
262 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
263 qvirtqueue_add(vq, req_addr + 16, 513, true, false);
264
265 qvirtqueue_kick(dev, vq, free_head);
266
267 qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_BLK_TIMEOUT_US);
268 status = readb(req_addr + 528);
269 g_assert_cmpint(status, ==, 0);
270
271 data = g_malloc0(512);
272 memread(req_addr + 16, data, 512);
273 g_assert_cmpstr(data, ==, "TEST");
274 g_free(data);
275
276 guest_free(alloc, req_addr);
277 }
278 }
279
280 static void pci_basic(void)
281 {
282 QVirtioPCIDevice *dev;
283 QOSState *qs;
284 QVirtQueuePCI *vqpci;
285
286 qs = pci_test_start();
287 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
288
289 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
290
291 test_basic(&dev->vdev, qs->alloc, &vqpci->vq);
292
293 /* End test */
294 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
295 qvirtio_pci_device_disable(dev);
296 qvirtio_pci_device_free(dev);
297 qtest_shutdown(qs);
298 }
299
300 static void pci_indirect(void)
301 {
302 QVirtioPCIDevice *dev;
303 QVirtQueuePCI *vqpci;
304 QOSState *qs;
305 QVirtioBlkReq req;
306 QVRingIndirectDesc *indirect;
307 uint64_t req_addr;
308 uint64_t capacity;
309 uint32_t features;
310 uint32_t free_head;
311 uint8_t status;
312 char *data;
313
314 qs = pci_test_start();
315
316 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
317
318 capacity = qvirtio_config_readq(&dev->vdev, 0);
319 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
320
321 features = qvirtio_get_features(&dev->vdev);
322 g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
323 features = features & ~(QVIRTIO_F_BAD_FEATURE |
324 (1u << VIRTIO_RING_F_EVENT_IDX) |
325 (1u << VIRTIO_BLK_F_SCSI));
326 qvirtio_set_features(&dev->vdev, features);
327
328 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
329 qvirtio_set_driver_ok(&dev->vdev);
330
331 /* Write request */
332 req.type = VIRTIO_BLK_T_OUT;
333 req.ioprio = 1;
334 req.sector = 0;
335 req.data = g_malloc0(512);
336 strcpy(req.data, "TEST");
337
338 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
339
340 g_free(req.data);
341
342 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
343 qvring_indirect_desc_add(indirect, req_addr, 528, false);
344 qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
345 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
346 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
347
348 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
349 QVIRTIO_BLK_TIMEOUT_US);
350 status = readb(req_addr + 528);
351 g_assert_cmpint(status, ==, 0);
352
353 g_free(indirect);
354 guest_free(qs->alloc, req_addr);
355
356 /* Read request */
357 req.type = VIRTIO_BLK_T_IN;
358 req.ioprio = 1;
359 req.sector = 0;
360 req.data = g_malloc0(512);
361 strcpy(req.data, "TEST");
362
363 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
364
365 g_free(req.data);
366
367 indirect = qvring_indirect_desc_setup(&dev->vdev, qs->alloc, 2);
368 qvring_indirect_desc_add(indirect, req_addr, 16, false);
369 qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
370 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
371 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
372
373 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
374 QVIRTIO_BLK_TIMEOUT_US);
375 status = readb(req_addr + 528);
376 g_assert_cmpint(status, ==, 0);
377
378 data = g_malloc0(512);
379 memread(req_addr + 16, data, 512);
380 g_assert_cmpstr(data, ==, "TEST");
381 g_free(data);
382
383 g_free(indirect);
384 guest_free(qs->alloc, req_addr);
385
386 /* End test */
387 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
388 qvirtio_pci_device_disable(dev);
389 qvirtio_pci_device_free(dev);
390 qtest_shutdown(qs);
391 }
392
393 static void pci_config(void)
394 {
395 QVirtioPCIDevice *dev;
396 QOSState *qs;
397 int n_size = TEST_IMAGE_SIZE / 2;
398 uint64_t capacity;
399
400 qs = pci_test_start();
401
402 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
403
404 capacity = qvirtio_config_readq(&dev->vdev, 0);
405 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
406
407 qvirtio_set_driver_ok(&dev->vdev);
408
409 qmp_discard_response("{ 'execute': 'block_resize', "
410 " 'arguments': { 'device': 'drive0', "
411 " 'size': %d } }", n_size);
412 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
413
414 capacity = qvirtio_config_readq(&dev->vdev, 0);
415 g_assert_cmpint(capacity, ==, n_size / 512);
416
417 qvirtio_pci_device_disable(dev);
418 qvirtio_pci_device_free(dev);
419
420 qtest_shutdown(qs);
421 }
422
423 static void pci_msix(void)
424 {
425 QVirtioPCIDevice *dev;
426 QOSState *qs;
427 QVirtQueuePCI *vqpci;
428 QVirtioBlkReq req;
429 int n_size = TEST_IMAGE_SIZE / 2;
430 uint64_t req_addr;
431 uint64_t capacity;
432 uint32_t features;
433 uint32_t free_head;
434 uint8_t status;
435 char *data;
436
437 qs = pci_test_start();
438
439 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
440 qpci_msix_enable(dev->pdev);
441
442 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
443
444 capacity = qvirtio_config_readq(&dev->vdev, 0);
445 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
446
447 features = qvirtio_get_features(&dev->vdev);
448 features = features & ~(QVIRTIO_F_BAD_FEATURE |
449 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
450 (1u << VIRTIO_RING_F_EVENT_IDX) |
451 (1u << VIRTIO_BLK_F_SCSI));
452 qvirtio_set_features(&dev->vdev, features);
453
454 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
455 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
456
457 qvirtio_set_driver_ok(&dev->vdev);
458
459 qmp_discard_response("{ 'execute': 'block_resize', "
460 " 'arguments': { 'device': 'drive0', "
461 " 'size': %d } }", n_size);
462
463 qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
464
465 capacity = qvirtio_config_readq(&dev->vdev, 0);
466 g_assert_cmpint(capacity, ==, n_size / 512);
467
468 /* Write request */
469 req.type = VIRTIO_BLK_T_OUT;
470 req.ioprio = 1;
471 req.sector = 0;
472 req.data = g_malloc0(512);
473 strcpy(req.data, "TEST");
474
475 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
476
477 g_free(req.data);
478
479 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
480 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
481 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
482 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
483
484 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
485 QVIRTIO_BLK_TIMEOUT_US);
486
487 status = readb(req_addr + 528);
488 g_assert_cmpint(status, ==, 0);
489
490 guest_free(qs->alloc, req_addr);
491
492 /* Read request */
493 req.type = VIRTIO_BLK_T_IN;
494 req.ioprio = 1;
495 req.sector = 0;
496 req.data = g_malloc0(512);
497
498 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &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, true, true);
504 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
505
506 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
507
508
509 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
510 QVIRTIO_BLK_TIMEOUT_US);
511
512 status = readb(req_addr + 528);
513 g_assert_cmpint(status, ==, 0);
514
515 data = g_malloc0(512);
516 memread(req_addr + 16, data, 512);
517 g_assert_cmpstr(data, ==, "TEST");
518 g_free(data);
519
520 guest_free(qs->alloc, req_addr);
521
522 /* End test */
523 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
524 qpci_msix_disable(dev->pdev);
525 qvirtio_pci_device_disable(dev);
526 qvirtio_pci_device_free(dev);
527 qtest_shutdown(qs);
528 }
529
530 static void pci_idx(void)
531 {
532 QVirtioPCIDevice *dev;
533 QOSState *qs;
534 QVirtQueuePCI *vqpci;
535 QVirtioBlkReq req;
536 uint64_t req_addr;
537 uint64_t capacity;
538 uint32_t features;
539 uint32_t free_head;
540 uint32_t write_head;
541 uint32_t desc_idx;
542 uint8_t status;
543 char *data;
544
545 qs = pci_test_start();
546
547 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
548 qpci_msix_enable(dev->pdev);
549
550 qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
551
552 capacity = qvirtio_config_readq(&dev->vdev, 0);
553 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
554
555 features = qvirtio_get_features(&dev->vdev);
556 features = features & ~(QVIRTIO_F_BAD_FEATURE |
557 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
558 (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
559 (1u << VIRTIO_BLK_F_SCSI));
560 qvirtio_set_features(&dev->vdev, features);
561
562 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
563 qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
564
565 qvirtio_set_driver_ok(&dev->vdev);
566
567 /* Write request */
568 req.type = VIRTIO_BLK_T_OUT;
569 req.ioprio = 1;
570 req.sector = 0;
571 req.data = g_malloc0(512);
572 strcpy(req.data, "TEST");
573
574 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
575
576 g_free(req.data);
577
578 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
579 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
580 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
581 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
582
583 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head,
584 QVIRTIO_BLK_TIMEOUT_US);
585
586 /* Write request */
587 req.type = VIRTIO_BLK_T_OUT;
588 req.ioprio = 1;
589 req.sector = 1;
590 req.data = g_malloc0(512);
591 strcpy(req.data, "TEST");
592
593 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
594
595 g_free(req.data);
596
597 /* Notify after processing the third request */
598 qvirtqueue_set_used_event(&vqpci->vq, 2);
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);
603 write_head = free_head;
604
605 /* No notification expected */
606 status = qvirtio_wait_status_byte_no_isr(&dev->vdev,
607 &vqpci->vq, req_addr + 528,
608 QVIRTIO_BLK_TIMEOUT_US);
609 g_assert_cmpint(status, ==, 0);
610
611 guest_free(qs->alloc, req_addr);
612
613 /* Read request */
614 req.type = VIRTIO_BLK_T_IN;
615 req.ioprio = 1;
616 req.sector = 1;
617 req.data = g_malloc0(512);
618
619 req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
620
621 g_free(req.data);
622
623 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
624 qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
625 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
626
627 qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
628
629 /* We get just one notification for both requests */
630 qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head,
631 QVIRTIO_BLK_TIMEOUT_US);
632 g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx));
633 g_assert_cmpint(desc_idx, ==, free_head);
634
635 status = readb(req_addr + 528);
636 g_assert_cmpint(status, ==, 0);
637
638 data = g_malloc0(512);
639 memread(req_addr + 16, data, 512);
640 g_assert_cmpstr(data, ==, "TEST");
641 g_free(data);
642
643 guest_free(qs->alloc, req_addr);
644
645 /* End test */
646 qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
647 qpci_msix_disable(dev->pdev);
648 qvirtio_pci_device_disable(dev);
649 qvirtio_pci_device_free(dev);
650 qtest_shutdown(qs);
651 }
652
653 static void pci_hotplug(void)
654 {
655 QVirtioPCIDevice *dev;
656 QOSState *qs;
657 const char *arch = qtest_get_arch();
658
659 qs = pci_test_start();
660
661 /* plug secondary disk */
662 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP,
663 "'drive': 'drive1'");
664
665 dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT_HP);
666 g_assert(dev);
667 qvirtio_pci_device_disable(dev);
668 qvirtio_pci_device_free(dev);
669
670 /* unplug secondary disk */
671 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
672 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
673 }
674 qtest_shutdown(qs);
675 }
676
677 /*
678 * Check that setting the vring addr on a non-existent virtqueue does
679 * not crash.
680 */
681 static void test_nonexistent_virtqueue(void)
682 {
683 QPCIBar bar0;
684 QOSState *qs;
685 QPCIDevice *dev;
686
687 qs = pci_test_start();
688 dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4, 0));
689 g_assert(dev != NULL);
690
691 qpci_device_enable(dev);
692 bar0 = qpci_iomap(dev, 0, NULL);
693
694 qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2);
695 qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1);
696
697 g_free(dev);
698 qtest_shutdown(qs);
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);
723
724 qmp_discard_response("{ 'execute': 'block_resize', "
725 " 'arguments': { 'device': 'drive0', "
726 " 'size': %d } }", n_size);
727
728 qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US);
729
730 capacity = qvirtio_config_readq(&dev->vdev, 0);
731 g_assert_cmpint(capacity, ==, n_size / 512);
732
733 /* End test */
734 qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
735 g_free(dev);
736 generic_alloc_uninit(alloc);
737 test_end();
738 }
739
740 int main(int argc, char **argv)
741 {
742 const char *arch = qtest_get_arch();
743
744 g_test_init(&argc, &argv, NULL);
745
746 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0 ||
747 strcmp(arch, "ppc64") == 0) {
748 qtest_add_func("/virtio/blk/pci/basic", pci_basic);
749 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
750 qtest_add_func("/virtio/blk/pci/config", pci_config);
751 qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue);
752 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
753 qtest_add_func("/virtio/blk/pci/msix", pci_msix);
754 qtest_add_func("/virtio/blk/pci/idx", pci_idx);
755 }
756 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
757 } else if (strcmp(arch, "arm") == 0) {
758 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
759 }
760
761 return g_test_run();
762 }