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