File 0296-virtio-make-sure-vdev-vq-i-.inuse-n.patch of Package qemu.10254
From eaeb373fc1ffec83426bf2c0d92e243433827e5d Mon Sep 17 00:00:00 2001
From: Fei Li <fli@suse.com>
Date: Thu, 15 Mar 2018 16:56:11 +0800
Subject: [PATCH] virtio: make sure vdev->vq[i].inuse never goes below 0
Set vdev->vq[i].inuse to 0 if its value goes below 0. Or else its
value would turn to be a large unsigned integer like 65535 when
comparing with unsigned vdev->vq[i].vring.num, which leads to an
error.
[FL: BSC#1020928]
Signed-off-by: Fei Li <fli@suse.com>
---
hw/virtio/virtio.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 4738e33e1a..812e200895 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1097,6 +1097,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
for (i = 0; i < num; i++) {
if (vdev->vq[i].pa) {
uint16_t nheads;
+ int inuse_tmp;
nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
/* Check it isn't doing strange things with descriptor numbers. */
if (nheads > vdev->vq[i].vring.num) {
@@ -1115,8 +1116,17 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
* Since max ring size < UINT16_MAX it's safe to use modulo
* UINT16_MAX + 1 subtraction.
*/
- vdev->vq[i].inuse = (uint16_t)(vdev->vq[i].last_avail_idx -
- vdev->vq[i].used_idx);
+ inuse_tmp = (int)(vdev->vq[i].last_avail_idx -
+ vdev->vq[i].used_idx);
+ if (inuse_tmp < 0) {
+ printf("WARNING: for VQ %d, its last_avail_idx 0x%x < used_idx "
+ "0x%x. Their difference will falsely turn to be a large "
+ "unsigned integer like 65535 when later comparing with "
+ "the unsigned vring.num. Set the minus to 0 to avoid.\n",
+ i, vdev->vq[i].last_avail_idx, vdev->vq[i].used_idx);
+ }
+ vdev->vq[i].inuse = (inuse_tmp < 0 ? 0 : inuse_tmp);
+
if (vdev->vq[i].inuse > vdev->vq[i].vring.num) {
error_report("VQ %d size 0x%x < last_avail_idx 0x%x - "
"used_idx 0x%x",