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