qemu/tests/virtio-blk-test.c
<<
>>
Prefs
   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
  50typedef struct QVirtioBlkReq {
  51    uint32_t type;
  52    uint32_t ioprio;
  53    uint64_t sector;
  54    char *data;
  55    uint8_t status;
  56} QVirtioBlkReq;
  57
  58static 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
  83static void test_end(void)
  84{
  85    qtest_end();
  86}
  87
  88static 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
 105static 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
 120static 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
 138static 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
 283static 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
 382static 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
 414static 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
 524static 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
 645static 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
 666int 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}
 683