@@ -21,7 +21,8 @@
#include "virtio-9p-coth.h"
#include "hw/virtio/virtio-access.h"
-static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features)
+static uint64_t virtio_9p_get_features_legacy(VirtIODevice *vdev,
+ uint64_t features)
{
virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
return features;
@@ -152,7 +153,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data)
dc->props = virtio_9p_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->realize = virtio_9p_device_realize;
- vdc->get_features = virtio_9p_get_features;
+ vdc->get_features_legacy = virtio_9p_get_features_legacy;
vdc->get_config = virtio_9p_get_config;
}
@@ -564,7 +564,8 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
aio_context_release(blk_get_aio_context(s->blk));
}
-static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
+static uint64_t virtio_blk_get_features_legacy(VirtIODevice *vdev,
+ uint64_t features)
{
VirtIOBlock *s = VIRTIO_BLK(vdev);
@@ -587,15 +588,8 @@ static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
return features;
}
-static uint64_t virtio_blk_get_features_rev(VirtIODevice *vdev,
- uint64_t features,
- unsigned int revision)
+static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
{
- if (revision == 0) {
- /* legacy */
- virtio_clear_feature(&features, VIRTIO_F_VERSION_1);
- return virtio_blk_get_features(vdev, features);
- }
/* virtio 1.0 or later */
virtio_clear_feature(&features, VIRTIO_BLK_F_SCSI);
virtio_clear_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
@@ -839,7 +833,7 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
vdc->get_config = virtio_blk_update_config;
vdc->set_config = virtio_blk_set_config;
vdc->get_features = virtio_blk_get_features;
- vdc->get_features_rev = virtio_blk_get_features_rev;
+ vdc->get_features_legacy = virtio_blk_get_features_legacy;
vdc->set_status = virtio_blk_set_status;
vdc->reset = virtio_blk_reset;
vdc->save = virtio_blk_save_device;
@@ -467,18 +467,29 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
{
}
-static uint64_t get_features(VirtIODevice *vdev, uint64_t features)
+static uint64_t get_features_common(VirtIOSerial *vser, uint64_t features)
{
- VirtIOSerial *vser;
-
- vser = VIRTIO_SERIAL(vdev);
-
if (vser->bus.max_nr_ports > 1) {
virtio_add_feature(&features, VIRTIO_CONSOLE_F_MULTIPORT);
}
return features;
}
+static uint64_t get_features(VirtIODevice *vdev, uint64_t features)
+{
+ VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
+
+ /* virtio_add_feature(&features, VIRTIO_F_VERSION_1); */
+ return get_features_common(vser, features);
+}
+
+static uint64_t get_features_legacy(VirtIODevice *vdev, uint64_t features)
+{
+ VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
+
+ return get_features_common(vser, features);
+}
+
/* Guest requested config info */
static void get_config(VirtIODevice *vdev, uint8_t *config_data)
{
@@ -1076,6 +1087,7 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data)
vdc->realize = virtio_serial_device_realize;
vdc->unrealize = virtio_serial_device_unrealize;
vdc->get_features = get_features;
+ vdc->get_features_legacy = get_features_legacy;
vdc->get_config = get_config;
vdc->set_status = set_status;
vdc->reset = vser_reset;
@@ -448,11 +448,9 @@ static void virtio_net_set_queues(VirtIONet *n)
static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
-static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
+static uint64_t virtio_net_get_features_common(VirtIONet *n,
+ uint64_t features)
{
- VirtIONet *n = VIRTIO_NET(vdev);
- NetClientState *nc = qemu_get_queue(n->nic);
-
virtio_add_feature(&features, VIRTIO_NET_F_MAC);
if (!peer_has_vnet_hdr(n)) {
@@ -472,6 +470,16 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
virtio_clear_feature(&features, VIRTIO_NET_F_HOST_UFO);
}
+ return features;
+}
+
+static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
+{
+ VirtIONet *n = VIRTIO_NET(vdev);
+ NetClientState *nc = qemu_get_queue(n->nic);
+
+ features = virtio_net_get_features_common(n, features);
+
if (!get_vhost_net(nc->peer)) {
virtio_add_feature(&features, VIRTIO_F_VERSION_1);
return features;
@@ -479,6 +487,20 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
return vhost_net_get_features(get_vhost_net(nc->peer), features);
}
+static uint64_t virtio_net_get_features_legacy(VirtIODevice *vdev,
+ uint64_t features)
+{
+ VirtIONet *n = VIRTIO_NET(vdev);
+ NetClientState *nc = qemu_get_queue(n->nic);
+
+ features = virtio_net_get_features_common(n, features);
+
+ if (!get_vhost_net(nc->peer)) {
+ return features;
+ }
+ return vhost_net_get_features(get_vhost_net(nc->peer), features);
+}
+
static uint64_t virtio_net_bad_features(VirtIODevice *vdev)
{
uint64_t features = 0;
@@ -1753,6 +1775,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
vdc->get_config = virtio_net_get_config;
vdc->set_config = virtio_net_set_config;
vdc->get_features = virtio_net_get_features;
+ vdc->get_features_legacy = virtio_net_get_features_legacy;
vdc->set_features = virtio_net_set_features;
vdc->bad_features = virtio_net_bad_features;
vdc->reset = virtio_net_reset;
@@ -128,8 +128,8 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
bus->dev_offs += dev_len;
- dev->host_features = virtio_bus_get_vdev_features(&dev->bus,
- dev->host_features);
+ dev->host_features =
+ virtio_bus_get_vdev_features_legacy(&dev->bus, dev->host_features);
s390_virtio_device_sync(dev);
s390_virtio_reset_idx(dev);
if (dev->qdev.hotplugged) {
@@ -693,16 +693,16 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
}
cpu_physical_memory_read(ccw.cda, &revinfo, len);
if (dev->revision >= 0 ||
- revinfo.revision > virtio_ccw_rev_max(dev)) {
+ revinfo.revision > virtio_ccw_rev_max(dev, vdev)) {
ret = -ENOSYS;
break;
}
ret = 0;
dev->revision = revinfo.revision;
/* Re-evaluate which features the device wants to offer. */
- dev->host_features =
- virtio_bus_get_vdev_features_rev(&dev->bus, dev->host_features,
- dev->revision >= 1 ? 1 : 0);
+ dev->host_features = dev->revision >= 1 ?
+ virtio_bus_get_vdev_features(&dev->bus, dev->host_features) :
+ virtio_bus_get_vdev_features_legacy(&dev->bus, dev->host_features);
break;
default:
ret = -ENOSYS;
@@ -718,7 +718,7 @@ static void virtio_sch_disable_cb(SubchDev *sch)
dev->revision = -1;
/* Reset the device's features to legacy. */
dev->host_features =
- virtio_bus_get_vdev_features_rev(&dev->bus, dev->host_features, 0);
+ virtio_bus_get_vdev_features_legacy(&dev->bus, dev->host_features);
}
static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
@@ -862,7 +862,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
/* All devices start in legacy mode. */
dev->host_features =
- virtio_bus_get_vdev_features_rev(&dev->bus, dev->host_features, 0);
+ virtio_bus_get_vdev_features_legacy(&dev->bus, dev->host_features);
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
parent->hotplugged, 1);
@@ -102,9 +102,9 @@ struct VirtioCcwDevice {
};
/* The maximum virtio revision we support. */
-static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev)
+static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev, VirtIODevice *vdev)
{
- return dev->host_features & (1ULL << VIRTIO_F_VERSION_1) ? 1 : 0;
+ return virtio_version_1_capable(vdev, dev->host_features) ? 1 : 0;
}
/* virtual css bus type */
@@ -630,6 +630,13 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
static uint64_t virtio_scsi_get_features(VirtIODevice *vdev,
uint64_t requested_features)
{
+ /* virtio_add_feature(&requested_features, VIRTIO_F_VERSION_1); */
+ return requested_features;
+}
+
+static uint64_t virtio_scsi_get_features_legacy(VirtIODevice *vdev,
+ uint64_t requested_features)
+{
return requested_features;
}
@@ -961,6 +968,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
vdc->unrealize = virtio_scsi_device_unrealize;
vdc->set_config = virtio_scsi_set_config;
vdc->get_features = virtio_scsi_get_features;
+ vdc->get_features_legacy = virtio_scsi_get_features_legacy;
vdc->reset = virtio_scsi_reset;
hc->plug = virtio_scsi_hotplug;
hc->unplug = virtio_scsi_hotunplug;
@@ -303,7 +303,8 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
}
}
-static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f)
+static uint64_t virtio_balloon_get_features_legacy(VirtIODevice *vdev,
+ uint64_t f)
{
f |= (1 << VIRTIO_BALLOON_F_STATS_VQ);
return f;
@@ -423,7 +424,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
vdc->unrealize = virtio_balloon_device_unrealize;
vdc->get_config = virtio_balloon_get_config;
vdc->set_config = virtio_balloon_set_config;
- vdc->get_features = virtio_balloon_get_features;
+ vdc->get_features_legacy = virtio_balloon_get_features_legacy;
vdc->save = virtio_balloon_save_device;
vdc->load = virtio_balloon_load_device;
}
@@ -97,26 +97,34 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
}
/* Get the features of the plugged device. */
-uint64_t virtio_bus_get_vdev_features_rev(VirtioBusState *bus,
- uint64_t requested_features,
- unsigned int revision)
+uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus,
+ uint64_t requested_features)
{
VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
assert(vdev != NULL);
k = VIRTIO_DEVICE_GET_CLASS(vdev);
- if (revision > 0 && k->get_features_rev) {
- return k->get_features_rev(vdev, requested_features, revision);
+ assert((k->get_features != NULL) || (k->get_features_legacy != NULL));
+ if (k->get_features) {
+ return k->get_features(vdev, requested_features);
}
- assert(k->get_features != NULL);
- return k->get_features(vdev, requested_features);
+ /* ensure version_1 is cleared on unsupported devices */
+ virtio_clear_feature(&requested_features, VIRTIO_F_VERSION_1);
+ return k->get_features_legacy(vdev, requested_features);
}
-uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus,
- uint64_t requested_features)
+uint64_t virtio_bus_get_vdev_features_legacy(VirtioBusState *bus,
+ uint64_t requested_features)
{
- return virtio_bus_get_vdev_features_rev(bus, requested_features, 0);
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ VirtioDeviceClass *k;
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
+ assert(k->get_features_legacy != NULL);
+ virtio_clear_feature(&requested_features, VIRTIO_F_VERSION_1);
+ return k->get_features_legacy(vdev, requested_features);
}
/* Get bad features of the plugged device. */
@@ -353,8 +353,8 @@ static void virtio_mmio_device_plugged(DeviceState *opaque)
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
- proxy->host_features = virtio_bus_get_vdev_features(&proxy->bus,
- proxy->host_features);
+ proxy->host_features =
+ virtio_bus_get_vdev_features_legacy(&proxy->bus, proxy->host_features);
}
static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
@@ -1414,8 +1414,8 @@ static void virtio_pci_device_plugged(DeviceState *d)
virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
virtio_add_feature(&proxy->host_features, VIRTIO_F_BAD_FEATURE);
- proxy->host_features = virtio_bus_get_vdev_features(bus,
- proxy->host_features);
+ proxy->host_features =
+ virtio_bus_get_vdev_features_legacy(bus, proxy->host_features);
}
static void virtio_pci_device_unplugged(DeviceState *d)
@@ -101,6 +101,12 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
static uint64_t get_features(VirtIODevice *vdev, uint64_t f)
{
+ /* virtio_add_feature(&f, VIRTIO_F_VERSION_1); */
+ return f;
+}
+
+static uint64_t get_features_legacy(VirtIODevice *vdev, uint64_t f)
+{
return f;
}
@@ -233,6 +239,7 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
vdc->realize = virtio_rng_device_realize;
vdc->unrealize = virtio_rng_device_unrealize;
vdc->get_features = get_features;
+ vdc->get_features_legacy = get_features_legacy;
}
static void virtio_rng_initfn(Object *obj)
@@ -1122,6 +1122,18 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val)
return __virtio_set_features(vdev, val);
}
+bool virtio_version_1_capable(VirtIODevice *vdev, uint64_t host_features)
+{
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+ uint64_t features;
+
+ if (!k->get_features) {
+ return 0;
+ }
+ features = k->get_features(vdev, host_features);
+ return __virtio_has_feature(features, VIRTIO_F_VERSION_1) ? 1 : 0;
+}
+
int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
{
int i, ret;
@@ -84,9 +84,8 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus);
/* Get the features of the plugged device. */
uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus,
uint64_t requested_features);
-uint64_t virtio_bus_get_vdev_features_rev(VirtioBusState *bus,
- uint64_t requested_features,
- unsigned int revision);
+uint64_t virtio_bus_get_vdev_features_legacy(VirtioBusState *bus,
+ uint64_t requested_features);
/* Get bad features of the plugged device. */
uint64_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus);
/* Get config of the plugged device. */
@@ -148,9 +148,8 @@ typedef struct VirtioDeviceClass {
DeviceRealize realize;
DeviceUnrealize unrealize;
uint64_t (*get_features)(VirtIODevice *vdev, uint64_t requested_features);
- uint64_t (*get_features_rev)(VirtIODevice *vdev,
- uint64_t requested_features,
- unsigned int revision);
+ uint64_t (*get_features_legacy)(VirtIODevice *vdev,
+ uint64_t requested_features);
uint64_t (*bad_features)(VirtIODevice *vdev);
void (*set_features)(VirtIODevice *vdev, uint64_t val);
int (*validate_features)(VirtIODevice *vdev);
@@ -248,6 +247,7 @@ int 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, uint64_t val);
+bool virtio_version_1_capable(VirtIODevice *vdev, uint64_t host_features);
/* Base devices. */
typedef struct VirtIOBlkConf VirtIOBlkConf;
Use a "legacy features" instead of a "revision specific" callback. Updates "virtio: support revision-specific features" and "virtio-blk: revision specific feature bits" as currently in git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git virtio-1.0 Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> --- hw/9pfs/virtio-9p-device.c | 5 +++-- hw/block/virtio-blk.c | 14 ++++---------- hw/char/virtio-serial-bus.c | 22 +++++++++++++++++----- hw/net/virtio-net.c | 31 +++++++++++++++++++++++++++---- hw/s390x/s390-virtio-bus.c | 4 ++-- hw/s390x/virtio-ccw.c | 12 ++++++------ hw/s390x/virtio-ccw.h | 4 ++-- hw/scsi/virtio-scsi.c | 8 ++++++++ hw/virtio/virtio-balloon.c | 5 +++-- hw/virtio/virtio-bus.c | 28 ++++++++++++++++++---------- hw/virtio/virtio-mmio.c | 4 ++-- hw/virtio/virtio-pci.c | 4 ++-- hw/virtio/virtio-rng.c | 7 +++++++ hw/virtio/virtio.c | 12 ++++++++++++ include/hw/virtio/virtio-bus.h | 5 ++--- include/hw/virtio/virtio.h | 6 +++--- 16 files changed, 118 insertions(+), 53 deletions(-)