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