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