]> git.proxmox.com Git - mirror_qemu.git/blob - tests/virtio-blk-test.c
libqos: Add virtio MMIO support
[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 <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 2 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, 528, false, true);
207 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
208 qvirtqueue_kick(bus, dev, vq, free_head);
209
210 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
211 status = readb(req_addr + 528);
212 g_assert_cmpint(status, ==, 0);
213
214 guest_free(alloc, req_addr);
215
216 /* Read request */
217 req.type = QVIRTIO_BLK_T_IN;
218 req.ioprio = 1;
219 req.sector = 0;
220 req.data = g_malloc0(512);
221
222 req_addr = virtio_blk_request(alloc, &req, 512);
223
224 g_free(req.data);
225
226 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
227 qvirtqueue_add(vq, req_addr + 16, 513, true, false);
228
229 qvirtqueue_kick(bus, dev, vq, free_head);
230
231 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
232 status = readb(req_addr + 528);
233 g_assert_cmpint(status, ==, 0);
234
235 data = g_malloc0(512);
236 memread(req_addr + 16, data, 512);
237 g_assert_cmpstr(data, ==, "TEST");
238 g_free(data);
239
240 guest_free(alloc, req_addr);
241
242 /* Write and read with 3 descriptor layout */
243 /* Write request */
244 req.type = QVIRTIO_BLK_T_OUT;
245 req.ioprio = 1;
246 req.sector = 1;
247 req.data = g_malloc0(512);
248 strcpy(req.data, "TEST");
249
250 req_addr = virtio_blk_request(alloc, &req, 512);
251
252 g_free(req.data);
253
254 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
255 qvirtqueue_add(vq, req_addr + 16, 512, false, true);
256 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
257
258 qvirtqueue_kick(bus, dev, vq, free_head);
259
260 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
261 status = readb(req_addr + 528);
262 g_assert_cmpint(status, ==, 0);
263
264 guest_free(alloc, req_addr);
265
266 /* Read request */
267 req.type = QVIRTIO_BLK_T_IN;
268 req.ioprio = 1;
269 req.sector = 1;
270 req.data = g_malloc0(512);
271
272 req_addr = virtio_blk_request(alloc, &req, 512);
273
274 g_free(req.data);
275
276 free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
277 qvirtqueue_add(vq, req_addr + 16, 512, true, true);
278 qvirtqueue_add(vq, req_addr + 528, 1, true, false);
279
280 qvirtqueue_kick(bus, dev, vq, free_head);
281
282 qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
283 status = readb(req_addr + 528);
284 g_assert_cmpint(status, ==, 0);
285
286 data = g_malloc0(512);
287 memread(req_addr + 16, data, 512);
288 g_assert_cmpstr(data, ==, "TEST");
289 g_free(data);
290
291 guest_free(alloc, req_addr);
292 }
293
294 static void pci_basic(void)
295 {
296 QVirtioPCIDevice *dev;
297 QPCIBus *bus;
298 QVirtQueuePCI *vqpci;
299 QGuestAllocator *alloc;
300 void *addr;
301
302 bus = pci_test_start();
303 dev = virtio_blk_pci_init(bus, PCI_SLOT);
304
305 alloc = pc_alloc_init();
306 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
307 alloc, 0);
308
309 /* MSI-X is not enabled */
310 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
311
312 test_basic(&qvirtio_pci, &dev->vdev, alloc, &vqpci->vq,
313 (uint64_t)(uintptr_t)addr);
314
315 /* End test */
316 guest_free(alloc, vqpci->vq.desc);
317 pc_alloc_uninit(alloc);
318 qvirtio_pci_device_disable(dev);
319 g_free(dev);
320 qpci_free_pc(bus);
321 test_end();
322 }
323
324 static void pci_indirect(void)
325 {
326 QVirtioPCIDevice *dev;
327 QPCIBus *bus;
328 QVirtQueuePCI *vqpci;
329 QGuestAllocator *alloc;
330 QVirtioBlkReq req;
331 QVRingIndirectDesc *indirect;
332 void *addr;
333 uint64_t req_addr;
334 uint64_t capacity;
335 uint32_t features;
336 uint32_t free_head;
337 uint8_t status;
338 char *data;
339
340 bus = pci_test_start();
341
342 dev = virtio_blk_pci_init(bus, PCI_SLOT);
343
344 /* MSI-X is not enabled */
345 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
346
347 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
348 (uint64_t)(uintptr_t)addr);
349 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
350
351 features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
352 g_assert_cmphex(features & QVIRTIO_F_RING_INDIRECT_DESC, !=, 0);
353 features = features & ~(QVIRTIO_F_BAD_FEATURE | QVIRTIO_F_RING_EVENT_IDX |
354 QVIRTIO_BLK_F_SCSI);
355 qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
356
357 alloc = pc_alloc_init();
358 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
359 alloc, 0);
360 qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
361
362 /* Write request */
363 req.type = QVIRTIO_BLK_T_OUT;
364 req.ioprio = 1;
365 req.sector = 0;
366 req.data = g_malloc0(512);
367 strcpy(req.data, "TEST");
368
369 req_addr = virtio_blk_request(alloc, &req, 512);
370
371 g_free(req.data);
372
373 indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);
374 qvring_indirect_desc_add(indirect, req_addr, 528, false);
375 qvring_indirect_desc_add(indirect, req_addr + 528, 1, true);
376 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
377 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
378
379 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
380 QVIRTIO_BLK_TIMEOUT_US);
381 status = readb(req_addr + 528);
382 g_assert_cmpint(status, ==, 0);
383
384 g_free(indirect);
385 guest_free(alloc, req_addr);
386
387 /* Read request */
388 req.type = QVIRTIO_BLK_T_IN;
389 req.ioprio = 1;
390 req.sector = 0;
391 req.data = g_malloc0(512);
392 strcpy(req.data, "TEST");
393
394 req_addr = virtio_blk_request(alloc, &req, 512);
395
396 g_free(req.data);
397
398 indirect = qvring_indirect_desc_setup(&dev->vdev, alloc, 2);
399 qvring_indirect_desc_add(indirect, req_addr, 16, false);
400 qvring_indirect_desc_add(indirect, req_addr + 16, 513, true);
401 free_head = qvirtqueue_add_indirect(&vqpci->vq, indirect);
402 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
403
404 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
405 QVIRTIO_BLK_TIMEOUT_US);
406 status = readb(req_addr + 528);
407 g_assert_cmpint(status, ==, 0);
408
409 data = g_malloc0(512);
410 memread(req_addr + 16, data, 512);
411 g_assert_cmpstr(data, ==, "TEST");
412 g_free(data);
413
414 g_free(indirect);
415 guest_free(alloc, req_addr);
416
417 /* End test */
418 guest_free(alloc, vqpci->vq.desc);
419 pc_alloc_uninit(alloc);
420 qvirtio_pci_device_disable(dev);
421 g_free(dev);
422 qpci_free_pc(bus);
423 test_end();
424 }
425
426 static void pci_config(void)
427 {
428 QVirtioPCIDevice *dev;
429 QPCIBus *bus;
430 int n_size = TEST_IMAGE_SIZE / 2;
431 void *addr;
432 uint64_t capacity;
433
434 bus = pci_test_start();
435
436 dev = virtio_blk_pci_init(bus, PCI_SLOT);
437
438 /* MSI-X is not enabled */
439 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
440
441 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
442 (uint64_t)(uintptr_t)addr);
443 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
444
445 qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
446
447 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
448 " 'size': %d } }", n_size);
449 qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
450
451 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
452 (uint64_t)(uintptr_t)addr);
453 g_assert_cmpint(capacity, ==, n_size / 512);
454
455 qvirtio_pci_device_disable(dev);
456 g_free(dev);
457 qpci_free_pc(bus);
458 test_end();
459 }
460
461 static void pci_msix(void)
462 {
463 QVirtioPCIDevice *dev;
464 QPCIBus *bus;
465 QVirtQueuePCI *vqpci;
466 QGuestAllocator *alloc;
467 QVirtioBlkReq req;
468 int n_size = TEST_IMAGE_SIZE / 2;
469 void *addr;
470 uint64_t req_addr;
471 uint64_t capacity;
472 uint32_t features;
473 uint32_t free_head;
474 uint8_t status;
475 char *data;
476
477 bus = pci_test_start();
478 alloc = pc_alloc_init();
479
480 dev = virtio_blk_pci_init(bus, PCI_SLOT);
481 qpci_msix_enable(dev->pdev);
482
483 qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
484
485 /* MSI-X is enabled */
486 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX;
487
488 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
489 (uint64_t)(uintptr_t)addr);
490 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
491
492 features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
493 features = features & ~(QVIRTIO_F_BAD_FEATURE |
494 QVIRTIO_F_RING_INDIRECT_DESC |
495 QVIRTIO_F_RING_EVENT_IDX | QVIRTIO_BLK_F_SCSI);
496 qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
497
498 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
499 alloc, 0);
500 qvirtqueue_pci_msix_setup(dev, vqpci, alloc, 1);
501
502 qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
503
504 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
505 " 'size': %d } }", n_size);
506
507 qvirtio_wait_config_isr(&qvirtio_pci, &dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
508
509 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
510 (uint64_t)(uintptr_t)addr);
511 g_assert_cmpint(capacity, ==, n_size / 512);
512
513 /* Write request */
514 req.type = QVIRTIO_BLK_T_OUT;
515 req.ioprio = 1;
516 req.sector = 0;
517 req.data = g_malloc0(512);
518 strcpy(req.data, "TEST");
519
520 req_addr = virtio_blk_request(alloc, &req, 512);
521
522 g_free(req.data);
523
524 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 528, false, true);
525 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
526 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
527
528 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
529 QVIRTIO_BLK_TIMEOUT_US);
530
531 status = readb(req_addr + 528);
532 g_assert_cmpint(status, ==, 0);
533
534 guest_free(alloc, req_addr);
535
536 /* Read request */
537 req.type = QVIRTIO_BLK_T_IN;
538 req.ioprio = 1;
539 req.sector = 0;
540 req.data = g_malloc0(512);
541
542 req_addr = virtio_blk_request(alloc, &req, 512);
543
544 g_free(req.data);
545
546 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
547 qvirtqueue_add(&vqpci->vq, req_addr + 16, 513, true, false);
548
549 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
550
551
552 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
553 QVIRTIO_BLK_TIMEOUT_US);
554
555 status = readb(req_addr + 528);
556 g_assert_cmpint(status, ==, 0);
557
558 data = g_malloc0(512);
559 memread(req_addr + 16, data, 512);
560 g_assert_cmpstr(data, ==, "TEST");
561 g_free(data);
562
563 guest_free(alloc, req_addr);
564
565 /* End test */
566 guest_free(alloc, vqpci->vq.desc);
567 pc_alloc_uninit(alloc);
568 qpci_msix_disable(dev->pdev);
569 qvirtio_pci_device_disable(dev);
570 g_free(dev);
571 qpci_free_pc(bus);
572 test_end();
573 }
574
575 static void pci_idx(void)
576 {
577 QVirtioPCIDevice *dev;
578 QPCIBus *bus;
579 QVirtQueuePCI *vqpci;
580 QGuestAllocator *alloc;
581 QVirtioBlkReq req;
582 void *addr;
583 uint64_t req_addr;
584 uint64_t capacity;
585 uint32_t features;
586 uint32_t free_head;
587 uint8_t status;
588 char *data;
589
590 bus = pci_test_start();
591 alloc = pc_alloc_init();
592
593 dev = virtio_blk_pci_init(bus, PCI_SLOT);
594 qpci_msix_enable(dev->pdev);
595
596 qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0);
597
598 /* MSI-X is enabled */
599 addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_MSIX;
600
601 capacity = qvirtio_config_readq(&qvirtio_pci, &dev->vdev,
602 (uint64_t)(uintptr_t)addr);
603 g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
604
605 features = qvirtio_get_features(&qvirtio_pci, &dev->vdev);
606 features = features & ~(QVIRTIO_F_BAD_FEATURE |
607 QVIRTIO_F_RING_INDIRECT_DESC |
608 QVIRTIO_F_NOTIFY_ON_EMPTY | QVIRTIO_BLK_F_SCSI);
609 qvirtio_set_features(&qvirtio_pci, &dev->vdev, features);
610
611 vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
612 alloc, 0);
613 qvirtqueue_pci_msix_setup(dev, vqpci, alloc, 1);
614
615 qvirtio_set_driver_ok(&qvirtio_pci, &dev->vdev);
616
617 /* Write request */
618 req.type = QVIRTIO_BLK_T_OUT;
619 req.ioprio = 1;
620 req.sector = 0;
621 req.data = g_malloc0(512);
622 strcpy(req.data, "TEST");
623
624 req_addr = virtio_blk_request(alloc, &req, 512);
625
626 g_free(req.data);
627
628 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 528, false, true);
629 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
630 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
631
632 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
633 QVIRTIO_BLK_TIMEOUT_US);
634
635 /* Write request */
636 req.type = QVIRTIO_BLK_T_OUT;
637 req.ioprio = 1;
638 req.sector = 1;
639 req.data = g_malloc0(512);
640 strcpy(req.data, "TEST");
641
642 req_addr = virtio_blk_request(alloc, &req, 512);
643
644 g_free(req.data);
645
646 /* Notify after processing the third request */
647 qvirtqueue_set_used_event(&vqpci->vq, 2);
648 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 528, false, true);
649 qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
650 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
651
652 /* No notification expected */
653 status = qvirtio_wait_status_byte_no_isr(&qvirtio_pci, &dev->vdev,
654 &vqpci->vq, req_addr + 528,
655 QVIRTIO_BLK_TIMEOUT_US);
656 g_assert_cmpint(status, ==, 0);
657
658 guest_free(alloc, req_addr);
659
660 /* Read request */
661 req.type = QVIRTIO_BLK_T_IN;
662 req.ioprio = 1;
663 req.sector = 1;
664 req.data = g_malloc0(512);
665
666 req_addr = virtio_blk_request(alloc, &req, 512);
667
668 g_free(req.data);
669
670 free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
671 qvirtqueue_add(&vqpci->vq, req_addr + 16, 513, true, false);
672
673 qvirtqueue_kick(&qvirtio_pci, &dev->vdev, &vqpci->vq, free_head);
674
675
676 qvirtio_wait_queue_isr(&qvirtio_pci, &dev->vdev, &vqpci->vq,
677 QVIRTIO_BLK_TIMEOUT_US);
678
679 status = readb(req_addr + 528);
680 g_assert_cmpint(status, ==, 0);
681
682 data = g_malloc0(512);
683 memread(req_addr + 16, data, 512);
684 g_assert_cmpstr(data, ==, "TEST");
685 g_free(data);
686
687 guest_free(alloc, req_addr);
688
689 /* End test */
690 guest_free(alloc, vqpci->vq.desc);
691 pc_alloc_uninit(alloc);
692 qpci_msix_disable(dev->pdev);
693 qvirtio_pci_device_disable(dev);
694 g_free(dev);
695 qpci_free_pc(bus);
696 test_end();
697 }
698
699 static void pci_hotplug(void)
700 {
701 QPCIBus *bus;
702 QVirtioPCIDevice *dev;
703
704 bus = pci_test_start();
705
706 /* plug secondary disk */
707 qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP,
708 "'drive': 'drive1'");
709
710 dev = virtio_blk_pci_init(bus, PCI_SLOT_HP);
711 g_assert(dev);
712 qvirtio_pci_device_disable(dev);
713 g_free(dev);
714
715 /* unplug secondary disk */
716 qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
717 qpci_free_pc(bus);
718 test_end();
719 }
720
721 static void mmio_basic(void)
722 {
723 QVirtioMMIODevice *dev;
724 QVirtQueue *vq;
725 QGuestAllocator *alloc;
726 int n_size = TEST_IMAGE_SIZE / 2;
727 uint64_t capacity;
728
729 arm_test_start();
730
731 dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
732 g_assert(dev != NULL);
733 g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_BLK_DEVICE_ID);
734
735 qvirtio_reset(&qvirtio_mmio, &dev->vdev);
736 qvirtio_set_acknowledge(&qvirtio_mmio, &dev->vdev);
737 qvirtio_set_driver(&qvirtio_mmio, &dev->vdev);
738
739 alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
740 vq = qvirtqueue_setup(&qvirtio_mmio, &dev->vdev, alloc, 0);
741
742 test_basic(&qvirtio_mmio, &dev->vdev, alloc, vq,
743 QVIRTIO_MMIO_DEVICE_SPECIFIC);
744
745 qmp("{ 'execute': 'block_resize', 'arguments': { 'device': 'drive0', "
746 " 'size': %d } }", n_size);
747
748 qvirtio_wait_queue_isr(&qvirtio_mmio, &dev->vdev, vq,
749 QVIRTIO_BLK_TIMEOUT_US);
750
751 capacity = qvirtio_config_readq(&qvirtio_mmio, &dev->vdev,
752 QVIRTIO_MMIO_DEVICE_SPECIFIC);
753 g_assert_cmpint(capacity, ==, n_size / 512);
754
755 /* End test */
756 guest_free(alloc, vq->desc);
757 generic_alloc_uninit(alloc);
758 g_free(dev);
759 test_end();
760 }
761
762 int main(int argc, char **argv)
763 {
764 int ret;
765 const char *arch = qtest_get_arch();
766
767 g_test_init(&argc, &argv, NULL);
768
769 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
770 qtest_add_func("/virtio/blk/pci/basic", pci_basic);
771 qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
772 qtest_add_func("/virtio/blk/pci/config", pci_config);
773 qtest_add_func("/virtio/blk/pci/msix", pci_msix);
774 qtest_add_func("/virtio/blk/pci/idx", pci_idx);
775 qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
776 } else if (strcmp(arch, "arm") == 0) {
777 qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
778 }
779
780 ret = g_test_run();
781
782 return ret;
783 }