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