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