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=null-co://,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    global_qtest = qs->qts;
  81    unlink(tmp_path);
  82    g_free(tmp_path);
  83    return qs;
  84}
  85
  86static void arm_test_start(void)
  87{
  88    char *tmp_path;
  89
  90    tmp_path = drive_create();
  91
  92    global_qtest = qtest_startf("-machine virt "
  93                                "-drive if=none,id=drive0,file=%s,format=raw "
  94                                "-device virtio-blk-device,drive=drive0",
  95                                tmp_path);
  96    unlink(tmp_path);
  97    g_free(tmp_path);
  98}
  99
 100static void test_end(void)
 101{
 102    qtest_end();
 103}
 104
 105static QVirtioPCIDevice *virtio_blk_pci_init(QPCIBus *bus, int slot)
 106{
 107    QVirtioPCIDevice *dev;
 108
 109    dev = qvirtio_pci_device_find_slot(bus, VIRTIO_ID_BLOCK, slot);
 110    g_assert(dev != NULL);
 111    g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
 112    g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN));
 113
 114    qvirtio_pci_device_enable(dev);
 115    qvirtio_reset(&dev->vdev);
 116    qvirtio_set_acknowledge(&dev->vdev);
 117    qvirtio_set_driver(&dev->vdev);
 118
 119    return dev;
 120}
 121
 122static inline void virtio_blk_fix_request(QVirtioDevice *d, QVirtioBlkReq *req)
 123{
 124#ifdef HOST_WORDS_BIGENDIAN
 125    const bool host_is_big_endian = true;
 126#else
 127    const bool host_is_big_endian = false;
 128#endif
 129
 130    if (qvirtio_is_big_endian(d) != host_is_big_endian) {
 131        req->type = bswap32(req->type);
 132        req->ioprio = bswap32(req->ioprio);
 133        req->sector = bswap64(req->sector);
 134    }
 135}
 136
 137static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d,
 138                                   QVirtioBlkReq *req, uint64_t data_size)
 139{
 140    uint64_t addr;
 141    uint8_t status = 0xFF;
 142
 143    g_assert_cmpuint(data_size % 512, ==, 0);
 144    addr = guest_alloc(alloc, sizeof(*req) + data_size);
 145
 146    virtio_blk_fix_request(d, req);
 147
 148    memwrite(addr, req, 16);
 149    memwrite(addr + 16, req->data, data_size);
 150    memwrite(addr + 16 + data_size, &status, sizeof(status));
 151
 152    return addr;
 153}
 154
 155static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
 156                       QVirtQueue *vq)
 157{
 158    QVirtioBlkReq req;
 159    uint64_t req_addr;
 160    uint64_t capacity;
 161    uint32_t features;
 162    uint32_t free_head;
 163    uint8_t status;
 164    char *data;
 165
 166    capacity = qvirtio_config_readq(dev, 0);
 167
 168    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 169
 170    features = qvirtio_get_features(dev);
 171    features = features & ~(QVIRTIO_F_BAD_FEATURE |
 172                    (1u << VIRTIO_RING_F_INDIRECT_DESC) |
 173                    (1u << VIRTIO_RING_F_EVENT_IDX) |
 174                    (1u << VIRTIO_BLK_F_SCSI));
 175    qvirtio_set_features(dev, features);
 176
 177    qvirtio_set_driver_ok(dev);
 178
 179    /* Write and read with 3 descriptor layout */
 180    /* Write request */
 181    req.type = VIRTIO_BLK_T_OUT;
 182    req.ioprio = 1;
 183    req.sector = 0;
 184    req.data = g_malloc0(512);
 185    strcpy(req.data, "TEST");
 186
 187    req_addr = virtio_blk_request(alloc, dev, &req, 512);
 188
 189    g_free(req.data);
 190
 191    free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
 192    qvirtqueue_add(vq, req_addr + 16, 512, false, true);
 193    qvirtqueue_add(vq, req_addr + 528, 1, true, false);
 194
 195    qvirtqueue_kick(dev, vq, free_head);
 196
 197    qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
 198    status = readb(req_addr + 528);
 199    g_assert_cmpint(status, ==, 0);
 200
 201    guest_free(alloc, req_addr);
 202
 203    /* Read request */
 204    req.type = VIRTIO_BLK_T_IN;
 205    req.ioprio = 1;
 206    req.sector = 0;
 207    req.data = g_malloc0(512);
 208
 209    req_addr = virtio_blk_request(alloc, dev, &req, 512);
 210
 211    g_free(req.data);
 212
 213    free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
 214    qvirtqueue_add(vq, req_addr + 16, 512, true, true);
 215    qvirtqueue_add(vq, req_addr + 528, 1, true, false);
 216
 217    qvirtqueue_kick(dev, vq, free_head);
 218
 219    qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
 220    status = readb(req_addr + 528);
 221    g_assert_cmpint(status, ==, 0);
 222
 223    data = g_malloc0(512);
 224    memread(req_addr + 16, data, 512);
 225    g_assert_cmpstr(data, ==, "TEST");
 226    g_free(data);
 227
 228    guest_free(alloc, req_addr);
 229
 230    if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
 231        /* Write and read with 2 descriptor layout */
 232        /* Write request */
 233        req.type = VIRTIO_BLK_T_OUT;
 234        req.ioprio = 1;
 235        req.sector = 1;
 236        req.data = g_malloc0(512);
 237        strcpy(req.data, "TEST");
 238
 239        req_addr = virtio_blk_request(alloc, dev, &req, 512);
 240
 241        g_free(req.data);
 242
 243        free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
 244        qvirtqueue_add(vq, req_addr + 528, 1, true, false);
 245        qvirtqueue_kick(dev, vq, free_head);
 246
 247        qvirtio_wait_used_elem(dev, vq, free_head, NULL,
 248                               QVIRTIO_BLK_TIMEOUT_US);
 249        status = readb(req_addr + 528);
 250        g_assert_cmpint(status, ==, 0);
 251
 252        guest_free(alloc, req_addr);
 253
 254        /* Read request */
 255        req.type = VIRTIO_BLK_T_IN;
 256        req.ioprio = 1;
 257        req.sector = 1;
 258        req.data = g_malloc0(512);
 259
 260        req_addr = virtio_blk_request(alloc, dev, &req, 512);
 261
 262        g_free(req.data);
 263
 264        free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
 265        qvirtqueue_add(vq, req_addr + 16, 513, true, false);
 266
 267        qvirtqueue_kick(dev, vq, free_head);
 268
 269        qvirtio_wait_used_elem(dev, vq, free_head, NULL,
 270                               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    qvirtio_pci_device_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_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
 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_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
 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    qvirtio_pci_device_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_discard_response("{ 'execute': 'block_resize', "
 413                         " 'arguments': { 'device': 'drive0', "
 414                         " 'size': %d } }", n_size);
 415    qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
 416
 417    capacity = qvirtio_config_readq(&dev->vdev, 0);
 418    g_assert_cmpint(capacity, ==, n_size / 512);
 419
 420    qvirtio_pci_device_disable(dev);
 421    qvirtio_pci_device_free(dev);
 422
 423    qtest_shutdown(qs);
 424}
 425
 426static void pci_msix(void)
 427{
 428    QVirtioPCIDevice *dev;
 429    QOSState *qs;
 430    QVirtQueuePCI *vqpci;
 431    QVirtioBlkReq req;
 432    int n_size = TEST_IMAGE_SIZE / 2;
 433    uint64_t req_addr;
 434    uint64_t capacity;
 435    uint32_t features;
 436    uint32_t free_head;
 437    uint8_t status;
 438    char *data;
 439
 440    qs = pci_test_start();
 441
 442    dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
 443    qpci_msix_enable(dev->pdev);
 444
 445    qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
 446
 447    capacity = qvirtio_config_readq(&dev->vdev, 0);
 448    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 449
 450    features = qvirtio_get_features(&dev->vdev);
 451    features = features & ~(QVIRTIO_F_BAD_FEATURE |
 452                            (1u << VIRTIO_RING_F_INDIRECT_DESC) |
 453                            (1u << VIRTIO_RING_F_EVENT_IDX) |
 454                            (1u << VIRTIO_BLK_F_SCSI));
 455    qvirtio_set_features(&dev->vdev, features);
 456
 457    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
 458    qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
 459
 460    qvirtio_set_driver_ok(&dev->vdev);
 461
 462    qmp_discard_response("{ 'execute': 'block_resize', "
 463                         " 'arguments': { 'device': 'drive0', "
 464                         " 'size': %d } }", n_size);
 465
 466    qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US);
 467
 468    capacity = qvirtio_config_readq(&dev->vdev, 0);
 469    g_assert_cmpint(capacity, ==, n_size / 512);
 470
 471    /* Write request */
 472    req.type = VIRTIO_BLK_T_OUT;
 473    req.ioprio = 1;
 474    req.sector = 0;
 475    req.data = g_malloc0(512);
 476    strcpy(req.data, "TEST");
 477
 478    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
 479
 480    g_free(req.data);
 481
 482    free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
 483    qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
 484    qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
 485    qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
 486
 487    qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
 488                           QVIRTIO_BLK_TIMEOUT_US);
 489
 490    status = readb(req_addr + 528);
 491    g_assert_cmpint(status, ==, 0);
 492
 493    guest_free(qs->alloc, req_addr);
 494
 495    /* Read request */
 496    req.type = VIRTIO_BLK_T_IN;
 497    req.ioprio = 1;
 498    req.sector = 0;
 499    req.data = g_malloc0(512);
 500
 501    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
 502
 503    g_free(req.data);
 504
 505    free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
 506    qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
 507    qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
 508
 509    qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
 510
 511
 512    qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
 513                           QVIRTIO_BLK_TIMEOUT_US);
 514
 515    status = readb(req_addr + 528);
 516    g_assert_cmpint(status, ==, 0);
 517
 518    data = g_malloc0(512);
 519    memread(req_addr + 16, data, 512);
 520    g_assert_cmpstr(data, ==, "TEST");
 521    g_free(data);
 522
 523    guest_free(qs->alloc, req_addr);
 524
 525    /* End test */
 526    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
 527    qpci_msix_disable(dev->pdev);
 528    qvirtio_pci_device_disable(dev);
 529    qvirtio_pci_device_free(dev);
 530    qtest_shutdown(qs);
 531}
 532
 533static void pci_idx(void)
 534{
 535    QVirtioPCIDevice *dev;
 536    QOSState *qs;
 537    QVirtQueuePCI *vqpci;
 538    QVirtioBlkReq req;
 539    uint64_t req_addr;
 540    uint64_t capacity;
 541    uint32_t features;
 542    uint32_t free_head;
 543    uint32_t write_head;
 544    uint32_t desc_idx;
 545    uint8_t status;
 546    char *data;
 547
 548    qs = pci_test_start();
 549
 550    dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT);
 551    qpci_msix_enable(dev->pdev);
 552
 553    qvirtio_pci_set_msix_configuration_vector(dev, qs->alloc, 0);
 554
 555    capacity = qvirtio_config_readq(&dev->vdev, 0);
 556    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);
 557
 558    features = qvirtio_get_features(&dev->vdev);
 559    features = features & ~(QVIRTIO_F_BAD_FEATURE |
 560                            (1u << VIRTIO_RING_F_INDIRECT_DESC) |
 561                            (1u << VIRTIO_F_NOTIFY_ON_EMPTY) |
 562                            (1u << VIRTIO_BLK_F_SCSI));
 563    qvirtio_set_features(&dev->vdev, features);
 564
 565    vqpci = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev, qs->alloc, 0);
 566    qvirtqueue_pci_msix_setup(dev, vqpci, qs->alloc, 1);
 567
 568    qvirtio_set_driver_ok(&dev->vdev);
 569
 570    /* Write request */
 571    req.type = VIRTIO_BLK_T_OUT;
 572    req.ioprio = 1;
 573    req.sector = 0;
 574    req.data = g_malloc0(512);
 575    strcpy(req.data, "TEST");
 576
 577    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
 578
 579    g_free(req.data);
 580
 581    free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
 582    qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
 583    qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
 584    qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
 585
 586    qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, free_head, NULL,
 587                           QVIRTIO_BLK_TIMEOUT_US);
 588
 589    /* Write request */
 590    req.type = VIRTIO_BLK_T_OUT;
 591    req.ioprio = 1;
 592    req.sector = 1;
 593    req.data = g_malloc0(512);
 594    strcpy(req.data, "TEST");
 595
 596    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
 597
 598    g_free(req.data);
 599
 600    /* Notify after processing the third request */
 601    qvirtqueue_set_used_event(&vqpci->vq, 2);
 602    free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
 603    qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, false, true);
 604    qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
 605    qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
 606    write_head = free_head;
 607
 608    /* No notification expected */
 609    status = qvirtio_wait_status_byte_no_isr(&dev->vdev,
 610                                             &vqpci->vq, req_addr + 528,
 611                                             QVIRTIO_BLK_TIMEOUT_US);
 612    g_assert_cmpint(status, ==, 0);
 613
 614    guest_free(qs->alloc, req_addr);
 615
 616    /* Read request */
 617    req.type = VIRTIO_BLK_T_IN;
 618    req.ioprio = 1;
 619    req.sector = 1;
 620    req.data = g_malloc0(512);
 621
 622    req_addr = virtio_blk_request(qs->alloc, &dev->vdev, &req, 512);
 623
 624    g_free(req.data);
 625
 626    free_head = qvirtqueue_add(&vqpci->vq, req_addr, 16, false, true);
 627    qvirtqueue_add(&vqpci->vq, req_addr + 16, 512, true, true);
 628    qvirtqueue_add(&vqpci->vq, req_addr + 528, 1, true, false);
 629
 630    qvirtqueue_kick(&dev->vdev, &vqpci->vq, free_head);
 631
 632    /* We get just one notification for both requests */
 633    qvirtio_wait_used_elem(&dev->vdev, &vqpci->vq, write_head, NULL,
 634                           QVIRTIO_BLK_TIMEOUT_US);
 635    g_assert(qvirtqueue_get_buf(&vqpci->vq, &desc_idx, NULL));
 636    g_assert_cmpint(desc_idx, ==, free_head);
 637
 638    status = readb(req_addr + 528);
 639    g_assert_cmpint(status, ==, 0);
 640
 641    data = g_malloc0(512);
 642    memread(req_addr + 16, data, 512);
 643    g_assert_cmpstr(data, ==, "TEST");
 644    g_free(data);
 645
 646    guest_free(qs->alloc, req_addr);
 647
 648    /* End test */
 649    qvirtqueue_cleanup(dev->vdev.bus, &vqpci->vq, qs->alloc);
 650    qpci_msix_disable(dev->pdev);
 651    qvirtio_pci_device_disable(dev);
 652    qvirtio_pci_device_free(dev);
 653    qtest_shutdown(qs);
 654}
 655
 656static void pci_hotplug(void)
 657{
 658    QVirtioPCIDevice *dev;
 659    QOSState *qs;
 660    const char *arch = qtest_get_arch();
 661
 662    qs = pci_test_start();
 663
 664    /* plug secondary disk */
 665    qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP,
 666                          "'drive': 'drive1'");
 667
 668    dev = virtio_blk_pci_init(qs->pcibus, PCI_SLOT_HP);
 669    g_assert(dev);
 670    qvirtio_pci_device_disable(dev);
 671    qvirtio_pci_device_free(dev);
 672
 673    /* unplug secondary disk */
 674    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
 675        qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP);
 676    }
 677    qtest_shutdown(qs);
 678}
 679
 680/*
 681 * Check that setting the vring addr on a non-existent virtqueue does
 682 * not crash.
 683 */
 684static void test_nonexistent_virtqueue(void)
 685{
 686    QPCIBar bar0;
 687    QOSState *qs;
 688    QPCIDevice *dev;
 689
 690    qs = pci_test_start();
 691    dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4, 0));
 692    g_assert(dev != NULL);
 693
 694    qpci_device_enable(dev);
 695    bar0 = qpci_iomap(dev, 0, NULL);
 696
 697    qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2);
 698    qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1);
 699
 700    g_free(dev);
 701    qtest_shutdown(qs);
 702}
 703
 704static void mmio_basic(void)
 705{
 706    QVirtioMMIODevice *dev;
 707    QVirtQueue *vq;
 708    QGuestAllocator *alloc;
 709    int n_size = TEST_IMAGE_SIZE / 2;
 710    uint64_t capacity;
 711
 712    arm_test_start();
 713
 714    dev = qvirtio_mmio_init_device(MMIO_DEV_BASE_ADDR, MMIO_PAGE_SIZE);
 715    g_assert(dev != NULL);
 716    g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_BLOCK);
 717
 718    qvirtio_reset(&dev->vdev);
 719    qvirtio_set_acknowledge(&dev->vdev);
 720    qvirtio_set_driver(&dev->vdev);
 721
 722    alloc = generic_alloc_init(MMIO_RAM_ADDR, MMIO_RAM_SIZE, MMIO_PAGE_SIZE);
 723    vq = qvirtqueue_setup(&dev->vdev, alloc, 0);
 724
 725    test_basic(&dev->vdev, alloc, vq);
 726
 727    qmp_discard_response("{ 'execute': 'block_resize', "
 728                         " 'arguments': { 'device': 'drive0', "
 729                         " 'size': %d } }", n_size);
 730
 731    qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US);
 732
 733    capacity = qvirtio_config_readq(&dev->vdev, 0);
 734    g_assert_cmpint(capacity, ==, n_size / 512);
 735
 736    /* End test */
 737    qvirtqueue_cleanup(dev->vdev.bus, vq, alloc);
 738    g_free(dev);
 739    generic_alloc_uninit(alloc);
 740    test_end();
 741}
 742
 743int main(int argc, char **argv)
 744{
 745    const char *arch = qtest_get_arch();
 746
 747    g_test_init(&argc, &argv, NULL);
 748
 749    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0 ||
 750        strcmp(arch, "ppc64") == 0) {
 751        qtest_add_func("/virtio/blk/pci/basic", pci_basic);
 752        qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
 753        qtest_add_func("/virtio/blk/pci/config", pci_config);
 754        qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue);
 755        if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
 756            qtest_add_func("/virtio/blk/pci/msix", pci_msix);
 757            qtest_add_func("/virtio/blk/pci/idx", pci_idx);
 758        }
 759        qtest_add_func("/virtio/blk/pci/hotplug", pci_hotplug);
 760    } else if (strcmp(arch, "arm") == 0) {
 761        qtest_add_func("/virtio/blk/mmio/basic", mmio_basic);
 762    }
 763
 764    return g_test_run();
 765}
 766