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); }
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); }
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); }
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); }