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