OSDN Git Service

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