Patchwork [04,v2] s390: reset avail and used index on reboot

login
register
mail settings
Submitter Christian Borntraeger
Date April 26, 2012, 7:03 p.m.
Message ID <1335467016-49116-1-git-send-email-borntraeger@de.ibm.com>
Download mbox | patch
Permalink /patch/155319/
State New
Headers show

Comments

Christian Borntraeger - April 26, 2012, 7:03 p.m.
From: Jens Freimann <jfrei@linux.vnet.ibm.com>

reset the guest vring avail/used idx fields, otherwise it's possible
that old values remain in memory which would cause a reboot to fail
with a "Guest moved used index" message

version 2: split out the index reset 

Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 hw/s390-virtio-bus.c |   19 ++++++++++++++++++-
 hw/s390-virtio-bus.h |    4 ++++
 hw/s390-virtio.c     |    1 +
 3 files changed, 23 insertions(+), 1 deletion(-)

Patch

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 74419b3..63ccd5c 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -63,6 +63,23 @@  static void s390_virtio_bus_reset(void *opaque)
     bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
 }
 
+void s390_virtio_reset_idx(VirtIOS390Device *dev)
+{
+    int i;
+    target_phys_addr_t idx_addr;
+    uint8_t num_vq;
+
+    num_vq = s390_virtio_device_num_vq(dev);
+    for (i = 0; i < num_vq; i++) {
+        idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) +
+            VIRTIO_VRING_AVAIL_IDX_OFFS;
+        stw_phys(idx_addr, 0);
+        idx_addr = virtio_queue_get_used_addr(dev->vdev, i) +
+            VIRTIO_VRING_USED_IDX_OFFS;
+        stw_phys(idx_addr, 0);
+    }
+}
+
 VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
 {
     VirtIOS390Bus *bus;
@@ -121,7 +138,7 @@  static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
     virtio_bind_device(vdev, &virtio_s390_bindings, dev);
     dev->host_features = vdev->get_features(vdev, dev->host_features);
     s390_virtio_device_sync(dev);
-
+    s390_virtio_reset_idx(dev);
     if (dev->qdev.hotplugged) {
         CPUS390XState *env = s390_cpu_addr2state(0);
         s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index 0e60bc0..49e6c46 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -34,6 +34,8 @@ 
 #define VIRTIO_VQCONFIG_LEN		24
 
 #define VIRTIO_RING_LEN			(TARGET_PAGE_SIZE * 3)
+#define VIRTIO_VRING_AVAIL_IDX_OFFS 2
+#define VIRTIO_VRING_USED_IDX_OFFS 2
 #define S390_DEVICE_PAGES		512
 
 #define VIRTIO_PARAM_MASK               0xff
@@ -90,3 +92,5 @@  VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
                                              ram_addr_t mem, int *vq_num);
 VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem);
 void s390_virtio_device_sync(VirtIOS390Device *dev);
+void s390_virtio_reset_idx(VirtIOS390Device *dev);
+
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index d17602f..38e8fba 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -99,6 +99,7 @@  int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall)
         virtio_reset(dev->vdev);
         stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
         s390_virtio_device_sync(dev);
+        s390_virtio_reset_idx(dev);
         break;
     }
     case KVM_S390_VIRTIO_SET_STATUS: