Пример #1
0
static void init_virtio_dev(TestServer *s, uint32_t features_mask)
{
    uint32_t features;
    int i;

    s->bus = qpci_init_pc(global_qtest, NULL);
    g_assert_nonnull(s->bus);

    s->dev = qvirtio_pci_device_find(s->bus, VIRTIO_ID_NET);
    g_assert_nonnull(s->dev);

    qvirtio_pci_device_enable(s->dev);
    qvirtio_reset(&s->dev->vdev);
    qvirtio_set_acknowledge(&s->dev->vdev);
    qvirtio_set_driver(&s->dev->vdev);

    s->alloc = pc_alloc_init(global_qtest);

    for (i = 0; i < s->queues * 2; i++) {
        s->vq[i] = qvirtqueue_setup(&s->dev->vdev, s->alloc, i);
    }

    features = qvirtio_get_features(&s->dev->vdev);
    features = features & features_mask;
    qvirtio_set_features(&s->dev->vdev, features);

    qvirtio_set_driver_ok(&s->dev->vdev);
}
Пример #2
0
static void driver_init(const QVirtioBus *bus, QVirtioDevice *dev)
{
    uint32_t features;

    features = qvirtio_get_features(bus, dev);
    features = features & ~(QVIRTIO_F_BAD_FEATURE |
                            QVIRTIO_F_RING_INDIRECT_DESC |
                            QVIRTIO_F_RING_EVENT_IDX);
    qvirtio_set_features(bus, dev, features);

    qvirtio_set_driver_ok(bus, dev);
}
Пример #3
0
static void init_virtio_dev(TestServer *s)
{
    QVirtioPCIDevice *dev;
    uint32_t features;

    s->bus = qpci_init_pc(NULL);
    g_assert_nonnull(s->bus);

    dev = qvirtio_pci_device_find(s->bus, VIRTIO_ID_NET);
    g_assert_nonnull(dev);

    qvirtio_pci_device_enable(dev);
    qvirtio_reset(&dev->vdev);
    qvirtio_set_acknowledge(&dev->vdev);
    qvirtio_set_driver(&dev->vdev);

    features = qvirtio_get_features(&dev->vdev);
    features = features & VIRTIO_NET_F_MAC;
    qvirtio_set_features(&dev->vdev, features);

    qvirtio_set_driver_ok(&dev->vdev);
    qvirtio_pci_device_free(dev);
}
Пример #4
0
static void test_basic(QVirtioDevice *dev, QGuestAllocator *alloc,
                       QVirtQueue *vq)
{
    QVirtioBlkReq req;
    uint64_t req_addr;
    uint64_t capacity;
    uint32_t features;
    uint32_t free_head;
    uint8_t status;
    char *data;

    capacity = qvirtio_config_readq(dev, 0);

    g_assert_cmpint(capacity, ==, TEST_IMAGE_SIZE / 512);

    features = qvirtio_get_features(dev);
    features = features & ~(QVIRTIO_F_BAD_FEATURE |
                    (1u << VIRTIO_RING_F_INDIRECT_DESC) |
                    (1u << VIRTIO_RING_F_EVENT_IDX) |
                    (1u << VIRTIO_BLK_F_SCSI));
    qvirtio_set_features(dev, features);

    qvirtio_set_driver_ok(dev);

    /* Write and read with 3 descriptor layout */
    /* Write request */
    req.type = VIRTIO_BLK_T_OUT;
    req.ioprio = 1;
    req.sector = 0;
    req.data = g_malloc0(512);
    strcpy(req.data, "TEST");

    req_addr = virtio_blk_request(alloc, dev, &req, 512);

    g_free(req.data);

    free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
    qvirtqueue_add(vq, req_addr + 16, 512, false, true);
    qvirtqueue_add(vq, req_addr + 528, 1, true, false);

    qvirtqueue_kick(dev, vq, free_head);

    qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
    status = readb(req_addr + 528);
    g_assert_cmpint(status, ==, 0);

    guest_free(alloc, req_addr);

    /* Read request */
    req.type = VIRTIO_BLK_T_IN;
    req.ioprio = 1;
    req.sector = 0;
    req.data = g_malloc0(512);

    req_addr = virtio_blk_request(alloc, dev, &req, 512);

    g_free(req.data);

    free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
    qvirtqueue_add(vq, req_addr + 16, 512, true, true);
    qvirtqueue_add(vq, req_addr + 528, 1, true, false);

    qvirtqueue_kick(dev, vq, free_head);

    qvirtio_wait_used_elem(dev, vq, free_head, NULL, QVIRTIO_BLK_TIMEOUT_US);
    status = readb(req_addr + 528);
    g_assert_cmpint(status, ==, 0);

    data = g_malloc0(512);
    memread(req_addr + 16, data, 512);
    g_assert_cmpstr(data, ==, "TEST");
    g_free(data);

    guest_free(alloc, req_addr);

    if (features & (1u << VIRTIO_BLK_F_WRITE_ZEROES)) {
        struct virtio_blk_discard_write_zeroes dwz_hdr;
        void *expected;

        /*
         * WRITE_ZEROES request on the same sector of previous test where
         * we wrote "TEST".
         */
        req.type = VIRTIO_BLK_T_WRITE_ZEROES;
        req.data = (char *) &dwz_hdr;
        dwz_hdr.sector = 0;
        dwz_hdr.num_sectors = 1;
        dwz_hdr.flags = 0;

        virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);

        req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));

        free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
        qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
        qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);

        qvirtqueue_kick(dev, vq, free_head);

        qvirtio_wait_used_elem(dev, vq, free_head, NULL,
                               QVIRTIO_BLK_TIMEOUT_US);
        status = readb(req_addr + 16 + sizeof(dwz_hdr));
        g_assert_cmpint(status, ==, 0);

        guest_free(alloc, req_addr);

        /* Read request to check if the sector contains all zeroes */
        req.type = VIRTIO_BLK_T_IN;
        req.ioprio = 1;
        req.sector = 0;
        req.data = g_malloc0(512);

        req_addr = virtio_blk_request(alloc, dev, &req, 512);

        g_free(req.data);

        free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
        qvirtqueue_add(vq, req_addr + 16, 512, true, true);
        qvirtqueue_add(vq, req_addr + 528, 1, true, false);

        qvirtqueue_kick(dev, vq, free_head);

        qvirtio_wait_used_elem(dev, vq, free_head, NULL,
                               QVIRTIO_BLK_TIMEOUT_US);
        status = readb(req_addr + 528);
        g_assert_cmpint(status, ==, 0);

        data = g_malloc(512);
        expected = g_malloc0(512);
        memread(req_addr + 16, data, 512);
        g_assert_cmpmem(data, 512, expected, 512);
        g_free(expected);
        g_free(data);

        guest_free(alloc, req_addr);
    }

    if (features & (1u << VIRTIO_BLK_F_DISCARD)) {
        struct virtio_blk_discard_write_zeroes dwz_hdr;

        req.type = VIRTIO_BLK_T_DISCARD;
        req.data = (char *) &dwz_hdr;
        dwz_hdr.sector = 0;
        dwz_hdr.num_sectors = 1;
        dwz_hdr.flags = 0;

        virtio_blk_fix_dwz_hdr(dev, &dwz_hdr);

        req_addr = virtio_blk_request(alloc, dev, &req, sizeof(dwz_hdr));

        free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
        qvirtqueue_add(vq, req_addr + 16, sizeof(dwz_hdr), false, true);
        qvirtqueue_add(vq, req_addr + 16 + sizeof(dwz_hdr), 1, true, false);

        qvirtqueue_kick(dev, vq, free_head);

        qvirtio_wait_used_elem(dev, vq, free_head, NULL,
                               QVIRTIO_BLK_TIMEOUT_US);
        status = readb(req_addr + 16 + sizeof(dwz_hdr));
        g_assert_cmpint(status, ==, 0);

        guest_free(alloc, req_addr);
    }

    if (features & (1u << VIRTIO_F_ANY_LAYOUT)) {
        /* Write and read with 2 descriptor layout */
        /* Write request */
        req.type = VIRTIO_BLK_T_OUT;
        req.ioprio = 1;
        req.sector = 1;
        req.data = g_malloc0(512);
        strcpy(req.data, "TEST");

        req_addr = virtio_blk_request(alloc, dev, &req, 512);

        g_free(req.data);

        free_head = qvirtqueue_add(vq, req_addr, 528, false, true);
        qvirtqueue_add(vq, req_addr + 528, 1, true, false);
        qvirtqueue_kick(dev, vq, free_head);

        qvirtio_wait_used_elem(dev, vq, free_head, NULL,
                               QVIRTIO_BLK_TIMEOUT_US);
        status = readb(req_addr + 528);
        g_assert_cmpint(status, ==, 0);

        guest_free(alloc, req_addr);

        /* Read request */
        req.type = VIRTIO_BLK_T_IN;
        req.ioprio = 1;
        req.sector = 1;
        req.data = g_malloc0(512);

        req_addr = virtio_blk_request(alloc, dev, &req, 512);

        g_free(req.data);

        free_head = qvirtqueue_add(vq, req_addr, 16, false, true);
        qvirtqueue_add(vq, req_addr + 16, 513, true, false);

        qvirtqueue_kick(dev, vq, free_head);

        qvirtio_wait_used_elem(dev, vq, free_head, NULL,
                               QVIRTIO_BLK_TIMEOUT_US);
        status = readb(req_addr + 528);
        g_assert_cmpint(status, ==, 0);

        data = g_malloc0(512);
        memread(req_addr + 16, data, 512);
        g_assert_cmpstr(data, ==, "TEST");
        g_free(data);

        guest_free(alloc, req_addr);
    }