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