From fb8b489c8750a462a0dc6ad721c618b5e74dcfa8 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Fri, 22 Sep 2017 13:14:53 +0200 Subject: [PATCH] fix #1107: merge: virtio: fix descriptor counting in virtqueue_pop --- ...descriptor-counting-in-virtqueue_pop.patch | 55 +++++++++++++++++++ debian/patches/series | 1 + 2 files changed, 56 insertions(+) create mode 100644 debian/patches/extra/0014-virtio-fix-descriptor-counting-in-virtqueue_pop.patch diff --git a/debian/patches/extra/0014-virtio-fix-descriptor-counting-in-virtqueue_pop.patch b/debian/patches/extra/0014-virtio-fix-descriptor-counting-in-virtqueue_pop.patch new file mode 100644 index 0000000..15c5afe --- /dev/null +++ b/debian/patches/extra/0014-virtio-fix-descriptor-counting-in-virtqueue_pop.patch @@ -0,0 +1,55 @@ +From 3474ad551f5ff8c550d388251c9555882d9beb5d Mon Sep 17 00:00:00 2001 +From: Wolfgang Bumiller +Date: Tue, 19 Sep 2017 14:20:28 +0200 +Subject: [PATCH 14/14] virtio: fix descriptor counting in virtqueue_pop + +While changing the s/g list allocation, commit 3b3b0628 +also changed the descriptor counting to count iovec entries +as split by cpu_physical_memory_map(). Previously only the +actual descriptor entries were counted and the split into +the iovec happened afterwards in virtqueue_map(). +Count the entries again instead to avoid erroneous +"Looped descriptor" errors. + +Reported-by: Hans Middelhoek +Link: https://forum.proxmox.com/threads/vm-crash-with-memory-hotplug.35904/ +Fixes: 3b3b0628217e ("virtio: slim down allocation of VirtQueueElements") +Signed-off-by: Wolfgang Bumiller +--- + hw/virtio/virtio.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 890b4d7eb7..33bb770177 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -834,7 +834,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) + int64_t len; + VirtIODevice *vdev = vq->vdev; + VirtQueueElement *elem = NULL; +- unsigned out_num, in_num; ++ unsigned out_num, in_num, elem_entries; + hwaddr addr[VIRTQUEUE_MAX_SIZE]; + struct iovec iov[VIRTQUEUE_MAX_SIZE]; + VRingDesc desc; +@@ -852,7 +852,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) + smp_rmb(); + + /* When we start there are none of either input nor output. */ +- out_num = in_num = 0; ++ out_num = in_num = elem_entries = 0; + + max = vq->vring.num; + +@@ -922,7 +922,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) + } + + /* If we've got too many, that implies a descriptor loop. */ +- if ((in_num + out_num) > max) { ++ if (++elem_entries > max) { + virtio_error(vdev, "Looped descriptor"); + goto err_undo_map; + } +-- +2.11.0 + diff --git a/debian/patches/series b/debian/patches/series index 6de3a93..b4c21c8 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -39,3 +39,4 @@ extra/0010-vga-fix-display-update-region-calculation.patch extra/0011-vga-fix-display-update-region-calculation-split-scre.patch extra/0012-vga-stop-passing-pointers-to-vga_draw_line-functions.patch extra/0013-multiboot-validate-multiboot-header-address-values.patch +extra/0014-virtio-fix-descriptor-counting-in-virtqueue_pop.patch