From e45451c6994f6e93729ee3860e45fa965483356f Mon Sep 17 00:00:00 2001 From: Ladi Prosek Date: Fri, 16 Dec 2016 10:54:32 +0100 Subject: [PATCH] [virtio] Cap queue size to MAX_QUEUE_NUM vpm_find_vqs incorrectly accepted the host provided queue size with no regard to iPXE's internal limitations. Virtio 1.0 makes it possible for the driver to override the queue size to reduce memory requirements and iPXE is a great use case for this feature. Also removing the extra vq->vring.num assignment which is already handled in vring_init. Signed-off-by: Ladi Prosek Acked-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Signed-off-by: Michael Brown --- src/drivers/bus/virtio-pci.c | 8 +++++++- src/include/ipxe/virtio-ring.h | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/drivers/bus/virtio-pci.c b/src/drivers/bus/virtio-pci.c index 3311595f..1fcf9bae 100644 --- a/src/drivers/bus/virtio-pci.c +++ b/src/drivers/bus/virtio-pci.c @@ -358,12 +358,18 @@ int vpm_find_vqs(struct virtio_pci_modern_device *vdev, return -EINVAL; } + if (size > MAX_QUEUE_NUM) { + /* iPXE networking tends to be not perf critical so there's no + * need to accept large queue sizes. + */ + size = MAX_QUEUE_NUM; + } + vq = &vqs[i]; vq->queue_index = i; /* get offset of notification word for this vq */ off = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_notify_off)); - vq->vring.num = size; vring_init(&vq->vring, size, (unsigned char *)vq->queue); diff --git a/src/include/ipxe/virtio-ring.h b/src/include/ipxe/virtio-ring.h index 6ba550b5..d2ded300 100644 --- a/src/include/ipxe/virtio-ring.h +++ b/src/include/ipxe/virtio-ring.h @@ -95,7 +95,7 @@ static inline void vring_init(struct vring *vr, unsigned int i; unsigned long pa; - vr->num = num; + vr->num = num; /* physical address of desc must be page aligned */ @@ -103,13 +103,13 @@ static inline void vring_init(struct vring *vr, pa = (pa + PAGE_MASK) & ~PAGE_MASK; vr->desc = phys_to_virt(pa); - vr->avail = (struct vring_avail *)&vr->desc[num]; + vr->avail = (struct vring_avail *)&vr->desc[num]; /* physical address of used must be page aligned */ pa = virt_to_phys(&vr->avail->ring[num]); pa = (pa + PAGE_MASK) & ~PAGE_MASK; - vr->used = phys_to_virt(pa); + vr->used = phys_to_virt(pa); for (i = 0; i < num - 1; i++) vr->desc[i].next = i + 1;