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