[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [6975] Fix oops on 2.6.25 guest (Rusty Russell)
From: |
Anthony Liguori |
Subject: |
[Qemu-devel] [6975] Fix oops on 2.6.25 guest (Rusty Russell) |
Date: |
Sun, 05 Apr 2009 17:40:14 +0000 |
Revision: 6975
http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6975
Author: aliguori
Date: 2009-04-05 17:40:08 +0000 (Sun, 05 Apr 2009)
Log Message:
-----------
Fix oops on 2.6.25 guest (Rusty Russell)
I believe this is behind the following:
https://bugs.edge.launchpad.net/ubuntu/jaunty/+source/linux/+bug/331128
virtio_pci in 2.6.25 didn't do feature negotiation correctly: it acked every
bit. Fortunately, we can detect this.
Signed-off-by: Rusty Russell <address@hidden>
Signed-off-by: Anthony Liguori <address@hidden>
Modified Paths:
--------------
trunk/hw/virtio-net.c
trunk/hw/virtio.c
trunk/hw/virtio.h
Modified: trunk/hw/virtio-net.c
===================================================================
--- trunk/hw/virtio-net.c 2009-04-04 19:10:26 UTC (rev 6974)
+++ trunk/hw/virtio-net.c 2009-04-05 17:40:08 UTC (rev 6975)
@@ -113,6 +113,21 @@
return features;
}
+static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
+{
+ uint32_t features = 0;
+
+ /* Linux kernel 2.6.25. It understood MAC (as everyone must),
+ * but also these: */
+ features |= (1 << VIRTIO_NET_F_MAC);
+ features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
+ features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
+ features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
+ features |= (1 << VIRTIO_NET_F_GUEST_ECN);
+
+ return features & virtio_net_get_features(vdev);
+}
+
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
{
VirtIONet *n = to_virtio_net(vdev);
@@ -580,6 +595,7 @@
n->vdev.set_config = virtio_net_set_config;
n->vdev.get_features = virtio_net_get_features;
n->vdev.set_features = virtio_net_set_features;
+ n->vdev.bad_features = virtio_net_bad_features;
n->vdev.reset = virtio_net_reset;
n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
Modified: trunk/hw/virtio.c
===================================================================
--- trunk/hw/virtio.c 2009-04-04 19:10:26 UTC (rev 6974)
+++ trunk/hw/virtio.c 2009-04-05 17:40:08 UTC (rev 6975)
@@ -451,6 +451,13 @@
switch (addr) {
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 = vdev->bad_features(vdev);
+ else
+ val = 0;
+ }
if (vdev->set_features)
vdev->set_features(vdev, val);
vdev->features = val;
@@ -490,7 +497,7 @@
switch (addr) {
case VIRTIO_PCI_HOST_FEATURES:
ret = vdev->get_features(vdev);
- ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE);
break;
case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->features;
Modified: trunk/hw/virtio.h
===================================================================
--- trunk/hw/virtio.h 2009-04-04 19:10:26 UTC (rev 6974)
+++ trunk/hw/virtio.h 2009-04-05 17:40:08 UTC (rev 6975)
@@ -32,6 +32,8 @@
/* We notify when the ring is completely used, even if the guest is supressing
* callbacks */
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
+/* A guest should never accept this. It implies negotiation is broken. */
+#define VIRTIO_F_BAD_FEATURE 30
/* from Linux's linux/virtio_ring.h */
@@ -82,6 +84,7 @@
size_t config_len;
void *config;
uint32_t (*get_features)(VirtIODevice *vdev);
+ uint32_t (*bad_features)(VirtIODevice *vdev);
void (*set_features)(VirtIODevice *vdev, uint32_t val);
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [6975] Fix oops on 2.6.25 guest (Rusty Russell),
Anthony Liguori <=