diff --git a/hw/pci/virtio/virtio.c b/hw/pci/virtio/virtio.c index a022cb63a..21506f595 100644 --- a/hw/pci/virtio/virtio.c +++ b/hw/pci/virtio/virtio.c @@ -227,7 +227,40 @@ virtio_vq_init(struct virtio_base *base, uint32_t pfn) static void virtio_vq_enable(struct virtio_base *base) { - /* TODO: to be implemented */ + struct virtio_vq_info *vq; + uint16_t qsz; + uint64_t phys; + size_t size; + char *vb; + + vq = &base->queues[base->curq]; + qsz = vq->qsize; + + /* descriptors */ + phys = (((uint64_t)vq->gpa_desc[1]) << 32) | vq->gpa_desc[0]; + size = qsz * sizeof(struct virtio_desc); + vb = paddr_guest2host(base->dev->vmctx, phys, size); + vq->desc = (struct virtio_desc *)vb; + + /* available ring */ + phys = (((uint64_t)vq->gpa_avail[1]) << 32) | vq->gpa_avail[0]; + size = (2 + qsz + 1) * sizeof(uint16_t); + vb = paddr_guest2host(base->dev->vmctx, phys, size); + vq->avail = (struct vring_avail *)vb; + + /* used ring */ + phys = (((uint64_t)vq->gpa_used[1]) << 32) | vq->gpa_used[0]; + size = sizeof(uint16_t) * 3 + sizeof(struct virtio_used) * qsz; + vb = paddr_guest2host(base->dev->vmctx, phys, size); + vq->used = (struct vring_used *)vb; + + /* Mark queue as allocated, and start at 0 when we use it. */ + vq->flags = VQ_ALLOC; + vq->last_avail = 0; + vq->save_used = 0; + + /* Mark queue as enabled. */ + vq->enabled = true; } /* diff --git a/include/virtio.h b/include/virtio.h index ea455ceb3..c1574ec88 100644 --- a/include/virtio.h +++ b/include/virtio.h @@ -318,7 +318,8 @@ struct vring_used { /* From section 2.3, "Virtqueue Configuration", of the virtio specification */ /** - * @brief Calculate size of a virtual ring. + * @brief Calculate size of a virtual ring, this interface is only valid for + * legacy virtio. * * @param qsz Size of raw data in a certain virtqueue. *