Commit 8eca6b1bc770982595db2f7207c65051572436cb

Authored by aliguori
1 parent 1da92db2

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 <rusty@rustcorp.com.au>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6975 c046a42c-6fe2-441c-8c8c-71466251a162
hw/virtio-net.c
@@ -113,6 +113,21 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) @@ -113,6 +113,21 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev)
113 return features; 113 return features;
114 } 114 }
115 115
  116 +static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
  117 +{
  118 + uint32_t features = 0;
  119 +
  120 + /* Linux kernel 2.6.25. It understood MAC (as everyone must),
  121 + * but also these: */
  122 + features |= (1 << VIRTIO_NET_F_MAC);
  123 + features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
  124 + features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
  125 + features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
  126 + features |= (1 << VIRTIO_NET_F_GUEST_ECN);
  127 +
  128 + return features & virtio_net_get_features(vdev);
  129 +}
  130 +
116 static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) 131 static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
117 { 132 {
118 VirtIONet *n = to_virtio_net(vdev); 133 VirtIONet *n = to_virtio_net(vdev);
@@ -580,6 +595,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) @@ -580,6 +595,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
580 n->vdev.set_config = virtio_net_set_config; 595 n->vdev.set_config = virtio_net_set_config;
581 n->vdev.get_features = virtio_net_get_features; 596 n->vdev.get_features = virtio_net_get_features;
582 n->vdev.set_features = virtio_net_set_features; 597 n->vdev.set_features = virtio_net_set_features;
  598 + n->vdev.bad_features = virtio_net_bad_features;
583 n->vdev.reset = virtio_net_reset; 599 n->vdev.reset = virtio_net_reset;
584 n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx); 600 n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
585 n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx); 601 n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
hw/virtio.c
@@ -451,6 +451,13 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) @@ -451,6 +451,13 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
451 451
452 switch (addr) { 452 switch (addr) {
453 case VIRTIO_PCI_GUEST_FEATURES: 453 case VIRTIO_PCI_GUEST_FEATURES:
  454 + /* Guest does not negotiate properly? We have to assume nothing. */
  455 + if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
  456 + if (vdev->bad_features)
  457 + val = vdev->bad_features(vdev);
  458 + else
  459 + val = 0;
  460 + }
454 if (vdev->set_features) 461 if (vdev->set_features)
455 vdev->set_features(vdev, val); 462 vdev->set_features(vdev, val);
456 vdev->features = val; 463 vdev->features = val;
@@ -490,7 +497,7 @@ static uint32_t virtio_ioport_read(void *opaque, uint32_t addr) @@ -490,7 +497,7 @@ static uint32_t virtio_ioport_read(void *opaque, uint32_t addr)
490 switch (addr) { 497 switch (addr) {
491 case VIRTIO_PCI_HOST_FEATURES: 498 case VIRTIO_PCI_HOST_FEATURES:
492 ret = vdev->get_features(vdev); 499 ret = vdev->get_features(vdev);
493 - ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY); 500 + ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | (1 << VIRTIO_F_BAD_FEATURE);
494 break; 501 break;
495 case VIRTIO_PCI_GUEST_FEATURES: 502 case VIRTIO_PCI_GUEST_FEATURES:
496 ret = vdev->features; 503 ret = vdev->features;
hw/virtio.h
@@ -32,6 +32,8 @@ @@ -32,6 +32,8 @@
32 /* We notify when the ring is completely used, even if the guest is supressing 32 /* We notify when the ring is completely used, even if the guest is supressing
33 * callbacks */ 33 * callbacks */
34 #define VIRTIO_F_NOTIFY_ON_EMPTY 24 34 #define VIRTIO_F_NOTIFY_ON_EMPTY 24
  35 +/* A guest should never accept this. It implies negotiation is broken. */
  36 +#define VIRTIO_F_BAD_FEATURE 30
35 37
36 /* from Linux's linux/virtio_ring.h */ 38 /* from Linux's linux/virtio_ring.h */
37 39
@@ -82,6 +84,7 @@ struct VirtIODevice @@ -82,6 +84,7 @@ struct VirtIODevice
82 size_t config_len; 84 size_t config_len;
83 void *config; 85 void *config;
84 uint32_t (*get_features)(VirtIODevice *vdev); 86 uint32_t (*get_features)(VirtIODevice *vdev);
  87 + uint32_t (*bad_features)(VirtIODevice *vdev);
85 void (*set_features)(VirtIODevice *vdev, uint32_t val); 88 void (*set_features)(VirtIODevice *vdev, uint32_t val);
86 void (*get_config)(VirtIODevice *vdev, uint8_t *config); 89 void (*get_config)(VirtIODevice *vdev, uint8_t *config);
87 void (*set_config)(VirtIODevice *vdev, const uint8_t *config); 90 void (*set_config)(VirtIODevice *vdev, const uint8_t *config);