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