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