]> rtime.felk.cvut.cz Git - lisovros/qemu_apohw.git/commitdiff
virtio: add and use virtio_set_features
authorPaolo Bonzini <pbonzini@redhat.com>
Thu, 24 Nov 2011 12:28:52 +0000 (13:28 +0100)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 28 Nov 2011 17:36:28 +0000 (11:36 -0600)
vdev->guest_features is not masking features that are not supported by
the guest.  Fix this by introducing a common wrapper to be used by all
virtio bus implementations.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
hw/s390-virtio-bus.c
hw/syborg_virtio.c
hw/virtio-pci.c
hw/virtio.c
hw/virtio.h

index 0ce6406b6db6895a2f5507a6eb5724d24f656772..c4b9a99e6ec27f7fff91fe7ddc4afcf0a856cba2 100644 (file)
@@ -254,10 +254,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
     /* Update guest supported feature bitmap */
 
     features = bswap32(ldl_be_phys(dev->feat_offs));
-    if (vdev->set_features) {
-        vdev->set_features(vdev, features);
-    }
-    vdev->guest_features = features;
+    virtio_set_features(vdev, features);
 }
 
 VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
index 00c7be8c8f4560cab7a4a71d6de38e814814e58e..6de952c938235f3cb1ca615507a23cc92b3c40d7 100644 (file)
@@ -131,9 +131,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
     }
     switch (offset >> 2) {
     case SYBORG_VIRTIO_GUEST_FEATURES:
-        if (vdev->set_features)
-            vdev->set_features(vdev, value);
-        vdev->guest_features = value;
+        virtio_set_features(vdev, value);
         break;
     case SYBORG_VIRTIO_QUEUE_BASE:
         if (value == 0)
index ca5923c49539698a4a6c06fe5e4ec8be3c8a00c4..64c6a9414ff39b5e3202505a7c5c2a4f941ca0ba 100644 (file)
@@ -285,14 +285,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     case VIRTIO_PCI_GUEST_FEATURES:
        /* Guest does not negotiate properly?  We have to assume nothing. */
        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
-           if (vdev->bad_features)
-               val = proxy->host_features & vdev->bad_features(vdev);
-           else
-               val = 0;
+            val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
        }
-        if (vdev->set_features)
-            vdev->set_features(vdev, val);
-        vdev->guest_features = val;
+        virtio_set_features(vdev, val);
         break;
     case VIRTIO_PCI_QUEUE_PFN:
         pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
index 7011b5b398523232bce63e11f7fbcd1e2a2d7212..81ecc40b310d0d02dc1c8fbf8592de948be3b6d2 100644 (file)
@@ -763,12 +763,25 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
     }
 }
 
+int virtio_set_features(VirtIODevice *vdev, uint32_t val)
+{
+    uint32_t supported_features =
+        vdev->binding->get_features(vdev->binding_opaque);
+    bool bad = (val & ~supported_features) != 0;
+
+    val &= supported_features;
+    if (vdev->set_features) {
+        vdev->set_features(vdev, val);
+    }
+    vdev->guest_features = val;
+    return bad ? -1 : 0;
+}
+
 int virtio_load(VirtIODevice *vdev, QEMUFile *f)
 {
     int num, i, ret;
     uint32_t features;
-    uint32_t supported_features =
-        vdev->binding->get_features(vdev->binding_opaque);
+    uint32_t supported_features;
 
     if (vdev->binding->load_config) {
         ret = vdev->binding->load_config(vdev->binding_opaque, f);
@@ -780,14 +793,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     qemu_get_8s(f, &vdev->isr);
     qemu_get_be16s(f, &vdev->queue_sel);
     qemu_get_be32s(f, &features);
-    if (features & ~supported_features) {
+
+    if (virtio_set_features(vdev, features) < 0) {
+        supported_features = vdev->binding->get_features(vdev->binding_opaque);
         error_report("Features 0x%x unsupported. Allowed features: 0x%x",
                      features, supported_features);
         return -1;
     }
-    if (vdev->set_features)
-        vdev->set_features(vdev, features);
-    vdev->guest_features = features;
     vdev->config_len = qemu_get_be32(f);
     qemu_get_buffer(f, vdev->config, vdev->config_len);
 
index 2d18209fb2d7804c467a58304b718b10f9f09822..25f55647b4e3d4b658838351c28222353ee89f33 100644 (file)
@@ -185,6 +185,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector);
 void virtio_set_status(VirtIODevice *vdev, uint8_t val);
 void virtio_reset(void *opaque);
 void virtio_update_irq(VirtIODevice *vdev);
+int virtio_set_features(VirtIODevice *vdev, uint32_t val);
 
 void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
                         void *opaque);