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