aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/s390-virtio-bus.c12
-rw-r--r--hw/s390-virtio-bus.h1
-rw-r--r--hw/syborg_virtio.c13
-rw-r--r--hw/virtio-balloon.c4
-rw-r--r--hw/virtio-blk.c6
-rw-r--r--hw/virtio-blk.h8
-rw-r--r--hw/virtio-console.c4
-rw-r--r--hw/virtio-net.c39
-rw-r--r--hw/virtio-net.h20
-rw-r--r--hw/virtio-pci.c25
-rw-r--r--hw/virtio.c2
-rw-r--r--hw/virtio.h7
12 files changed, 91 insertions, 50 deletions
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 6c0da11f73..980e7ebbe8 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -101,6 +101,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
bus->dev_offs += dev_len;
virtio_bind_device(vdev, &virtio_s390_bindings, dev);
+ dev->host_features = vdev->get_features(vdev, dev->host_features);
s390_virtio_device_sync(dev);
return 0;
@@ -222,9 +223,7 @@ static void s390_virtio_device_sync(VirtIOS390Device *dev)
cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
/* Sync feature bitmap */
- if (dev->vdev->get_features) {
- stl_phys(cur_offs, dev->vdev->get_features(dev->vdev));
- }
+ stl_phys(cur_offs, dev->host_features);
dev->feat_offs = cur_offs + dev->feat_len;
cur_offs += dev->feat_len * 2;
@@ -310,10 +309,17 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token);
}
+static unsigned virtio_s390_get_features(void *opaque)
+{
+ VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
+ return dev->host_features;
+}
+
/**************** S390 Virtio Bus Device Descriptions *******************/
static const VirtIOBindings virtio_s390_bindings = {
.notify = virtio_s390_notify,
+ .get_features = virtio_s390_get_features,
};
static VirtIOS390DeviceInfo s390_virtio_net = {
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index ef3671421a..8ae206563e 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -40,6 +40,7 @@ typedef struct VirtIOS390Device {
VirtIODevice *vdev;
DriveInfo *dinfo;
NICConf nic;
+ uint32_t host_features;
} VirtIOS390Device;
typedef struct VirtIOS390Bus {
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index fe6fc23ecd..65239a0572 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -25,6 +25,7 @@
#include "syborg.h"
#include "sysbus.h"
#include "virtio.h"
+#include "virtio-net.h"
#include "sysemu.h"
//#define DEBUG_SYBORG_VIRTIO
@@ -66,6 +67,7 @@ typedef struct {
uint32_t int_enable;
uint32_t id;
NICConf nic;
+ uint32_t host_features;
} SyborgVirtIOProxy;
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
@@ -86,8 +88,7 @@ static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
ret = s->id;
break;
case SYBORG_VIRTIO_HOST_FEATURES:
- ret = vdev->get_features(vdev);
- ret |= vdev->binding->get_features(s);
+ ret = s->host_features;
break;
case SYBORG_VIRTIO_GUEST_FEATURES:
ret = vdev->guest_features;
@@ -244,9 +245,8 @@ static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
static unsigned syborg_virtio_get_features(void *opaque)
{
- unsigned ret = 0;
- ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
- return ret;
+ SyborgVirtIOProxy *proxy = opaque;
+ return proxy->host_features;
}
static VirtIOBindings syborg_virtio_bindings = {
@@ -272,6 +272,8 @@ static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
qemu_register_reset(virtio_reset, vdev);
virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
+ proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ proxy->host_features = vdev->get_features(vdev, proxy->host_features);
return 0;
}
@@ -292,6 +294,7 @@ static SysBusDeviceInfo syborg_virtio_net_info = {
.qdev.size = sizeof(SyborgVirtIOProxy),
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
+ DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
DEFINE_PROP_END_OF_LIST(),
}
};
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index cfd3b413ff..e17880ff7c 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -124,9 +124,9 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
dev->actual = config.actual;
}
-static uint32_t virtio_balloon_get_features(VirtIODevice *vdev)
+static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
{
- return 0;
+ return f;
}
static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target)
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index a2f063974a..cb1ae1f953 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -432,19 +432,15 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
memcpy(config, &blkcfg, s->config_size);
}
-static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
+static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
{
VirtIOBlock *s = to_virtio_blk(vdev);
- uint32_t features = 0;
features |= (1 << VIRTIO_BLK_F_SEG_MAX);
features |= (1 << VIRTIO_BLK_F_GEOMETRY);
if (bdrv_enable_write_cache(s->bs))
features |= (1 << VIRTIO_BLK_F_WCACHE);
-#ifdef __linux__
- features |= (1 << VIRTIO_BLK_F_SCSI);
-#endif
if (strcmp(s->serial_str, "0"))
features |= 1 << VIRTIO_BLK_F_IDENTIFY;
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index 23ad74caec..c28f776c2e 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -92,4 +92,12 @@ struct virtio_scsi_inhdr
uint32_t residual;
};
+#ifdef __linux__
+#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
+ DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
+ DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true)
+#else
+#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
+ DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
+#endif
#endif
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 57f8f89afa..4f18ef29cb 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -51,9 +51,9 @@ static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq)
{
}
-static uint32_t virtio_console_get_features(VirtIODevice *vdev)
+static uint32_t virtio_console_get_features(VirtIODevice *vdev, uint32_t f)
{
- return 0;
+ return f;
}
static int vcon_can_read(void *opaque)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index ab20a33e21..c2a389ffb5 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -147,34 +147,27 @@ static int peer_has_ufo(VirtIONet *n)
return n->has_ufo;
}
-static uint32_t virtio_net_get_features(VirtIODevice *vdev)
+static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
{
VirtIONet *n = to_virtio_net(vdev);
- uint32_t features = (1 << VIRTIO_NET_F_MAC) |
- (1 << VIRTIO_NET_F_MRG_RXBUF) |
- (1 << VIRTIO_NET_F_STATUS) |
- (1 << VIRTIO_NET_F_CTRL_VQ) |
- (1 << VIRTIO_NET_F_CTRL_RX) |
- (1 << VIRTIO_NET_F_CTRL_VLAN) |
- (1 << VIRTIO_NET_F_CTRL_RX_EXTRA);
if (peer_has_vnet_hdr(n)) {
tap_using_vnet_hdr(n->nic->nc.peer, 1);
+ } else {
+ features &= ~(0x1 << VIRTIO_NET_F_CSUM);
+ features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4);
+ features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6);
+ features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN);
+
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM);
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4);
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6);
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN);
+ }
- features |= (1 << VIRTIO_NET_F_CSUM);
- features |= (1 << VIRTIO_NET_F_HOST_TSO4);
- features |= (1 << VIRTIO_NET_F_HOST_TSO6);
- features |= (1 << VIRTIO_NET_F_HOST_ECN);
-
- 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);
-
- if (peer_has_ufo(n)) {
- features |= (1 << VIRTIO_NET_F_GUEST_UFO);
- features |= (1 << VIRTIO_NET_F_HOST_UFO);
- }
+ if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
+ features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO);
+ features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
}
return features;
@@ -192,7 +185,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
features |= (1 << VIRTIO_NET_F_HOST_TSO6);
features |= (1 << VIRTIO_NET_F_HOST_ECN);
- return features & virtio_net_get_features(vdev);
+ return features;
}
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 2085181673..9130d75c93 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -153,4 +153,24 @@ struct virtio_net_ctrl_mac {
#define VIRTIO_NET_CTRL_VLAN_ADD 0
#define VIRTIO_NET_CTRL_VLAN_DEL 1
+#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \
+ DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
+ DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
+ DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \
+ DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \
+ DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \
+ DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \
+ DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \
+ DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \
+ DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \
+ DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \
+ DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \
+ DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \
+ DEFINE_PROP_BIT("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \
+ DEFINE_PROP_BIT("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \
+ DEFINE_PROP_BIT("status", _state, _field, VIRTIO_NET_F_STATUS, true), \
+ DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \
+ DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
+ DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
+ DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true)
#endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 4e1d5e1963..6d0f9dd37a 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -16,6 +16,8 @@
#include <inttypes.h>
#include "virtio.h"
+#include "virtio-blk.h"
+#include "virtio-net.h"
#include "pci.h"
#include "sysemu.h"
#include "msix.h"
@@ -92,6 +94,7 @@ typedef struct {
uint32_t nvectors;
DriveInfo *dinfo;
NICConf nic;
+ uint32_t host_features;
} VirtIOPCIProxy;
/* virtio device */
@@ -175,7 +178,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
/* 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);
+ val = proxy->host_features & vdev->bad_features(vdev);
else
val = 0;
}
@@ -235,8 +238,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
switch (addr) {
case VIRTIO_PCI_HOST_FEATURES:
- ret = vdev->get_features(vdev);
- ret |= vdev->binding->get_features(proxy);
+ ret = proxy->host_features;
break;
case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->guest_features;
@@ -382,11 +384,8 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
static unsigned virtio_pci_get_features(void *opaque)
{
- unsigned ret = 0;
- ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
- ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
- ret |= (1 << VIRTIO_F_BAD_FEATURE);
- return ret;
+ VirtIOPCIProxy *proxy = opaque;
+ return proxy->host_features;
}
static const VirtIOBindings virtio_pci_bindings = {
@@ -442,6 +441,9 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
virtio_map);
virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
+ proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
+ proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
+ proxy->host_features = vdev->get_features(vdev, proxy->host_features);
}
static int virtio_blk_init_pci(PCIDevice *pci_dev)
@@ -553,6 +555,7 @@ static PCIDeviceInfo virtio_info[] = {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+ DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(),
},
.qdev.reset = virtio_pci_reset,
@@ -564,6 +567,7 @@ static PCIDeviceInfo virtio_info[] = {
.romfile = "pxe-virtio.bin",
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+ DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
DEFINE_PROP_END_OF_LIST(),
},
@@ -575,6 +579,7 @@ static PCIDeviceInfo virtio_info[] = {
.exit = virtio_exit_pci,
.qdev.props = (Property[]) {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(),
},
.qdev.reset = virtio_pci_reset,
@@ -583,6 +588,10 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_balloon_init_pci,
.exit = virtio_exit_pci,
+ .qdev.props = (Property[]) {
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+ DEFINE_PROP_END_OF_LIST(),
+ },
.qdev.reset = virtio_pci_reset,
},{
/* end of list */
diff --git a/hw/virtio.c b/hw/virtio.c
index c25a5f12bb..fa7184ab95 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -652,7 +652,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{
int num, i, ret;
uint32_t features;
- uint32_t supported_features = vdev->get_features(vdev) |
+ uint32_t supported_features =
vdev->binding->get_features(vdev->binding_opaque);
if (vdev->binding->load_config) {
diff --git a/hw/virtio.h b/hw/virtio.h
index 85ef171248..3994cc973f 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -105,7 +105,7 @@ struct VirtIODevice
void *config;
uint16_t config_vector;
int nvectors;
- uint32_t (*get_features)(VirtIODevice *vdev);
+ uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
uint32_t (*bad_features)(VirtIODevice *vdev);
void (*set_features)(VirtIODevice *vdev, uint32_t val);
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
@@ -176,4 +176,9 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev);
void virtio_net_exit(VirtIODevice *vdev);
+#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
+ DEFINE_PROP_BIT("indirect_desc", _state, _field, \
+ VIRTIO_RING_F_INDIRECT_DESC, true)
+
+
#endif