From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LqWKf-0002Oc-6e for qemu-devel@nongnu.org; Sun, 05 Apr 2009 13:40:33 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LqWKd-0002NJ-PW for qemu-devel@nongnu.org; Sun, 05 Apr 2009 13:40:32 -0400 Received: from [199.232.76.173] (port=34504 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LqWKd-0002N6-Bn for qemu-devel@nongnu.org; Sun, 05 Apr 2009 13:40:31 -0400 Received: from savannah.gnu.org ([199.232.41.3]:38363 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LqWKc-00043r-VL for qemu-devel@nongnu.org; Sun, 05 Apr 2009 13:40:31 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1LqWKU-00066Z-1X for qemu-devel@nongnu.org; Sun, 05 Apr 2009 17:40:25 +0000 Received: from aliguori by cvs.savannah.gnu.org with local (Exim 4.69) (envelope-from ) id 1LqWKL-00065U-R2 for qemu-devel@nongnu.org; Sun, 05 Apr 2009 17:40:20 +0000 MIME-Version: 1.0 Errors-To: aliguori Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Anthony Liguori Message-Id: Date: Sun, 05 Apr 2009 17:40:14 +0000 Subject: [Qemu-devel] [6975] Fix oops on 2.6.25 guest (Rusty Russell) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org 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 Signed-off-by: Anthony Liguori 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);