static QVirtQueue *qvirtio_mmio_virtqueue_setup(QVirtioDevice *d, QGuestAllocator *alloc, uint16_t index) { QVirtioMMIODevice *dev = (QVirtioMMIODevice *)d; QVirtQueue *vq; uint64_t addr; vq = g_malloc0(sizeof(*vq)); qvirtio_mmio_queue_select(d, index); writel(dev->addr + QVIRTIO_MMIO_QUEUE_ALIGN, dev->page_size); vq->index = index; vq->size = qvirtio_mmio_get_queue_size(d); vq->free_head = 0; vq->num_free = vq->size; vq->align = dev->page_size; vq->indirect = (dev->features & (1u << VIRTIO_RING_F_INDIRECT_DESC)) != 0; vq->event = (dev->features & (1u << VIRTIO_RING_F_EVENT_IDX)) != 0; writel(dev->addr + QVIRTIO_MMIO_QUEUE_NUM, vq->size); /* Check different than 0 */ g_assert_cmpint(vq->size, !=, 0); /* Check power of 2 */ g_assert_cmpint(vq->size & (vq->size - 1), ==, 0); addr = guest_alloc(alloc, qvring_size(vq->size, dev->page_size)); qvring_init(alloc, vq, addr); qvirtio_mmio_set_queue_address(d, vq->desc / dev->page_size); return vq; }
static uint64_t virtio_blk_request(QGuestAllocator *alloc, QVirtioDevice *d, QVirtioBlkReq *req, uint64_t data_size) { uint64_t addr; uint8_t status = 0xFF; switch (req->type) { case VIRTIO_BLK_T_IN: case VIRTIO_BLK_T_OUT: g_assert_cmpuint(data_size % 512, ==, 0); break; case VIRTIO_BLK_T_DISCARD: case VIRTIO_BLK_T_WRITE_ZEROES: g_assert_cmpuint(data_size % sizeof(struct virtio_blk_discard_write_zeroes), ==, 0); break; default: g_assert_cmpuint(data_size, ==, 0); } addr = guest_alloc(alloc, sizeof(*req) + data_size); virtio_blk_fix_request(d, req); memwrite(addr, req, 16); memwrite(addr + 16, req->data, data_size); memwrite(addr + 16 + data_size, &status, sizeof(status)); return addr; }
/* This used to cause a NULL pointer dereference. */ static void megasas_pd_get_info_fuzz(void *obj, void *data, QGuestAllocator *alloc) { QMegasas *megasas = obj; QPCIDevice *dev = &megasas->dev; QPCIBar bar; uint32_t context[256]; uint64_t context_pa; int i; qpci_device_enable(dev); bar = qpci_iomap(dev, 0, NULL); memset(context, 0, sizeof(context)); context[0] = cpu_to_le32(0x05050505); context[1] = cpu_to_le32(0x01010101); for (i = 2; i < ARRAY_SIZE(context); i++) { context[i] = cpu_to_le32(0x41414141); } context[6] = cpu_to_le32(0x02020000); context[7] = cpu_to_le32(0); context_pa = guest_alloc(alloc, sizeof(context)); memwrite(context_pa, context, sizeof(context)); qpci_io_writel(dev, bar, 0x40, context_pa); }
static void v9fs_req_send(P9Req *req) { QVirtIO9P *v9p = req->v9p; uint32_t free_head; req->r_msg = guest_alloc(v9p->qs->alloc, P9_MAX_SIZE); free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false, true); qvirtqueue_add(v9p->vq, req->r_msg, P9_MAX_SIZE, true, false); qvirtqueue_kick(v9p->dev, v9p->vq, free_head); req->t_off = 0; }
static uint64_t qvirtio_scsi_alloc(QVirtioSCSIQueues *vs, size_t alloc_size, const void *data) { uint64_t addr; addr = guest_alloc(alloc, alloc_size); if (data) { memwrite(addr, data, alloc_size); } return addr; }
static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id, uint16_t tag) { P9Req *req = g_new0(P9Req, 1); uint32_t t_size = 7 + size; /* 9P header has well-known size of 7 bytes */ P9Hdr hdr = { .size = cpu_to_le32(t_size), .id = id, .tag = cpu_to_le16(tag) }; g_assert_cmpint(t_size, <=, P9_MAX_SIZE); req->v9p = v9p; req->t_size = t_size; req->t_msg = guest_alloc(v9p->qs->alloc, req->t_size); v9fs_memwrite(req, &hdr, 7); req->tag = tag; return req; }
QVRingIndirectDesc *qvring_indirect_desc_setup(QVirtioDevice *d, QGuestAllocator *alloc, uint16_t elem) { int i; QVRingIndirectDesc *indirect = g_malloc(sizeof(*indirect)); indirect->index = 0; indirect->elem = elem; indirect->desc = guest_alloc(alloc, sizeof(QVRingDesc)*elem); for (i = 0; i < elem - 1; ++i) { /* indirect->desc[i].addr */ writeq(indirect->desc + (16 * i), 0); /* indirect->desc[i].flags */ writew(indirect->desc + (16 * i) + 12, QVRING_DESC_F_NEXT); /* indirect->desc[i].next */ writew(indirect->desc + (16 * i) + 14, i + 1); } return indirect; }
uint32_t free_head; char test[] = "TEST"; char buffer[64]; int len = htonl(sizeof(test)); struct iovec iov[] = { { .iov_base = &len, .iov_len = sizeof(len), }, { .iov_base = test, .iov_len = sizeof(test), }, }; int ret; req_addr = guest_alloc(alloc, 64); free_head = qvirtqueue_add(vq, req_addr, 64, true, false); qvirtqueue_kick(bus, dev, vq, free_head); ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test)); g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len)); qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_NET_TIMEOUT_US); memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test)); g_assert_cmpstr(buffer, ==, "TEST"); guest_free(alloc, req_addr); } static void tx_test(const QVirtioBus *bus, QVirtioDevice *dev,