Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 00/19] qemu: towards virtio-1 host support
Another iteration of virtio-1 patches for qemu, as always available on git://github.com/cohuck/qemu virtio-1 This one seems to work together with the current vhost-next patches (well, I can ping :) Changes from v4: - add helpers for feature bit manipulation and checking - use 64 bit feature bits instead of 32 bit arrays - infrastructure to allow devices to offer different sets of feature bits for legacy and standard devices - several fixes (mainly regarding, you guessed it, feature bits) Cornelia Huck (16): virtio: cull virtio_bus_set_vdev_features virtio: feature bit manipulation helpers virtio: add feature checking helpers virtio: support more feature bits virtio: endianness checks for virtio 1.0 devices virtio: allow virtio-1 queue layout dataplane: allow virtio-1 devices s390x/virtio-ccw: support virtio-1 set_vq format virtio: disallow late feature changes for virtio-1 virtio: allow to fail setting status s390x/virtio-ccw: enable virtio 1.0 virtio-net: no writeable mac for virtio-1 virtio-net: support longer header virtio-net: enable virtio 1.0 virtio: support revision-specific features virtio-blk: revision specific feature bits Thomas Huth (3): linux-headers/virtio_config: Update with VIRTIO_F_VERSION_1 s390x/css: Add a callback for when subchannel gets disabled s390x/virtio-ccw: add virtio set-revision call hw/9pfs/virtio-9p-device.c | 4 +- hw/block/dataplane/virtio-blk.c | 4 +- hw/block/virtio-blk.c | 44 +++-- hw/char/virtio-serial-bus.c | 6 +- hw/net/virtio-net.c | 100 ++++++----- hw/s390x/css.c | 12 ++ hw/s390x/css.h | 1 + hw/s390x/s390-virtio-bus.c | 3 +- hw/s390x/s390-virtio-bus.h | 2 +- hw/s390x/virtio-ccw.c | 235 ++++++++++++++++++------- hw/s390x/virtio-ccw.h | 8 +- hw/scsi/vhost-scsi.c | 3 +- hw/scsi/virtio-scsi-dataplane.c | 2 +- hw/scsi/virtio-scsi.c | 12 +- hw/virtio/Makefile.objs | 2 +- hw/virtio/dataplane/Makefile.objs | 2 +- hw/virtio/dataplane/vring.c | 96 +++++----- hw/virtio/virtio-balloon.c | 4 +- hw/virtio/virtio-bus.c | 24 ++- hw/virtio/virtio-mmio.c | 6 +- hw/virtio/virtio-pci.c | 7 +- hw/virtio/virtio-pci.h | 2 +- hw/virtio/virtio-rng.c | 2 +- hw/virtio/virtio.c | 83 +++++++-- include/hw/qdev-properties.h | 11 ++ include/hw/virtio/dataplane/vring-accessors.h | 75 ++++++++ include/hw/virtio/dataplane/vring.h | 14 +- include/hw/virtio/virtio-access.h | 4 + include/hw/virtio/virtio-bus.h | 14 +- include/hw/virtio/virtio-net.h | 46 ++--- include/hw/virtio/virtio-scsi.h | 6 +- include/hw/virtio/virtio.h | 61 +++++-- linux-headers/linux/virtio_config.h | 3 + 33 files changed, 625 insertions(+), 273 deletions(-) create mode 100644 include/hw/virtio/dataplane/vring-accessors.h -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 01/19] linux-headers/virtio_config: Update with VIRTIO_F_VERSION_1
From: Thomas Huth <thuth at linux.vnet.ibm.com> Add the new VIRTIO_F_VERSION_1 definition to the virtio_config.h linux header. Signed-off-by: Thomas Huth <thuth at linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- linux-headers/linux/virtio_config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h index 75dc20b..16aa289 100644 --- a/linux-headers/linux/virtio_config.h +++ b/linux-headers/linux/virtio_config.h @@ -54,4 +54,7 @@ /* Can the device handle any descriptor layout? */ #define VIRTIO_F_ANY_LAYOUT 27 +/* v1.0 compliant. */ +#define VIRTIO_F_VERSION_1 32 + #endif /* _LINUX_VIRTIO_CONFIG_H */ -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 02/19] virtio: cull virtio_bus_set_vdev_features
The only user of this function was virtio-ccw, and it should use virtio_set_features() like everybody else: We need to make sure that bad features are masked out properly, which this function did not do. Reviewed-by: Thomas Huth <thuth at linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/s390x/virtio-ccw.c | 3 +-- hw/virtio/virtio-bus.c | 14 -------------- include/hw/virtio/virtio-bus.h | 3 --- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index ea236c9..84f17bc 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -400,8 +400,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ccw.cda + sizeof(features.features)); features.features = ldl_le_phys(&address_space_memory, ccw.cda); if (features.index < ARRAY_SIZE(dev->host_features)) { - virtio_bus_set_vdev_features(&dev->bus, features.features); - vdev->guest_features = features.features; + virtio_set_features(vdev, features.features); } else { /* * If the guest supports more feature bits, assert that it diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index eb77019..a8ffa07 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -109,20 +109,6 @@ uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, return k->get_features(vdev, requested_features); } -/* Set the features of the plugged device. */ -void virtio_bus_set_vdev_features(VirtioBusState *bus, - uint32_t requested_features) -{ - VirtIODevice *vdev = virtio_bus_get_device(bus); - VirtioDeviceClass *k; - - assert(vdev != NULL); - k = VIRTIO_DEVICE_GET_CLASS(vdev); - if (k->set_features != NULL) { - k->set_features(vdev, requested_features); - } -} - /* Get bad features of the plugged device. */ uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus) { diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h index 0756545..0d2e7b4 100644 --- a/include/hw/virtio/virtio-bus.h +++ b/include/hw/virtio/virtio-bus.h @@ -84,9 +84,6 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus); /* Get the features of the plugged device. */ uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, uint32_t requested_features); -/* Set the features of the plugged device. */ -void virtio_bus_set_vdev_features(VirtioBusState *bus, - uint32_t requested_features); /* Get bad features of the plugged device. */ uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); /* Get config of the plugged device. */ -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 03/19] virtio: feature bit manipulation helpers
Add virtio_{add,clear}_feature helper functions for manipulating a feature bits variable. This has some benefits over open coding: - add check that the bit is in a sane range - make it obvious at a glance what is going on - have a central point to change when we want to extend feature bits Convert existing code manipulating features to use the new helpers. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/9pfs/virtio-9p-device.c | 2 +- hw/block/virtio-blk.c | 16 ++++++++-------- hw/char/virtio-serial-bus.c | 2 +- hw/net/virtio-net.c | 34 +++++++++++++++++----------------- hw/s390x/virtio-ccw.c | 4 ++-- hw/virtio/virtio-mmio.c | 2 +- hw/virtio/virtio-pci.c | 4 ++-- include/hw/virtio/virtio.h | 12 ++++++++++++ 8 files changed, 44 insertions(+), 32 deletions(-) diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 2572747..30492ec 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -23,7 +23,7 @@ static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) { - features |= 1 << VIRTIO_9P_MOUNT_TAG; + virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG); return features; } diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index b19b102..3f76e2a 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -568,20 +568,20 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) { VirtIOBlock *s = VIRTIO_BLK(vdev); - features |= (1 << VIRTIO_BLK_F_SEG_MAX); - features |= (1 << VIRTIO_BLK_F_GEOMETRY); - features |= (1 << VIRTIO_BLK_F_TOPOLOGY); - features |= (1 << VIRTIO_BLK_F_BLK_SIZE); - features |= (1 << VIRTIO_BLK_F_SCSI); + virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX); + virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY); + virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY); + virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE); + virtio_add_feature(&features, VIRTIO_BLK_F_SCSI); if (s->conf.config_wce) { - features |= (1 << VIRTIO_BLK_F_CONFIG_WCE); + virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE); } if (blk_enable_write_cache(s->blk)) { - features |= (1 << VIRTIO_BLK_F_WCE); + virtio_add_feature(&features, VIRTIO_BLK_F_WCE); } if (blk_is_read_only(s->blk)) { - features |= 1 << VIRTIO_BLK_F_RO; + virtio_add_feature(&features, VIRTIO_BLK_F_RO); } return features; diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index a7b1b68..0f637db 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -474,7 +474,7 @@ static uint32_t get_features(VirtIODevice *vdev, uint32_t features) vser = VIRTIO_SERIAL(vdev); if (vser->bus.max_nr_ports > 1) { - features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT); + virtio_add_feature(&features, VIRTIO_CONSOLE_F_MULTIPORT); } return features; } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index e574bd4..f1aa100 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -446,23 +446,23 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) VirtIONet *n = VIRTIO_NET(vdev); NetClientState *nc = qemu_get_queue(n->nic); - features |= (1 << VIRTIO_NET_F_MAC); + virtio_add_feature(&features, VIRTIO_NET_F_MAC); if (!peer_has_vnet_hdr(n)) { - 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); + virtio_clear_feature(&features, VIRTIO_NET_F_CSUM); + virtio_clear_feature(&features, VIRTIO_NET_F_HOST_TSO4); + virtio_clear_feature(&features, VIRTIO_NET_F_HOST_TSO6); + virtio_clear_feature(&features, 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); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_CSUM); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO4); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO6); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ECN); } if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) { - features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO); - features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_UFO); + virtio_clear_feature(&features, VIRTIO_NET_F_HOST_UFO); } if (!get_vhost_net(nc->peer)) { @@ -477,11 +477,11 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev) /* 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_CSUM); - features |= (1 << VIRTIO_NET_F_HOST_TSO4); - features |= (1 << VIRTIO_NET_F_HOST_TSO6); - features |= (1 << VIRTIO_NET_F_HOST_ECN); + virtio_add_feature(&features, VIRTIO_NET_F_MAC); + virtio_add_feature(&features, VIRTIO_NET_F_CSUM); + virtio_add_feature(&features, VIRTIO_NET_F_HOST_TSO4); + virtio_add_feature(&features, VIRTIO_NET_F_HOST_TSO6); + virtio_add_feature(&features, VIRTIO_NET_F_HOST_ECN); return features; } @@ -1560,7 +1560,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features) { int i, config_size = 0; - host_features |= (1 << VIRTIO_NET_F_MAC); + virtio_add_feature(&host_features, VIRTIO_NET_F_MAC); for (i = 0; feature_sizes[i].flags != 0; i++) { if (host_features & feature_sizes[i].flags) { config_size = MAX(feature_sizes[i].end, config_size); diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 84f17bc..3fee4aa 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -743,8 +743,8 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus, dev->host_features[0]); - dev->host_features[0] |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; - dev->host_features[0] |= 0x1 << VIRTIO_F_BAD_FEATURE; + virtio_add_feature(&dev->host_features[0], VIRTIO_F_NOTIFY_ON_EMPTY); + virtio_add_feature(&dev->host_features[0], VIRTIO_F_BAD_FEATURE); css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, parent->hotplugged, 1); diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 2450c13..10123f3 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -349,7 +349,7 @@ static void virtio_mmio_device_plugged(DeviceState *opaque) { VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque); - proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY); + virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY); proxy->host_features = virtio_bus_get_vdev_features(&proxy->bus, proxy->host_features); } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index dde1d73..e7969bf 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -996,8 +996,8 @@ static void virtio_pci_device_plugged(DeviceState *d) proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; } - proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; - proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE; + 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); } diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 0726d76..2fede2e 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -266,6 +266,18 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, void virtio_queue_notify_vq(VirtQueue *vq); void virtio_irq(VirtQueue *vq); +static inline void virtio_add_feature(uint32_t *features, unsigned int fbit) +{ + assert(fbit < 32); + *features |= (1 << fbit); +} + +static inline void virtio_clear_feature(uint32_t *features, unsigned int fbit) +{ + assert(fbit < 32); + *features &= ~(1 << fbit); +} + static inline bool virtio_is_big_endian(VirtIODevice *vdev) { assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 04/19] virtio: add feature checking helpers
Add a helper function for checking whether a bit is set in the guest features for a vdev as well as one that works on a feature bit set. Convert code that open-coded this: It cleans up the code and makes it easier to extend the guest feature bits. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/block/virtio-blk.c | 7 ++----- hw/char/virtio-serial-bus.c | 2 +- hw/net/virtio-net.c | 23 +++++++++++++---------- hw/scsi/virtio-scsi.c | 8 ++++---- hw/virtio/dataplane/vring.c | 10 +++++----- hw/virtio/virtio-balloon.c | 2 +- hw/virtio/virtio.c | 10 +++++----- include/hw/virtio/virtio.h | 11 +++++++++++ 8 files changed, 42 insertions(+), 31 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 3f76e2a..27f263a 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -590,7 +590,6 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) { VirtIOBlock *s = VIRTIO_BLK(vdev); - uint32_t features; if (s->dataplane && !(status & (VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK))) { @@ -601,8 +600,6 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) return; } - features = vdev->guest_features; - /* A guest that supports VIRTIO_BLK_F_CONFIG_WCE must be able to send * cache flushes. Thus, the "auto writethrough" behavior is never * necessary for guests that support the VIRTIO_BLK_F_CONFIG_WCE feature. @@ -618,10 +615,10 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) * * s->blk would erroneously be placed in writethrough mode. */ - if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) { + if (!virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) { aio_context_acquire(blk_get_aio_context(s->blk)); blk_set_enable_write_cache(s->blk, - !!(features & (1 << VIRTIO_BLK_F_WCE))); + virtio_has_feature(vdev, VIRTIO_BLK_F_WCE)); aio_context_release(blk_get_aio_context(s->blk)); } } diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 0f637db..d49883f 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -75,7 +75,7 @@ static VirtIOSerialPort *find_port_by_name(char *name) static bool use_multiport(VirtIOSerial *vser) { VirtIODevice *vdev = VIRTIO_DEVICE(vser); - return vdev->guest_features & (1 << VIRTIO_CONSOLE_F_MULTIPORT); + return virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT); } static size_t write_to_port(VirtIOSerialPort *port, diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index f1aa100..9f3c58a 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -86,7 +86,7 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) memcpy(&netcfg, config, n->config_size); - if (!(vdev->guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) && + if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) && memcmp(netcfg.mac, n->mac, ETH_ALEN)) { memcpy(n->mac, netcfg.mac, ETH_ALEN); qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); @@ -305,7 +305,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) info->multicast_table = str_list; info->vlan_table = get_vlan_table(n); - if (!((1 << VIRTIO_NET_F_CTRL_VLAN) & vdev->guest_features)) { + if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) { info->vlan = RX_STATE_ALL; } else if (!info->vlan_table) { info->vlan = RX_STATE_NONE; @@ -519,9 +519,12 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) VirtIONet *n = VIRTIO_NET(vdev); int i; - virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ))); + virtio_net_set_multiqueue(n, + __virtio_has_feature(features, VIRTIO_NET_F_MQ)); - virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF))); + virtio_net_set_mrg_rx_bufs(n, + __virtio_has_feature(features, + VIRTIO_NET_F_MRG_RXBUF)); if (n->has_vnet_hdr) { n->curr_guest_offloads @@ -538,7 +541,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) vhost_net_ack_features(get_vhost_net(nc->peer), features); } - if ((1 << VIRTIO_NET_F_CTRL_VLAN) & features) { + if (__virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) { memset(n->vlans, 0, MAX_VLAN >> 3); } else { memset(n->vlans, 0xff, MAX_VLAN >> 3); @@ -585,7 +588,7 @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd, uint64_t offloads; size_t s; - if (!((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features)) { + if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { return VIRTIO_NET_ERR; } @@ -1378,7 +1381,7 @@ static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f) } } - if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) { + if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { qemu_put_be64(f, n->curr_guest_offloads); } } @@ -1486,7 +1489,7 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, } } - if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) { + if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { n->curr_guest_offloads = qemu_get_be64(f); } else { n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); @@ -1513,8 +1516,8 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, qemu_get_subqueue(n->nic, i)->link_down = link_down; } - if (vdev->guest_features & (0x1 << VIRTIO_NET_F_GUEST_ANNOUNCE) && - vdev->guest_features & (0x1 << VIRTIO_NET_F_CTRL_VQ)) { + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) && + virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) { n->announce_counter = SELF_ANNOUNCE_ROUNDS; timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)); } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index ef48550..56c92fb 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -144,7 +144,7 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req, * * TODO: always disable this workaround for virtio 1.0 devices. */ - if ((vdev->guest_features & VIRTIO_F_ANY_LAYOUT) == 0) { + if (!virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) { req_size = req->elem.out_sg[0].iov_len; resp_size = req->elem.in_sg[0].iov_len; } @@ -748,7 +748,7 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); VirtIODevice *vdev = VIRTIO_DEVICE(s); - if (((vdev->guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && + if (virtio_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) && dev->type != TYPE_ROM) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE, sense.asc | (sense.ascq << 8)); @@ -769,7 +769,7 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, blk_op_block_all(sd->conf.blk, s->blocker); } - if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { + if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); @@ -783,7 +783,7 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, VirtIOSCSI *s = VIRTIO_SCSI(vdev); SCSIDevice *sd = SCSI_DEVICE(dev); - if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { + if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 61f6d83..6e283fc 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -103,7 +103,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n) /* Disable guest->host notifies */ void vring_disable_notification(VirtIODevice *vdev, Vring *vring) { - if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) { + if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring->vr.used->flags |= VRING_USED_F_NO_NOTIFY; } } @@ -114,7 +114,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring) */ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring) { - if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = vring->vr.avail->idx; } else { vring->vr.used->flags &= ~VRING_USED_F_NO_NOTIFY; @@ -133,12 +133,12 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) * interrupts. */ smp_mb(); - if ((vdev->guest_features & VIRTIO_F_NOTIFY_ON_EMPTY) && + if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && unlikely(vring->vr.avail->idx == vring->last_avail_idx)) { return true; } - if (!(vdev->guest_features & VIRTIO_RING_F_EVENT_IDX)) { + if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { return !(vring->vr.avail->flags & VRING_AVAIL_F_NO_INTERRUPT); } old = vring->signalled_used; @@ -388,7 +388,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* On success, increment avail index. */ vring->last_avail_idx++; - if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = vring->last_avail_idx; } diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 7bfbb75..21e449a 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -69,7 +69,7 @@ static inline void reset_stats(VirtIOBalloon *dev) static bool balloon_stats_supported(const VirtIOBalloon *s) { VirtIODevice *vdev = VIRTIO_DEVICE(s); - return vdev->guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ); + return virtio_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ); } static bool balloon_stats_enabled(const VirtIOBalloon *s) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 013979a..5814433 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -217,7 +217,7 @@ static inline void vring_avail_event(VirtQueue *vq, uint16_t val) void virtio_queue_set_notification(VirtQueue *vq, int enable) { vq->notification = enable; - if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(vq, vring_avail_idx(vq)); } else if (enable) { vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY); @@ -468,7 +468,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) max = vq->vring.num; i = head = virtqueue_get_head(vq, vq->last_avail_idx++); - if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(vq, vq->last_avail_idx); } @@ -839,12 +839,12 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq) /* We need to expose used array entries before checking used event. */ smp_mb(); /* Always notify when queue is empty (when feature acknowledge) */ - if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) && - !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) { + if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && + !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) { return true; } - if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) { + if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT); } diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 2fede2e..f6c0379 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -278,6 +278,17 @@ static inline void virtio_clear_feature(uint32_t *features, unsigned int fbit) *features &= ~(1 << fbit); } +static inline bool __virtio_has_feature(uint32_t features, unsigned int fbit) +{ + assert(fbit < 32); + return !!(features & (1 << fbit)); +} + +static inline bool virtio_has_feature(VirtIODevice *vdev, unsigned int fbit) +{ + return __virtio_has_feature(vdev->guest_features, fbit); +} + static inline bool virtio_is_big_endian(VirtIODevice *vdev) { assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 05/19] virtio: support more feature bits
With virtio-1, we support more than 32 feature bits. Let's extend both host and guest features to 64, which should suffice for a while. vhost and migration have been ignored for now. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/9pfs/virtio-9p-device.c | 2 +- hw/block/virtio-blk.c | 2 +- hw/char/virtio-serial-bus.c | 2 +- hw/net/virtio-net.c | 22 +++++++++---------- hw/s390x/s390-virtio-bus.c | 3 ++- hw/s390x/s390-virtio-bus.h | 2 +- hw/s390x/virtio-ccw.c | 40 ++++++++++++++++++++-------------- hw/s390x/virtio-ccw.h | 5 +---- hw/scsi/vhost-scsi.c | 3 +-- hw/scsi/virtio-scsi.c | 4 ++-- hw/virtio/virtio-balloon.c | 2 +- hw/virtio/virtio-bus.c | 6 ++--- hw/virtio/virtio-mmio.c | 4 ++-- hw/virtio/virtio-pci.c | 3 ++- hw/virtio/virtio-pci.h | 2 +- hw/virtio/virtio-rng.c | 2 +- hw/virtio/virtio.c | 13 ++++++----- include/hw/qdev-properties.h | 11 ++++++++++ include/hw/virtio/virtio-bus.h | 8 +++---- include/hw/virtio/virtio-net.h | 46 +++++++++++++++++++-------------------- include/hw/virtio/virtio-scsi.h | 6 ++--- include/hw/virtio/virtio.h | 38 ++++++++++++++++++-------------- 22 files changed, 126 insertions(+), 100 deletions(-) diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 30492ec..60f9ff9 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -21,7 +21,7 @@ #include "virtio-9p-coth.h" #include "hw/virtio/virtio-access.h" -static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) +static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features) { virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG); return features; diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 27f263a..9cfae66 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -564,7 +564,7 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config) aio_context_release(blk_get_aio_context(s->blk)); } -static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) +static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features) { VirtIOBlock *s = VIRTIO_BLK(vdev); diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index d49883f..2d2ed9c 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -467,7 +467,7 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq) { } -static uint32_t get_features(VirtIODevice *vdev, uint32_t features) +static uint64_t get_features(VirtIODevice *vdev, uint64_t features) { VirtIOSerial *vser; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9f3c58a..d6d1b98 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -38,16 +38,16 @@ (offsetof(container, field) + sizeof(((container *)0)->field)) typedef struct VirtIOFeature { - uint32_t flags; + uint64_t flags; size_t end; } VirtIOFeature; static VirtIOFeature feature_sizes[] = { - {.flags = 1 << VIRTIO_NET_F_MAC, + {.flags = 1ULL << VIRTIO_NET_F_MAC, .end = endof(struct virtio_net_config, mac)}, - {.flags = 1 << VIRTIO_NET_F_STATUS, + {.flags = 1ULL << VIRTIO_NET_F_STATUS, .end = endof(struct virtio_net_config, status)}, - {.flags = 1 << VIRTIO_NET_F_MQ, + {.flags = 1ULL << VIRTIO_NET_F_MQ, .end = endof(struct virtio_net_config, max_virtqueue_pairs)}, {} }; @@ -441,7 +441,7 @@ static void virtio_net_set_queues(VirtIONet *n) static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue); -static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t 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); @@ -471,9 +471,9 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) return vhost_net_get_features(get_vhost_net(nc->peer), features); } -static uint32_t virtio_net_bad_features(VirtIODevice *vdev) +static uint64_t virtio_net_bad_features(VirtIODevice *vdev) { - uint32_t features = 0; + uint64_t features = 0; /* Linux kernel 2.6.25. It understood MAC (as everyone must), * but also these: */ @@ -496,7 +496,7 @@ static void virtio_net_apply_guest_offloads(VirtIONet *n) !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO))); } -static uint64_t virtio_net_guest_offloads_by_features(uint32_t features) +static uint64_t virtio_net_guest_offloads_by_features(uint64_t features) { static const uint64_t guest_offloads_mask (1ULL << VIRTIO_NET_F_GUEST_CSUM) | @@ -514,7 +514,7 @@ static inline uint64_t virtio_net_supported_guest_offloads(VirtIONet *n) return virtio_net_guest_offloads_by_features(vdev->guest_features); } -static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) +static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) { VirtIONet *n = VIRTIO_NET(vdev); int i; @@ -1036,7 +1036,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t return -1; error_report("virtio-net unexpected empty queue: " "i %zd mergeable %d offset %zd, size %zd, " - "guest hdr len %zd, host hdr len %zd guest features 0x%x", + "guest hdr len %zd, host hdr len %zd guest features 0x%lx", i, n->mergeable_rx_bufs, offset, size, n->guest_hdr_len, n->host_hdr_len, vdev->guest_features); exit(1); @@ -1560,7 +1560,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, vdev, idx, mask); } -void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features) +void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features) { int i, config_size = 0; virtio_add_feature(&host_features, VIRTIO_NET_F_MAC); diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 39dc201..3635909 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -490,9 +490,10 @@ static void virtio_s390_notify(DeviceState *d, uint16_t vector) s390_virtio_irq(0, token); } -static unsigned virtio_s390_get_features(DeviceState *d) +static uint64_t virtio_s390_get_features(DeviceState *d) { VirtIOS390Device *dev = to_virtio_s390_device(d); + return dev->host_features; } diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h index ffd0df7..e49d4ba 100644 --- a/hw/s390x/s390-virtio-bus.h +++ b/hw/s390x/s390-virtio-bus.h @@ -90,7 +90,7 @@ struct VirtIOS390Device { ram_addr_t feat_offs; uint8_t feat_len; VirtIODevice *vdev; - uint32_t host_features; + uint64_t host_features; VirtioBusState bus; }; diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 3fee4aa..e434718 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -371,8 +371,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) } else { features.index = ldub_phys(&address_space_memory, ccw.cda + sizeof(features.features)); - if (features.index < ARRAY_SIZE(dev->host_features)) { - features.features = dev->host_features[features.index]; + if (features.index == 0) { + features.features = (uint32_t)dev->host_features; + } else if (features.index == 1) { + features.features = (uint32_t)(dev->host_features >> 32); } else { /* Return zeroes if the guest supports more feature bits. */ features.features = 0; @@ -399,8 +401,14 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) features.index = ldub_phys(&address_space_memory, ccw.cda + sizeof(features.features)); features.features = ldl_le_phys(&address_space_memory, ccw.cda); - if (features.index < ARRAY_SIZE(dev->host_features)) { - virtio_set_features(vdev, features.features); + if (features.index == 0) { + virtio_set_features(vdev, + (vdev->guest_features & 0xffffffff00000000) | + features.features); + } else if (features.index == 1) { + virtio_set_features(vdev, + (vdev->guest_features & 0x00000000ffffffff) | + ((uint64_t)features.features << 32)); } else { /* * If the guest supports more feature bits, assert that it @@ -739,12 +747,13 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) sch->id.cu_type = VIRTIO_CCW_CU_TYPE; sch->id.cu_model = vdev->device_id; - /* Only the first 32 feature bits are used. */ - dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus, - dev->host_features[0]); + /* Set default feature bits that are offered by the host. */ + dev->host_features = 0; + virtio_add_feature(&dev->host_features, VIRTIO_F_NOTIFY_ON_EMPTY); + virtio_add_feature(&dev->host_features, VIRTIO_F_BAD_FEATURE); - virtio_add_feature(&dev->host_features[0], VIRTIO_F_NOTIFY_ON_EMPTY); - virtio_add_feature(&dev->host_features[0], VIRTIO_F_BAD_FEATURE); + dev->host_features = virtio_bus_get_vdev_features(&dev->bus, + dev->host_features); css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, parent->hotplugged, 1); @@ -777,7 +786,7 @@ static int virtio_ccw_net_init(VirtioCcwDevice *ccw_dev) VirtIONetCcw *dev = VIRTIO_NET_CCW(ccw_dev); DeviceState *vdev = DEVICE(&dev->vdev); - virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]); + virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features); virtio_net_set_netclient_name(&dev->vdev, qdev->id, object_get_typename(OBJECT(qdev))); qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); @@ -1063,12 +1072,11 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector) } } -static unsigned virtio_ccw_get_features(DeviceState *d) +static uint64_t virtio_ccw_get_features(DeviceState *d) { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); - /* Only the first 32 feature bits are used. */ - return dev->host_features[0]; + return dev->host_features; } static void virtio_ccw_reset(DeviceState *d) @@ -1381,7 +1389,7 @@ static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f) static Property virtio_ccw_net_properties[] = { DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), - DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]), + DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_END_OF_LIST(), @@ -1486,7 +1494,7 @@ static const TypeInfo virtio_ccw_balloon = { static Property virtio_ccw_scsi_properties[] = { DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), - DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]), + DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_END_OF_LIST(), @@ -1614,7 +1622,7 @@ static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev, } static Property virtio_ccw_properties[] = { - DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]), + DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 5a1f16e..9087f7a 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -68,9 +68,6 @@ typedef struct VirtIOCCWDeviceClass { int (*exit)(VirtioCcwDevice *dev); } VirtIOCCWDeviceClass; -/* Change here if we want to support more feature bits. */ -#define VIRTIO_CCW_FEATURE_SIZE 1 - /* Performance improves when virtqueue kick processing is decoupled from the * vcpu thread using ioeventfd for some devices. */ #define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1 @@ -88,7 +85,7 @@ struct VirtioCcwDevice { DeviceState parent_obj; SubchDev *sch; char *bus_id; - uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE]; + uint64_t host_features; VirtioBusState bus; bool ioeventfd_started; bool ioeventfd_disabled; diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 308b393..68e0489 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -150,8 +150,7 @@ static void vhost_scsi_stop(VHostSCSI *s) vhost_dev_disable_notifiers(&s->dev, vdev); } -static uint32_t vhost_scsi_get_features(VirtIODevice *vdev, - uint32_t features) +static uint64_t vhost_scsi_get_features(VirtIODevice *vdev, uint64_t features) { VHostSCSI *s = VHOST_SCSI(vdev); diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 56c92fb..fbac794 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -627,8 +627,8 @@ static void virtio_scsi_set_config(VirtIODevice *vdev, vs->cdb_size = virtio_ldl_p(vdev, &scsiconf->cdb_size); } -static uint32_t virtio_scsi_get_features(VirtIODevice *vdev, - uint32_t requested_features) +static uint64_t virtio_scsi_get_features(VirtIODevice *vdev, + uint64_t requested_features) { return requested_features; } diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 21e449a..d2d7c3e 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -303,7 +303,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, } } -static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f) +static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f) { f |= (1 << VIRTIO_BALLOON_F_STATS_VQ); return f; diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index a8ffa07..32e3fab 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -97,8 +97,8 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus) } /* Get the features of the plugged device. */ -uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, - uint32_t requested_features) +uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus, + uint64_t requested_features) { VirtIODevice *vdev = virtio_bus_get_device(bus); VirtioDeviceClass *k; @@ -110,7 +110,7 @@ uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, } /* Get bad features of the plugged device. */ -uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus) +uint64_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus) { VirtIODevice *vdev = virtio_bus_get_device(bus); VirtioDeviceClass *k; diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 10123f3..43b7e02 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -80,7 +80,7 @@ typedef struct { SysBusDevice parent_obj; MemoryRegion iomem; qemu_irq irq; - uint32_t host_features; + uint64_t host_features; /* Guest accessible state needing migration and reset */ uint32_t host_features_sel; uint32_t guest_features_sel; @@ -306,7 +306,7 @@ static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector) qemu_set_irq(proxy->irq, level); } -static unsigned int virtio_mmio_get_features(DeviceState *opaque) +static uint64_t virtio_mmio_get_features(DeviceState *opaque) { VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque); diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index e7969bf..7382705 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -478,9 +478,10 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, } } -static unsigned virtio_pci_get_features(DeviceState *d) +static uint64_t virtio_pci_get_features(DeviceState *d) { VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); + return proxy->host_features; } diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 8873b6d..85f102d 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -91,7 +91,7 @@ struct VirtIOPCIProxy { uint32_t flags; uint32_t class_code; uint32_t nvectors; - uint32_t host_features; + uint64_t host_features; bool ioeventfd_disabled; bool ioeventfd_started; VirtIOIRQFD *vector_irqfd; diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index 473c044..edd39cc 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -99,7 +99,7 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq) virtio_rng_process(vrng); } -static uint32_t get_features(VirtIODevice *vdev, uint32_t f) +static uint64_t get_features(VirtIODevice *vdev, uint64_t f) { return f; } diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 5814433..7f74ae5 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -593,6 +593,7 @@ void virtio_reset(void *opaque) } vdev->guest_features = 0; + vdev->queue_sel = 0; vdev->status = 0; vdev->isr = 0; @@ -924,7 +925,8 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) qemu_put_8s(f, &vdev->status); qemu_put_8s(f, &vdev->isr); qemu_put_be16s(f, &vdev->queue_sel); - qemu_put_be32s(f, &vdev->guest_features); + /* XXX features >= 32 */ + qemu_put_be32s(f, (uint32_t *)&vdev->guest_features); qemu_put_be32(f, vdev->config_len); qemu_put_buffer(f, vdev->config, vdev->config_len); @@ -958,12 +960,12 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) vmstate_save_state(f, &vmstate_virtio, vdev); } -int virtio_set_features(VirtIODevice *vdev, uint32_t val) +int virtio_set_features(VirtIODevice *vdev, uint64_t val) { BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); VirtioBusClass *vbusk = VIRTIO_BUS_GET_CLASS(qbus); VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - uint32_t supported_features = vbusk->get_features(qbus->parent); + uint64_t supported_features = vbusk->get_features(qbus->parent); bool bad = (val & ~supported_features) != 0; val &= supported_features; @@ -980,7 +982,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) int32_t config_len; uint32_t num; uint32_t features; - uint32_t supported_features; + uint64_t supported_features; BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); @@ -1005,9 +1007,10 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) } qemu_get_be32s(f, &features); + /* XXX features >= 32 */ if (virtio_set_features(vdev, features) < 0) { supported_features = k->get_features(qbus->parent); - error_report("Features 0x%x unsupported. Allowed features: 0x%x", + error_report("Features 0x%x unsupported. Allowed features: 0x%lx", features, supported_features); return -1; } diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 070006c..23d713b 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -51,6 +51,17 @@ extern PropertyInfo qdev_prop_arraylen; .defval = (bool)_defval, \ } +#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) { \ + .name = (_name), \ + .info = &(qdev_prop_bit), \ + .bitnr = (_bit), \ + .offset = offsetof(_state, _field) \ + + type_check(uint64_t,typeof_field(_state, _field)), \ + .qtype = QTYPE_QBOOL, \ + .defval = (bool)_defval, \ + } + + #define DEFINE_PROP_BOOL(_name, _state, _field, _defval) { \ .name = (_name), \ .info = &(qdev_prop_bool), \ diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h index 0d2e7b4..0a4dde1 100644 --- a/include/hw/virtio/virtio-bus.h +++ b/include/hw/virtio/virtio-bus.h @@ -47,7 +47,7 @@ typedef struct VirtioBusClass { int (*load_config)(DeviceState *d, QEMUFile *f); int (*load_queue)(DeviceState *d, int n, QEMUFile *f); int (*load_done)(DeviceState *d, QEMUFile *f); - unsigned (*get_features)(DeviceState *d); + uint64_t (*get_features)(DeviceState *d); bool (*query_guest_notifiers)(DeviceState *d); int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign); int (*set_host_notifier)(DeviceState *d, int n, bool assigned); @@ -82,10 +82,10 @@ uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus); /* Get the config_len field of the plugged device. */ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus); /* Get the features of the plugged device. */ -uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, - uint32_t requested_features); +uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus, + uint64_t requested_features); /* Get bad features of the plugged device. */ -uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); +uint64_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); /* Get config of the plugged device. */ void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config); /* Set config of the plugged device. */ diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 6ceb5aa..5c58b4b 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -258,35 +258,35 @@ struct virtio_net_ctrl_mq { #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 #define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ - DEFINE_PROP_BIT("any_layout", _state, _field, VIRTIO_F_ANY_LAYOUT, true), \ - 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("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("guest_announce", _state, _field, VIRTIO_NET_F_GUEST_ANNOUNCE, 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), \ - DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true), \ - DEFINE_PROP_BIT("ctrl_guest_offloads", _state, _field, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true), \ - DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, false) + DEFINE_PROP_BIT64("any_layout", _state, _field, VIRTIO_F_ANY_LAYOUT, true), \ + DEFINE_PROP_BIT64("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \ + DEFINE_PROP_BIT64("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \ + DEFINE_PROP_BIT64("gso", _state, _field, VIRTIO_NET_F_GSO, true), \ + DEFINE_PROP_BIT64("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \ + DEFINE_PROP_BIT64("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \ + DEFINE_PROP_BIT64("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \ + DEFINE_PROP_BIT64("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \ + DEFINE_PROP_BIT64("guest_announce", _state, _field, VIRTIO_NET_F_GUEST_ANNOUNCE, true), \ + DEFINE_PROP_BIT64("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \ + DEFINE_PROP_BIT64("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \ + DEFINE_PROP_BIT64("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \ + DEFINE_PROP_BIT64("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \ + DEFINE_PROP_BIT64("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \ + DEFINE_PROP_BIT64("status", _state, _field, VIRTIO_NET_F_STATUS, true), \ + DEFINE_PROP_BIT64("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \ + DEFINE_PROP_BIT64("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \ + DEFINE_PROP_BIT64("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \ + DEFINE_PROP_BIT64("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true), \ + DEFINE_PROP_BIT64("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true), \ + DEFINE_PROP_BIT64("ctrl_guest_offloads", _state, _field, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true), \ + DEFINE_PROP_BIT64("mq", _state, _field, VIRTIO_NET_F_MQ, false) #define DEFINE_VIRTIO_NET_PROPERTIES(_state, _field) \ DEFINE_PROP_UINT32("x-txtimer", _state, _field.txtimer, TX_TIMER_INTERVAL),\ DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST), \ DEFINE_PROP_STRING("tx", _state, _field.tx) -void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features); +void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features); void virtio_net_set_netclient_name(VirtIONet *n, const char *name, const char *type); diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index bf17cc9..f0c0a6e 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -253,11 +253,11 @@ QEMU_BUILD_BUG_ON(offsetof(VirtIOSCSIReq, req.cdb) ! DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128) #define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field) \ - DEFINE_PROP_BIT("any_layout", _state, _feature_field, \ + DEFINE_PROP_BIT64("any_layout", _state, _feature_field, \ VIRTIO_F_ANY_LAYOUT, true), \ - DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \ + DEFINE_PROP_BIT64("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \ true), \ - DEFINE_PROP_BIT("param_change", _state, _feature_field, \ + DEFINE_PROP_BIT64("param_change", _state, _feature_field, \ VIRTIO_SCSI_F_CHANGE, true) typedef void (*HandleOutput)(VirtIODevice *, VirtQueue *); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index f6c0379..08141c7 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -55,6 +55,12 @@ /* A guest should never accept this. It implies negotiation is broken. */ #define VIRTIO_F_BAD_FEATURE 30 +/* v1.0 compliant. */ +#define VIRTIO_F_VERSION_1 32 + +/* The highest feature bit that we support */ +#define VIRTIO_HIGHEST_FEATURE_BIT 32 + /* from Linux's linux/virtio_ring.h */ /* This marks a buffer as continuing via the next field. */ @@ -117,7 +123,7 @@ struct VirtIODevice uint8_t status; uint8_t isr; uint16_t queue_sel; - uint32_t guest_features; + uint64_t guest_features; size_t config_len; void *config; uint16_t config_vector; @@ -138,9 +144,9 @@ typedef struct VirtioDeviceClass { /* This is what a VirtioDevice must implement */ DeviceRealize realize; DeviceUnrealize unrealize; - uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features); - uint32_t (*bad_features)(VirtIODevice *vdev); - void (*set_features)(VirtIODevice *vdev, uint32_t val); + uint64_t (*get_features)(VirtIODevice *vdev, uint64_t requested_features); + uint64_t (*bad_features)(VirtIODevice *vdev); + void (*set_features)(VirtIODevice *vdev, uint64_t val); void (*get_config)(VirtIODevice *vdev, uint8_t *config); void (*set_config)(VirtIODevice *vdev, const uint8_t *config); void (*reset)(VirtIODevice *vdev); @@ -225,7 +231,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); void 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, uint32_t val); +int virtio_set_features(VirtIODevice *vdev, uint64_t val); /* Base devices. */ typedef struct VirtIOBlkConf VirtIOBlkConf; @@ -238,9 +244,9 @@ typedef struct VirtIOSCSIConf VirtIOSCSIConf; typedef struct VirtIORNGConf VirtIORNGConf; #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ - DEFINE_PROP_BIT("indirect_desc", _state, _field, \ + DEFINE_PROP_BIT64("indirect_desc", _state, _field, \ VIRTIO_RING_F_INDIRECT_DESC, true), \ - DEFINE_PROP_BIT("event_idx", _state, _field, \ + DEFINE_PROP_BIT64("event_idx", _state, _field, \ VIRTIO_RING_F_EVENT_IDX, true) hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n); @@ -266,22 +272,22 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, void virtio_queue_notify_vq(VirtQueue *vq); void virtio_irq(VirtQueue *vq); -static inline void virtio_add_feature(uint32_t *features, unsigned int fbit) +static inline void virtio_add_feature(uint64_t *features, unsigned int fbit) { - assert(fbit < 32); - *features |= (1 << fbit); + assert(fbit < 64); + *features |= (1ULL << fbit); } -static inline void virtio_clear_feature(uint32_t *features, unsigned int fbit) +static inline void virtio_clear_feature(uint64_t *features, unsigned int fbit) { - assert(fbit < 32); - *features &= ~(1 << fbit); + assert(fbit < 64); + *features &= ~(1ULL << fbit); } -static inline bool __virtio_has_feature(uint32_t features, unsigned int fbit) +static inline bool __virtio_has_feature(uint64_t features, unsigned int fbit) { - assert(fbit < 32); - return !!(features & (1 << fbit)); + assert(fbit < 64); + return !!(features & (1ULL << fbit)); } static inline bool virtio_has_feature(VirtIODevice *vdev, unsigned int fbit) -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 06/19] virtio: endianness checks for virtio 1.0 devices
Add code that checks for the VERSION_1 feature bit in order to make decisions about the device's endianness. This allows us to support transitional devices. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/virtio/virtio.c | 6 +++++- include/hw/virtio/virtio-access.h | 4 ++++ include/hw/virtio/virtio.h | 8 ++++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 7f74ae5..8f69ffa 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -881,7 +881,11 @@ static bool virtio_device_endian_needed(void *opaque) VirtIODevice *vdev = opaque; assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); - return vdev->device_endian != virtio_default_endian(); + if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + return vdev->device_endian != virtio_default_endian(); + } + /* Devices conforming to VIRTIO 1.0 or later are always LE. */ + return vdev->device_endian != VIRTIO_DEVICE_ENDIAN_LITTLE; } static const VMStateDescription vmstate_virtio_device_endian = { diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h index 46456fd..ee28c21 100644 --- a/include/hw/virtio/virtio-access.h +++ b/include/hw/virtio/virtio-access.h @@ -19,6 +19,10 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) { + if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + /* Devices conforming to VIRTIO 1.0 or later are always LE. */ + return false; + } #if defined(TARGET_IS_BIENDIAN) return virtio_is_big_endian(vdev); #elif defined(TARGET_WORDS_BIGENDIAN) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 08141c7..68c40db 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -297,7 +297,11 @@ static inline bool virtio_has_feature(VirtIODevice *vdev, unsigned int fbit) static inline bool virtio_is_big_endian(VirtIODevice *vdev) { - assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); - return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG; + if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); + return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG; + } + /* Devices conforming to VIRTIO 1.0 or later are always LE. */ + return false; } #endif -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 07/19] virtio: allow virtio-1 queue layout
For virtio-1 devices, we allow a more complex queue layout that doesn't require descriptor table and rings on a physically-contigous memory area: add virtio_queue_set_rings() to allow transports to set this up. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/virtio/virtio.c | 16 ++++++++++++++++ include/hw/virtio/virtio.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 8f69ffa..508dccf 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -96,6 +96,13 @@ static void virtqueue_init(VirtQueue *vq) { hwaddr pa = vq->pa; + if (pa == -1ULL) { + /* + * This is a virtio-1 style vq that has already been setup + * in virtio_queue_set. + */ + return; + } vq->vring.desc = pa; vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc); vq->vring.used = vring_align(vq->vring.avail + @@ -717,6 +724,15 @@ hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n) return vdev->vq[n].pa; } +void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, + hwaddr avail, hwaddr used) +{ + vdev->vq[n].pa = -1ULL; + vdev->vq[n].vring.desc = desc; + vdev->vq[n].vring.avail = avail; + vdev->vq[n].vring.used = used; +} + void virtio_queue_set_num(VirtIODevice *vdev, int n, int num) { /* Don't allow guest to flip queue between existent and diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 68c40db..80ee313 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -224,6 +224,8 @@ void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); void virtio_queue_set_num(VirtIODevice *vdev, int n, int num); int virtio_queue_get_num(VirtIODevice *vdev, int n); +void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, + hwaddr avail, hwaddr used); void virtio_queue_set_align(VirtIODevice *vdev, int n, int align); void virtio_queue_notify(VirtIODevice *vdev, int n); uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 08/19] dataplane: allow virtio-1 devices
Handle endianness conversion for virtio-1 virtqueues correctly. Note that dataplane now needs to be built per-target. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/block/dataplane/virtio-blk.c | 4 +- hw/scsi/virtio-scsi-dataplane.c | 2 +- hw/virtio/Makefile.objs | 2 +- hw/virtio/dataplane/Makefile.objs | 2 +- hw/virtio/dataplane/vring.c | 86 ++++++++++++++----------- include/hw/virtio/dataplane/vring-accessors.h | 75 +++++++++++++++++++++ include/hw/virtio/dataplane/vring.h | 14 +--- 7 files changed, 131 insertions(+), 54 deletions(-) create mode 100644 include/hw/virtio/dataplane/vring-accessors.h diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 1222a37..2d8cc15 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -16,7 +16,9 @@ #include "qemu/iov.h" #include "qemu/thread.h" #include "qemu/error-report.h" +#include "hw/virtio/virtio-access.h" #include "hw/virtio/dataplane/vring.h" +#include "hw/virtio/dataplane/vring-accessors.h" #include "sysemu/block-backend.h" #include "hw/virtio/virtio-blk.h" #include "virtio-blk.h" @@ -75,7 +77,7 @@ static void complete_request_vring(VirtIOBlockReq *req, unsigned char status) VirtIOBlockDataPlane *s = req->dev->dataplane; stb_p(&req->in->status, status); - vring_push(&req->dev->dataplane->vring, &req->elem, + vring_push(s->vdev, &req->dev->dataplane->vring, &req->elem, req->qiov.size + sizeof(*req->in)); /* Suppress notification to guest by BH and its scheduled diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 03a1e8c..418d73b 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -94,7 +94,7 @@ void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req) { VirtIODevice *vdev = VIRTIO_DEVICE(req->vring->parent); - vring_push(&req->vring->vring, &req->elem, + vring_push(vdev, &req->vring->vring, &req->elem, req->qsgl.size + req->resp_iov.size); if (vring_should_notify(vdev, &req->vring->vring)) { diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index d21c397..19b224a 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -2,7 +2,7 @@ common-obj-y += virtio-rng.o common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o common-obj-y += virtio-bus.o common-obj-y += virtio-mmio.o -common-obj-$(CONFIG_VIRTIO) += dataplane/ +obj-$(CONFIG_VIRTIO) += dataplane/ obj-y += virtio.o virtio-balloon.o obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o diff --git a/hw/virtio/dataplane/Makefile.objs b/hw/virtio/dataplane/Makefile.objs index 9a8cfc0..753a9ca 100644 --- a/hw/virtio/dataplane/Makefile.objs +++ b/hw/virtio/dataplane/Makefile.objs @@ -1 +1 @@ -common-obj-y += vring.o +obj-y += vring.o diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 6e283fc..a44c8c8 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -18,7 +18,9 @@ #include "hw/hw.h" #include "exec/memory.h" #include "exec/address-spaces.h" +#include "hw/virtio/virtio-access.h" #include "hw/virtio/dataplane/vring.h" +#include "hw/virtio/dataplane/vring-accessors.h" #include "qemu/error-report.h" /* vring_map can be coupled with vring_unmap or (if you still have the @@ -83,7 +85,7 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n) vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096); vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n); - vring->last_used_idx = vring->vr.used->idx; + vring->last_used_idx = vring_get_used_idx(vdev, vring); vring->signalled_used = 0; vring->signalled_used_valid = false; @@ -104,7 +106,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n) void vring_disable_notification(VirtIODevice *vdev, Vring *vring) { if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { - vring->vr.used->flags |= VRING_USED_F_NO_NOTIFY; + vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY); } } @@ -117,10 +119,10 @@ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring) if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = vring->vr.avail->idx; } else { - vring->vr.used->flags &= ~VRING_USED_F_NO_NOTIFY; + vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY); } smp_mb(); /* ensure update is seen before reading avail_idx */ - return !vring_more_avail(vring); + return !vring_more_avail(vdev, vring); } /* This is stolen from linux/drivers/vhost/vhost.c:vhost_notify() */ @@ -134,12 +136,13 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) smp_mb(); if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && - unlikely(vring->vr.avail->idx == vring->last_avail_idx)) { + unlikely(!vring_more_avail(vdev, vring))) { return true; } if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { - return !(vring->vr.avail->flags & VRING_AVAIL_F_NO_INTERRUPT); + return !(vring_get_avail_flags(vdev, vring) & + VRING_AVAIL_F_NO_INTERRUPT); } old = vring->signalled_used; v = vring->signalled_used_valid; @@ -154,15 +157,18 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) } -static int get_desc(Vring *vring, VirtQueueElement *elem, +static int get_desc(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem, struct vring_desc *desc) { unsigned *num; struct iovec *iov; hwaddr *addr; MemoryRegion *mr; + int is_write = virtio_tswap16(vdev, desc->flags) & VRING_DESC_F_WRITE; + uint32_t len = virtio_tswap32(vdev, desc->len); + uint64_t desc_addr = virtio_tswap64(vdev, desc->addr); - if (desc->flags & VRING_DESC_F_WRITE) { + if (is_write) { num = &elem->in_num; iov = &elem->in_sg[*num]; addr = &elem->in_addr[*num]; @@ -186,44 +192,45 @@ static int get_desc(Vring *vring, VirtQueueElement *elem, } /* TODO handle non-contiguous memory across region boundaries */ - iov->iov_base = vring_map(&mr, desc->addr, desc->len, - desc->flags & VRING_DESC_F_WRITE); + iov->iov_base = vring_map(&mr, desc_addr, len, is_write); if (!iov->iov_base) { error_report("Failed to map descriptor addr %#" PRIx64 " len %u", - (uint64_t)desc->addr, desc->len); + (uint64_t)desc_addr, len); return -EFAULT; } /* The MemoryRegion is looked up again and unref'ed later, leave the * ref in place. */ - iov->iov_len = desc->len; - *addr = desc->addr; + iov->iov_len = len; + *addr = desc_addr; *num += 1; return 0; } /* This is stolen from linux/drivers/vhost/vhost.c. */ -static int get_indirect(Vring *vring, VirtQueueElement *elem, - struct vring_desc *indirect) +static int get_indirect(VirtIODevice *vdev, Vring *vring, + VirtQueueElement *elem, struct vring_desc *indirect) { struct vring_desc desc; unsigned int i = 0, count, found = 0; int ret; + uint32_t len = virtio_tswap32(vdev, indirect->len); + uint64_t addr = virtio_tswap64(vdev, indirect->addr); /* Sanity check */ - if (unlikely(indirect->len % sizeof(desc))) { + if (unlikely(len % sizeof(desc))) { error_report("Invalid length in indirect descriptor: " "len %#x not multiple of %#zx", - indirect->len, sizeof(desc)); + len, sizeof(desc)); vring->broken = true; return -EFAULT; } - count = indirect->len / sizeof(desc); + count = len / sizeof(desc); /* Buffers are chained via a 16 bit next field, so * we can have at most 2^16 of these. */ if (unlikely(count > USHRT_MAX + 1)) { - error_report("Indirect buffer length too big: %d", indirect->len); + error_report("Indirect buffer length too big: %d", len); vring->broken = true; return -EFAULT; } @@ -234,12 +241,12 @@ static int get_indirect(Vring *vring, VirtQueueElement *elem, /* Translate indirect descriptor */ desc_ptr = vring_map(&mr, - indirect->addr + found * sizeof(desc), + addr + found * sizeof(desc), sizeof(desc), false); if (!desc_ptr) { error_report("Failed to map indirect descriptor " "addr %#" PRIx64 " len %zu", - (uint64_t)indirect->addr + found * sizeof(desc), + (uint64_t)addr + found * sizeof(desc), sizeof(desc)); vring->broken = true; return -EFAULT; @@ -257,19 +264,20 @@ static int get_indirect(Vring *vring, VirtQueueElement *elem, return -EFAULT; } - if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) { + if (unlikely(virtio_tswap16(vdev, desc.flags) + & VRING_DESC_F_INDIRECT)) { error_report("Nested indirect descriptor"); vring->broken = true; return -EFAULT; } - ret = get_desc(vring, elem, &desc); + ret = get_desc(vdev, vring, elem, &desc); if (ret < 0) { vring->broken |= (ret == -EFAULT); return ret; } - i = desc.next; - } while (desc.flags & VRING_DESC_F_NEXT); + i = virtio_tswap16(vdev, desc.next); + } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT); return 0; } @@ -320,7 +328,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* Check it isn't doing very strange things with descriptor numbers. */ last_avail_idx = vring->last_avail_idx; - avail_idx = vring->vr.avail->idx; + avail_idx = vring_get_avail_idx(vdev, vring); barrier(); /* load indices now and not again later */ if (unlikely((uint16_t)(avail_idx - last_avail_idx) > num)) { @@ -341,7 +349,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* Grab the next descriptor number they're advertising, and increment * the index we've seen. */ - head = vring->vr.avail->ring[last_avail_idx % num]; + head = vring_get_avail_ring(vdev, vring, last_avail_idx % num); elem->index = head; @@ -370,21 +378,21 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* Ensure descriptor is loaded before accessing fields */ barrier(); - if (desc.flags & VRING_DESC_F_INDIRECT) { - ret = get_indirect(vring, elem, &desc); + if (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_INDIRECT) { + ret = get_indirect(vdev, vring, elem, &desc); if (ret < 0) { goto out; } continue; } - ret = get_desc(vring, elem, &desc); + ret = get_desc(vdev, vring, elem, &desc); if (ret < 0) { goto out; } - i = desc.next; - } while (desc.flags & VRING_DESC_F_NEXT); + i = virtio_tswap16(vdev, desc.next); + } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT); /* On success, increment avail index. */ vring->last_avail_idx++; @@ -407,9 +415,9 @@ out: * * Stolen from linux/drivers/vhost/vhost.c. */ -void vring_push(Vring *vring, VirtQueueElement *elem, int len) +void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem, + int len) { - struct vring_used_elem *used; unsigned int head = elem->index; uint16_t new; @@ -422,14 +430,16 @@ void vring_push(Vring *vring, VirtQueueElement *elem, int len) /* The virtqueue contains a ring of used buffers. Get a pointer to the * next entry in that used ring. */ - used = &vring->vr.used->ring[vring->last_used_idx % vring->vr.num]; - used->id = head; - used->len = len; + vring_set_used_ring_id(vdev, vring, vring->last_used_idx % vring->vr.num, + head); + vring_set_used_ring_len(vdev, vring, vring->last_used_idx % vring->vr.num, + len); /* Make sure buffer is written before we update index. */ smp_wmb(); - new = vring->vr.used->idx = ++vring->last_used_idx; + new = ++vring->last_used_idx; + vring_set_used_idx(vdev, vring, new); if (unlikely((int16_t)(new - vring->signalled_used) < (uint16_t)1)) { vring->signalled_used_valid = false; } diff --git a/include/hw/virtio/dataplane/vring-accessors.h b/include/hw/virtio/dataplane/vring-accessors.h new file mode 100644 index 0000000..b508b87 --- /dev/null +++ b/include/hw/virtio/dataplane/vring-accessors.h @@ -0,0 +1,75 @@ +#ifndef VRING_ACCESSORS_H +#define VRING_ACCESSORS_H + +#include "hw/virtio/virtio_ring.h" +#include "hw/virtio/virtio.h" +#include "hw/virtio/virtio-access.h" + +static inline uint16_t vring_get_used_idx(VirtIODevice *vdev, Vring *vring) +{ + return virtio_tswap16(vdev, vring->vr.used->idx); +} + +static inline void vring_set_used_idx(VirtIODevice *vdev, Vring *vring, + uint16_t idx) +{ + vring->vr.used->idx = virtio_tswap16(vdev, idx); +} + +static inline uint16_t vring_get_avail_idx(VirtIODevice *vdev, Vring *vring) +{ + return virtio_tswap16(vdev, vring->vr.avail->idx); +} + +static inline uint16_t vring_get_avail_ring(VirtIODevice *vdev, Vring *vring, + int i) +{ + return virtio_tswap16(vdev, vring->vr.avail->ring[i]); +} + +static inline void vring_set_used_ring_id(VirtIODevice *vdev, Vring *vring, + int i, uint32_t id) +{ + vring->vr.used->ring[i].id = virtio_tswap32(vdev, id); +} + +static inline void vring_set_used_ring_len(VirtIODevice *vdev, Vring *vring, + int i, uint32_t len) +{ + vring->vr.used->ring[i].len = virtio_tswap32(vdev, len); +} + +static inline uint16_t vring_get_used_flags(VirtIODevice *vdev, Vring *vring) +{ + return virtio_tswap16(vdev, vring->vr.used->flags); +} + +static inline uint16_t vring_get_avail_flags(VirtIODevice *vdev, Vring *vring) +{ + return virtio_tswap16(vdev, vring->vr.avail->flags); +} + +static inline void vring_set_used_flags(VirtIODevice *vdev, Vring *vring, + uint16_t flags) +{ + vring->vr.used->flags |= virtio_tswap16(vdev, flags); +} + +static inline void vring_clear_used_flags(VirtIODevice *vdev, Vring *vring, + uint16_t flags) +{ + vring->vr.used->flags &= virtio_tswap16(vdev, ~flags); +} + +static inline unsigned int vring_get_num(Vring *vring) +{ + return vring->vr.num; +} + +/* Are there more descriptors available? */ +static inline bool vring_more_avail(VirtIODevice *vdev, Vring *vring) +{ + return vring_get_avail_idx(vdev, vring) != vring->last_avail_idx; +} + +#endif diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h index d3e086a..e42c0fc 100644 --- a/include/hw/virtio/dataplane/vring.h +++ b/include/hw/virtio/dataplane/vring.h @@ -31,17 +31,6 @@ typedef struct { bool broken; /* was there a fatal error? */ } Vring; -static inline unsigned int vring_get_num(Vring *vring) -{ - return vring->vr.num; -} - -/* Are there more descriptors available? */ -static inline bool vring_more_avail(Vring *vring) -{ - return vring->vr.avail->idx != vring->last_avail_idx; -} - /* Fail future vring_pop() and vring_push() calls until reset */ static inline void vring_set_broken(Vring *vring) { @@ -54,6 +43,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring); bool vring_enable_notification(VirtIODevice *vdev, Vring *vring); bool vring_should_notify(VirtIODevice *vdev, Vring *vring); int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem); -void vring_push(Vring *vring, VirtQueueElement *elem, int len); +void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem, + int len); #endif /* VRING_H */ -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 09/19] s390x/css: Add a callback for when subchannel gets disabled
From: Thomas Huth <thuth at linux.vnet.ibm.com> We need a possibility to run code when a subchannel gets disabled. This patch adds the necessary infrastructure. Signed-off-by: Thomas Huth <thuth at linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/s390x/css.c | 12 ++++++++++++ hw/s390x/css.h | 1 + 2 files changed, 13 insertions(+) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index b67c039..735ec55 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -588,6 +588,7 @@ int css_do_msch(SubchDev *sch, SCHIB *orig_schib) { SCSW *s = &sch->curr_status.scsw; PMCW *p = &sch->curr_status.pmcw; + uint16_t oldflags; int ret; SCHIB schib; @@ -610,6 +611,7 @@ int css_do_msch(SubchDev *sch, SCHIB *orig_schib) copy_schib_from_guest(&schib, orig_schib); /* Only update the program-modifiable fields. */ p->intparm = schib.pmcw.intparm; + oldflags = p->flags; p->flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA | PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME | PMCW_FLAGS_MASK_MP); @@ -625,6 +627,12 @@ int css_do_msch(SubchDev *sch, SCHIB *orig_schib) (PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_CSENSE); sch->curr_status.mba = schib.mba; + /* Has the channel been disabled? */ + if (sch->disable_cb && (oldflags & PMCW_FLAGS_MASK_ENA) != 0 + && (p->flags & PMCW_FLAGS_MASK_ENA) == 0) { + sch->disable_cb(sch); + } + ret = 0; out: @@ -1443,6 +1451,10 @@ void css_reset_sch(SubchDev *sch) { PMCW *p = &sch->curr_status.pmcw; + if ((p->flags & PMCW_FLAGS_MASK_ENA) != 0 && sch->disable_cb) { + sch->disable_cb(sch); + } + p->intparm = 0; p->flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA | PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME | diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 33104ac..7fa807b 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -81,6 +81,7 @@ struct SubchDev { uint8_t ccw_no_data_cnt; /* transport-provided data: */ int (*ccw_cb) (SubchDev *, CCW1); + void (*disable_cb)(SubchDev *); SenseId id; void *driver_data; }; -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 10/19] s390x/virtio-ccw: add virtio set-revision call
From: Thomas Huth <thuth at linux.vnet.ibm.com> Handle the virtio-ccw revision according to what the guest sets. When revision 1 is selected, we have a virtio-1 standard device with byteswapping for the virtio rings. When a channel gets disabled, we have to revert to the legacy behavior in case the next user of the device does not negotiate the revision 1 anymore (e.g. the boot firmware uses revision 1, but the operating system only uses the legacy mode). Note that revisions > 0 are still disabled. Signed-off-by: Thomas Huth <thuth at linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/s390x/virtio-ccw.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ hw/s390x/virtio-ccw.h | 5 +++++ 2 files changed, 57 insertions(+) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index e434718..5311d9f 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -20,9 +20,11 @@ #include "hw/virtio/virtio-net.h" #include "hw/sysbus.h" #include "qemu/bitops.h" +#include "hw/virtio/virtio-access.h" #include "hw/virtio/virtio-bus.h" #include "hw/s390x/adapter.h" #include "hw/s390x/s390_flic.h" +#include "linux/virtio_config.h" #include "ioinst.h" #include "css.h" @@ -260,6 +262,12 @@ typedef struct VirtioThinintInfo { uint8_t isc; } QEMU_PACKED VirtioThinintInfo; +typedef struct VirtioRevInfo { + uint16_t revision; + uint16_t length; + uint8_t data[0]; +} QEMU_PACKED VirtioRevInfo; + /* Specify where the virtqueues for the subchannel are in guest memory. */ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align, uint16_t index, uint16_t num) @@ -299,6 +307,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) { int ret; VqInfoBlock info; + VirtioRevInfo revinfo; uint8_t status; VirtioFeatDesc features; void *config; @@ -375,6 +384,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) features.features = (uint32_t)dev->host_features; } else if (features.index == 1) { features.features = (uint32_t)(dev->host_features >> 32); + /* + * Don't offer version 1 to the guest if it did not + * negotiate at least revision 1. + */ + if (dev->revision <= 0) { + features.features &= ~(1 << (VIRTIO_F_VERSION_1 - 32)); + } } else { /* Return zeroes if the guest supports more feature bits. */ features.features = 0; @@ -406,6 +422,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) (vdev->guest_features & 0xffffffff00000000) | features.features); } else if (features.index == 1) { + /* + * The guest should not set version 1 if it didn't + * negotiate a revision >= 1. + */ + if (dev->revision <= 0) { + features.features &= ~(1 << (VIRTIO_F_VERSION_1 - 32)); + } virtio_set_features(vdev, (vdev->guest_features & 0x00000000ffffffff) | ((uint64_t)features.features << 32)); @@ -608,6 +631,25 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) } } break; + case CCW_CMD_SET_VIRTIO_REV: + len = sizeof(revinfo); + if (ccw.count < len || (check_len && ccw.count > len)) { + ret = -EINVAL; + break; + } + if (!ccw.cda) { + ret = -EFAULT; + break; + } + cpu_physical_memory_read(ccw.cda, &revinfo, len); + if (dev->revision >= 0 || + revinfo.revision > VIRTIO_CCW_REV_MAX) { + ret = -ENOSYS; + break; + } + ret = 0; + dev->revision = revinfo.revision; + break; default: ret = -ENOSYS; break; @@ -615,6 +657,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) return ret; } +static void virtio_sch_disable_cb(SubchDev *sch) +{ + VirtioCcwDevice *dev = sch->driver_data; + + dev->revision = -1; +} + static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) { unsigned int cssid = 0; @@ -740,6 +789,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE); sch->ccw_cb = virtio_ccw_cb; + sch->disable_cb = virtio_sch_disable_cb; /* Build senseid data. */ memset(&sch->id, 0, sizeof(SenseId)); @@ -747,6 +797,8 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) sch->id.cu_type = VIRTIO_CCW_CU_TYPE; sch->id.cu_model = vdev->device_id; + dev->revision = -1; + /* Set default feature bits that are offered by the host. */ dev->host_features = 0; virtio_add_feature(&dev->host_features, VIRTIO_F_NOTIFY_ON_EMPTY); diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 9087f7a..fe5c782 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -40,6 +40,7 @@ #define CCW_CMD_SET_CONF_IND 0x53 #define CCW_CMD_READ_VQ_CONF 0x32 #define CCW_CMD_SET_IND_ADAPTER 0x73 +#define CCW_CMD_SET_VIRTIO_REV 0x83 #define TYPE_VIRTIO_CCW_DEVICE "virtio-ccw-device" #define VIRTIO_CCW_DEVICE(obj) \ @@ -68,6 +69,9 @@ typedef struct VirtIOCCWDeviceClass { int (*exit)(VirtioCcwDevice *dev); } VirtIOCCWDeviceClass; +/* The maximum virtio revision we support. */ +#define VIRTIO_CCW_REV_MAX 0 + /* Performance improves when virtqueue kick processing is decoupled from the * vcpu thread using ioeventfd for some devices. */ #define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1 @@ -86,6 +90,7 @@ struct VirtioCcwDevice { SubchDev *sch; char *bus_id; uint64_t host_features; + int revision; VirtioBusState bus; bool ioeventfd_started; bool ioeventfd_disabled; -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 11/19] s390x/virtio-ccw: support virtio-1 set_vq format
Support the new CCW_CMD_SET_VQ format for virtio-1 devices. While we're at it, refactor the code a bit and enforce big endian fields (which had always been required, even for legacy). Reviewed-by: Thomas Huth <thuth at linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/s390x/virtio-ccw.c | 114 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 5311d9f..75c9ff9 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -238,11 +238,20 @@ VirtualCssBus *virtual_css_bus_init(void) } /* Communication blocks used by several channel commands. */ -typedef struct VqInfoBlock { +typedef struct VqInfoBlockLegacy { uint64_t queue; uint32_t align; uint16_t index; uint16_t num; +} QEMU_PACKED VqInfoBlockLegacy; + +typedef struct VqInfoBlock { + uint64_t desc; + uint32_t res0; + uint16_t index; + uint16_t num; + uint64_t avail; + uint64_t used; } QEMU_PACKED VqInfoBlock; typedef struct VqConfigBlock { @@ -269,17 +278,20 @@ typedef struct VirtioRevInfo { } QEMU_PACKED VirtioRevInfo; /* Specify where the virtqueues for the subchannel are in guest memory. */ -static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align, - uint16_t index, uint16_t num) +static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info, + VqInfoBlockLegacy *linfo) { VirtIODevice *vdev = virtio_ccw_get_vdev(sch); + uint16_t index = info ? info->index : linfo->index; + uint16_t num = info ? info->num : linfo->num; + uint64_t desc = info ? info->desc : linfo->queue; if (index > VIRTIO_PCI_QUEUE_MAX) { return -EINVAL; } /* Current code in virtio.c relies on 4K alignment. */ - if (addr && (align != 4096)) { + if (linfo && desc && (linfo->align != 4096)) { return -EINVAL; } @@ -287,8 +299,12 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align, return -EINVAL; } - virtio_queue_set_addr(vdev, index, addr); - if (!addr) { + if (info) { + virtio_queue_set_rings(vdev, index, desc, info->avail, info->used); + } else { + virtio_queue_set_addr(vdev, index, desc); + } + if (!desc) { virtio_queue_set_vector(vdev, index, 0); } else { /* Fail if we don't have a big enough queue. */ @@ -303,10 +319,66 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align, return 0; } -static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) +static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len, + bool is_legacy) { int ret; VqInfoBlock info; + VqInfoBlockLegacy linfo; + size_t info_len = is_legacy ? sizeof(linfo) : sizeof(info); + + if (check_len) { + if (ccw.count != info_len) { + return -EINVAL; + } + } else if (ccw.count < info_len) { + /* Can't execute command. */ + return -EINVAL; + } + if (!ccw.cda) { + return -EFAULT; + } + if (is_legacy) { + linfo.queue = ldq_be_phys(&address_space_memory, ccw.cda); + linfo.align = ldl_be_phys(&address_space_memory, + ccw.cda + sizeof(linfo.queue)); + linfo.index = lduw_be_phys(&address_space_memory, + ccw.cda + sizeof(linfo.queue) + + sizeof(linfo.align)); + linfo.num = lduw_be_phys(&address_space_memory, + ccw.cda + sizeof(linfo.queue) + + sizeof(linfo.align) + + sizeof(linfo.index)); + ret = virtio_ccw_set_vqs(sch, NULL, &linfo); + } else { + info.desc = ldq_be_phys(&address_space_memory, ccw.cda); + info.index = lduw_be_phys(&address_space_memory, + ccw.cda + sizeof(info.desc) + + sizeof(info.res0)); + info.num = lduw_be_phys(&address_space_memory, + ccw.cda + sizeof(info.desc) + + sizeof(info.res0) + + sizeof(info.index)); + info.avail = ldq_be_phys(&address_space_memory, + ccw.cda + sizeof(info.desc) + + sizeof(info.res0) + + sizeof(info.index) + + sizeof(info.num)); + info.used = ldq_be_phys(&address_space_memory, + ccw.cda + sizeof(info.desc) + + sizeof(info.res0) + + sizeof(info.index) + + sizeof(info.num) + + sizeof(info.avail)); + ret = virtio_ccw_set_vqs(sch, &info, NULL); + } + sch->curr_status.scsw.count = 0; + return ret; +} + +static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) +{ + int ret; VirtioRevInfo revinfo; uint8_t status; VirtioFeatDesc features; @@ -331,33 +403,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) /* Look at the command. */ switch (ccw.cmd_code) { case CCW_CMD_SET_VQ: - if (check_len) { - if (ccw.count != sizeof(info)) { - ret = -EINVAL; - break; - } - } else if (ccw.count < sizeof(info)) { - /* Can't execute command. */ - ret = -EINVAL; - break; - } - if (!ccw.cda) { - ret = -EFAULT; - } else { - info.queue = ldq_phys(&address_space_memory, ccw.cda); - info.align = ldl_phys(&address_space_memory, - ccw.cda + sizeof(info.queue)); - info.index = lduw_phys(&address_space_memory, - ccw.cda + sizeof(info.queue) - + sizeof(info.align)); - info.num = lduw_phys(&address_space_memory, - ccw.cda + sizeof(info.queue) - + sizeof(info.align) - + sizeof(info.index)); - ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index, - info.num); - sch->curr_status.scsw.count = 0; - } + ret = virtio_ccw_handle_set_vq(sch, ccw, check_len, dev->revision < 1); break; case CCW_CMD_VDEV_RESET: virtio_ccw_stop_ioeventfd(dev); -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 12/19] virtio: disallow late feature changes for virtio-1
For virtio-1 devices, the driver must not attempt to set feature bits after it set FEATURES_OK in the device status. Simply reject it in that case. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/virtio/virtio.c | 16 ++++++++++++++-- include/hw/virtio/virtio.h | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 508dccf..4f2dc48 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -980,7 +980,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) vmstate_save_state(f, &vmstate_virtio, vdev); } -int virtio_set_features(VirtIODevice *vdev, uint64_t val) +static int __virtio_set_features(VirtIODevice *vdev, uint64_t val) { BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); VirtioBusClass *vbusk = VIRTIO_BUS_GET_CLASS(qbus); @@ -996,6 +996,18 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val) return bad ? -1 : 0; } +int virtio_set_features(VirtIODevice *vdev, uint64_t val) +{ + /* + * The driver must not attempt to set features after feature negotiation + * has finished. + */ + if (vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) { + return -EINVAL; + } + return __virtio_set_features(vdev, val); +} + int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) { int i, ret; @@ -1028,7 +1040,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) qemu_get_be32s(f, &features); /* XXX features >= 32 */ - if (virtio_set_features(vdev, features) < 0) { + if (__virtio_set_features(vdev, features) < 0) { supported_features = k->get_features(qbus->parent); error_report("Features 0x%x unsupported. Allowed features: 0x%lx", features, supported_features); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 80ee313..9a984c2 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -32,6 +32,8 @@ #define VIRTIO_CONFIG_S_DRIVER 2 /* Driver has used its parts of the config, and is happy */ #define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* Driver has finished configuring features */ +#define VIRTIO_CONFIG_S_FEATURES_OK 8 /* We've given up on this device. */ #define VIRTIO_CONFIG_S_FAILED 0x80 -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 13/19] virtio: allow to fail setting status
virtio-1 allow setting of the FEATURES_OK status bit to fail if the negotiated feature bits are inconsistent: let's fail virtio_set_status() in that case and update virtio-ccw to post an error to the guest. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/s390x/virtio-ccw.c | 20 ++++++++++++-------- hw/virtio/virtio.c | 24 +++++++++++++++++++++++- include/hw/virtio/virtio.h | 3 ++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 75c9ff9..ec492b8 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -555,15 +555,19 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) { virtio_ccw_stop_ioeventfd(dev); } - virtio_set_status(vdev, status); - if (vdev->status == 0) { - virtio_reset(vdev); - } - if (status & VIRTIO_CONFIG_S_DRIVER_OK) { - virtio_ccw_start_ioeventfd(dev); + if (virtio_set_status(vdev, status) == 0) { + if (vdev->status == 0) { + virtio_reset(vdev); + } + if (status & VIRTIO_CONFIG_S_DRIVER_OK) { + virtio_ccw_start_ioeventfd(dev); + } + sch->curr_status.scsw.count = ccw.count - sizeof(status); + ret = 0; + } else { + /* Trigger a command reject. */ + ret = -ENOSYS; } - sch->curr_status.scsw.count = ccw.count - sizeof(status); - ret = 0; } break; case CCW_CMD_SET_IND: diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 4f2dc48..be128f7 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -548,15 +548,37 @@ void virtio_update_irq(VirtIODevice *vdev) virtio_notify_vector(vdev, VIRTIO_NO_VECTOR); } -void virtio_set_status(VirtIODevice *vdev, uint8_t val) +static int virtio_validate_features(VirtIODevice *vdev) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + + if (k->validate_features) { + return k->validate_features(vdev); + } else { + return 0; + } +} + +int virtio_set_status(VirtIODevice *vdev, uint8_t val) { VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); trace_virtio_set_status(vdev, val); + if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + if (!(vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) && + val & VIRTIO_CONFIG_S_FEATURES_OK) { + int ret = virtio_validate_features(vdev); + + if (ret) { + return ret; + } + } + } if (k->set_status) { k->set_status(vdev, val); } vdev->status = val; + return 0; } bool target_words_bigendian(void); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 9a984c2..e7bedd1 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -149,6 +149,7 @@ typedef struct VirtioDeviceClass { uint64_t (*get_features)(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); void (*get_config)(VirtIODevice *vdev, uint8_t *config); void (*set_config)(VirtIODevice *vdev, const uint8_t *config); void (*reset)(VirtIODevice *vdev); @@ -232,7 +233,7 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align); void virtio_queue_notify(VirtIODevice *vdev, int n); uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); -void virtio_set_status(VirtIODevice *vdev, uint8_t val); +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); -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 14/19] s390x/virtio-ccw: enable virtio 1.0
virtio-ccw should now have everything in place to operate virtio 1.0 devices, so let's enable revision 1. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/s390x/virtio-ccw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index fe5c782..d40e3be 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -70,7 +70,7 @@ typedef struct VirtIOCCWDeviceClass { } VirtIOCCWDeviceClass; /* The maximum virtio revision we support. */ -#define VIRTIO_CCW_REV_MAX 0 +#define VIRTIO_CCW_REV_MAX 1 /* Performance improves when virtqueue kick processing is decoupled from the * vcpu thread using ioeventfd for some devices. */ -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 15/19] virtio-net: no writeable mac for virtio-1
Devices operating as virtio 1.0 may not allow writes to the mac address in config space. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/net/virtio-net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index d6d1b98..ebbea60 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -87,6 +87,7 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) memcpy(&netcfg, config, n->config_size); if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) && + !virtio_has_feature(vdev, VIRTIO_F_VERSION_1) && memcmp(netcfg.mac, n->mac, ETH_ALEN)) { memcpy(n->mac, netcfg.mac, ETH_ALEN); qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 16/19] virtio-net: support longer header
virtio-1 devices always use num_buffers in the header, even if mergeable rx buffers have not been negotiated. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/net/virtio-net.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index ebbea60..7ee2bd6 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -373,15 +373,21 @@ static int peer_has_ufo(VirtIONet *n) return n->has_ufo; } -static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs) +static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs, + int version_1) { int i; NetClientState *nc; n->mergeable_rx_bufs = mergeable_rx_bufs; - n->guest_hdr_len = n->mergeable_rx_bufs ? - sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); + if (version_1) { + n->guest_hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + } else { + n->guest_hdr_len = n->mergeable_rx_bufs ? + sizeof(struct virtio_net_hdr_mrg_rxbuf) : + sizeof(struct virtio_net_hdr); + } for (i = 0; i < n->max_queues; i++) { nc = qemu_get_subqueue(n->nic, i); @@ -525,7 +531,9 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) virtio_net_set_mrg_rx_bufs(n, __virtio_has_feature(features, - VIRTIO_NET_F_MRG_RXBUF)); + VIRTIO_NET_F_MRG_RXBUF), + __virtio_has_feature(features, + VIRTIO_F_VERSION_1)); if (n->has_vnet_hdr) { n->curr_guest_offloads @@ -1407,7 +1415,8 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, qemu_get_buffer(f, n->mac, ETH_ALEN); n->vqs[0].tx_waiting = qemu_get_be32(f); - virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f)); + virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f), + virtio_has_feature(vdev, VIRTIO_F_VERSION_1)); if (version_id >= 3) n->status = qemu_get_be16(f); @@ -1653,7 +1662,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) n->vqs[0].tx_waiting = 0; n->tx_burst = n->net_conf.txburst; - virtio_net_set_mrg_rx_bufs(n, 0); + virtio_net_set_mrg_rx_bufs(n, 0, 0); n->promisc = 1; /* for compatibility */ n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN); -- 1.7.9.5
virtio-net (non-vhost) now should have everything in place to support virtio 1.0: let's enable the feature bit for it. Note that VIRTIO_F_VERSION_1 is technically a transport feature; once every device is ready for virtio 1.0, we can move setting this feature bit out of the individual devices. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/net/virtio-net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 7ee2bd6..b5dd356 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -473,6 +473,7 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features) } if (!get_vhost_net(nc->peer)) { + virtio_add_feature(&features, VIRTIO_F_VERSION_1); return features; } return vhost_net_get_features(get_vhost_net(nc->peer), features); -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 18/19] virtio: support revision-specific features
Devices may support different sets of feature bits depending on which revision they're operating at. Let's give the transport a way to re-query the device about its features when the revision has been changed. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/s390x/virtio-ccw.c | 12 ++++++++++-- hw/virtio/virtio-bus.c | 14 ++++++++++++-- include/hw/virtio/virtio-bus.h | 3 +++ include/hw/virtio/virtio.h | 3 +++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index ec492b8..3826074 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -699,6 +699,10 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) } 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); break; default: ret = -ENOSYS; @@ -712,6 +716,9 @@ static void virtio_sch_disable_cb(SubchDev *sch) VirtioCcwDevice *dev = sch->driver_data; 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); } static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) @@ -854,8 +861,9 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) virtio_add_feature(&dev->host_features, VIRTIO_F_NOTIFY_ON_EMPTY); virtio_add_feature(&dev->host_features, VIRTIO_F_BAD_FEATURE); - dev->host_features = virtio_bus_get_vdev_features(&dev->bus, - dev->host_features); + /* All devices start in legacy mode. */ + dev->host_features + virtio_bus_get_vdev_features_rev(&dev->bus, dev->host_features, 0); css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, parent->hotplugged, 1); diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index 32e3fab..a30826c 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -97,18 +97,28 @@ 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) { 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); return k->get_features(vdev, requested_features); } +uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus, + uint64_t requested_features) +{ + return virtio_bus_get_vdev_features_rev(bus, requested_features, 0); +} + /* Get bad features of the plugged device. */ uint64_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus) { diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h index 0a4dde1..f0916ef 100644 --- a/include/hw/virtio/virtio-bus.h +++ b/include/hw/virtio/virtio-bus.h @@ -84,6 +84,9 @@ 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); /* Get bad features of the plugged device. */ uint64_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); /* Get config of the plugged device. */ diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index e7bedd1..f31e3df 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -147,6 +147,9 @@ 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 (*bad_features)(VirtIODevice *vdev); void (*set_features)(VirtIODevice *vdev, uint64_t val); int (*validate_features)(VirtIODevice *vdev); -- 1.7.9.5
Cornelia Huck
2014-Dec-02 13:00 UTC
[PATCH RFC v5 19/19] virtio-blk: revision specific feature bits
Wire up virtio-blk to provide different feature bit sets depending on whether legacy or v1.0 has been requested. Note that VERSION_1 is still disabled due to missing ANY_LAYOUT support. Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> --- hw/block/virtio-blk.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 9cfae66..fdc236a 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -587,6 +587,24 @@ 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) +{ + 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); + virtio_clear_feature(&features, VIRTIO_BLK_F_WCE); + /* we're still missing ANY_LAYOUT */ + /* virtio_add_feature(&features, VIRTIO_F_VERSION_1); */ + return features; +} + static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) { VirtIOBlock *s = VIRTIO_BLK(vdev); @@ -821,6 +839,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->set_status = virtio_blk_set_status; vdc->reset = virtio_blk_reset; vdc->save = virtio_blk_save_device; -- 1.7.9.5
Michael S. Tsirkin
2014-Dec-02 14:46 UTC
[PATCH RFC v5 07/19] virtio: allow virtio-1 queue layout
On Tue, Dec 02, 2014 at 02:00:15PM +0100, Cornelia Huck wrote:> For virtio-1 devices, we allow a more complex queue layout that doesn't > require descriptor table and rings on a physically-contigous memory area: > add virtio_queue_set_rings() to allow transports to set this up. > > Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> > --- > hw/virtio/virtio.c | 16 ++++++++++++++++ > include/hw/virtio/virtio.h | 2 ++ > 2 files changed, 18 insertions(+) > > diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c > index 8f69ffa..508dccf 100644 > --- a/hw/virtio/virtio.c > +++ b/hw/virtio/virtio.c > @@ -96,6 +96,13 @@ static void virtqueue_init(VirtQueue *vq) > { > hwaddr pa = vq->pa; > > + if (pa == -1ULL) { > + /* > + * This is a virtio-1 style vq that has already been setup > + * in virtio_queue_set. > + */ > + return; > + } > vq->vring.desc = pa; > vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc); > vq->vring.used = vring_align(vq->vring.avail + > @@ -717,6 +724,15 @@ hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n) > return vdev->vq[n].pa; > } > > +void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, > + hwaddr avail, hwaddr used) > +{ > + vdev->vq[n].pa = -1ULL; > + vdev->vq[n].vring.desc = desc; > + vdev->vq[n].vring.avail = avail; > + vdev->vq[n].vring.used = used; > +} > + > void virtio_queue_set_num(VirtIODevice *vdev, int n, int num) > { > /* Don't allow guest to flip queue between existent andpa == -1ULL tricks look quite ugly. Can't we set desc/avail/used unconditionally, and drop the pa value?> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h > index 68c40db..80ee313 100644 > --- a/include/hw/virtio/virtio.h > +++ b/include/hw/virtio/virtio.h > @@ -224,6 +224,8 @@ void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); > hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); > void virtio_queue_set_num(VirtIODevice *vdev, int n, int num); > int virtio_queue_get_num(VirtIODevice *vdev, int n); > +void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, > + hwaddr avail, hwaddr used); > void virtio_queue_set_align(VirtIODevice *vdev, int n, int align); > void virtio_queue_notify(VirtIODevice *vdev, int n); > uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); > -- > 1.7.9.5
Michael S. Tsirkin
2014-Dec-04 16:20 UTC
[PATCH RFC v5 10/19] s390x/virtio-ccw: add virtio set-revision call
On Tue, Dec 02, 2014 at 02:00:18PM +0100, Cornelia Huck wrote:> From: Thomas Huth <thuth at linux.vnet.ibm.com> > > Handle the virtio-ccw revision according to what the guest sets. > When revision 1 is selected, we have a virtio-1 standard device > with byteswapping for the virtio rings. > > When a channel gets disabled, we have to revert to the legacy behavior > in case the next user of the device does not negotiate the revision 1 > anymore (e.g. the boot firmware uses revision 1, but the operating > system only uses the legacy mode). > > Note that revisions > 0 are still disabled. > > Signed-off-by: Thomas Huth <thuth at linux.vnet.ibm.com> > Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> > --- > hw/s390x/virtio-ccw.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ > hw/s390x/virtio-ccw.h | 5 +++++ > 2 files changed, 57 insertions(+) > > diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c > index e434718..5311d9f 100644 > --- a/hw/s390x/virtio-ccw.c > +++ b/hw/s390x/virtio-ccw.c > @@ -20,9 +20,11 @@ > #include "hw/virtio/virtio-net.h" > #include "hw/sysbus.h" > #include "qemu/bitops.h" > +#include "hw/virtio/virtio-access.h" > #include "hw/virtio/virtio-bus.h" > #include "hw/s390x/adapter.h" > #include "hw/s390x/s390_flic.h" > +#include "linux/virtio_config.h" > > #include "ioinst.h" > #include "css.h" > @@ -260,6 +262,12 @@ typedef struct VirtioThinintInfo { > uint8_t isc; > } QEMU_PACKED VirtioThinintInfo; > > +typedef struct VirtioRevInfo { > + uint16_t revision; > + uint16_t length; > + uint8_t data[0]; > +} QEMU_PACKED VirtioRevInfo; > + > /* Specify where the virtqueues for the subchannel are in guest memory. */ > static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align, > uint16_t index, uint16_t num) > @@ -299,6 +307,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) > { > int ret; > VqInfoBlock info; > + VirtioRevInfo revinfo; > uint8_t status; > VirtioFeatDesc features; > void *config; > @@ -375,6 +384,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) > features.features = (uint32_t)dev->host_features; > } else if (features.index == 1) { > features.features = (uint32_t)(dev->host_features >> 32); > + /* > + * Don't offer version 1 to the guest if it did not > + * negotiate at least revision 1. > + */ > + if (dev->revision <= 0) { > + features.features &= ~(1 << (VIRTIO_F_VERSION_1 - 32)); > + } > } else { > /* Return zeroes if the guest supports more feature bits. */ > features.features = 0; > @@ -406,6 +422,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) > (vdev->guest_features & 0xffffffff00000000) | > features.features); > } else if (features.index == 1) { > + /* > + * The guest should not set version 1 if it didn't > + * negotiate a revision >= 1. > + */ > + if (dev->revision <= 0) { > + features.features &= ~(1 << (VIRTIO_F_VERSION_1 - 32)); > + } > virtio_set_features(vdev, > (vdev->guest_features & 0x00000000ffffffff) | > ((uint64_t)features.features << 32)); > @@ -608,6 +631,25 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) > } > } > break; > + case CCW_CMD_SET_VIRTIO_REV: > + len = sizeof(revinfo); > + if (ccw.count < len || (check_len && ccw.count > len)) { > + ret = -EINVAL; > + break; > + } > + if (!ccw.cda) { > + ret = -EFAULT; > + break; > + } > + cpu_physical_memory_read(ccw.cda, &revinfo, len); > + if (dev->revision >= 0 || > + revinfo.revision > VIRTIO_CCW_REV_MAX) { > + ret = -ENOSYS; > + break; > + } > + ret = 0; > + dev->revision = revinfo.revision; > + break; > default: > ret = -ENOSYS; > break; > @@ -615,6 +657,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) > return ret; > } > > +static void virtio_sch_disable_cb(SubchDev *sch) > +{ > + VirtioCcwDevice *dev = sch->driver_data; > + > + dev->revision = -1; > +} > + > static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) > { > unsigned int cssid = 0; > @@ -740,6 +789,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) > css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE); > > sch->ccw_cb = virtio_ccw_cb; > + sch->disable_cb = virtio_sch_disable_cb; > > /* Build senseid data. */ > memset(&sch->id, 0, sizeof(SenseId)); > @@ -747,6 +797,8 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) > sch->id.cu_type = VIRTIO_CCW_CU_TYPE; > sch->id.cu_model = vdev->device_id; > > + dev->revision = -1; > + > /* Set default feature bits that are offered by the host. */ > dev->host_features = 0; > virtio_add_feature(&dev->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);You should also clear it on device reset.> diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h > index 9087f7a..fe5c782 100644 > --- a/hw/s390x/virtio-ccw.h > +++ b/hw/s390x/virtio-ccw.h > @@ -40,6 +40,7 @@ > #define CCW_CMD_SET_CONF_IND 0x53 > #define CCW_CMD_READ_VQ_CONF 0x32 > #define CCW_CMD_SET_IND_ADAPTER 0x73 > +#define CCW_CMD_SET_VIRTIO_REV 0x83 > > #define TYPE_VIRTIO_CCW_DEVICE "virtio-ccw-device" > #define VIRTIO_CCW_DEVICE(obj) \ > @@ -68,6 +69,9 @@ typedef struct VirtIOCCWDeviceClass { > int (*exit)(VirtioCcwDevice *dev); > } VirtIOCCWDeviceClass; > > +/* The maximum virtio revision we support. */ > +#define VIRTIO_CCW_REV_MAX 0 > + > /* Performance improves when virtqueue kick processing is decoupled from the > * vcpu thread using ioeventfd for some devices. */ > #define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1 > @@ -86,6 +90,7 @@ struct VirtioCcwDevice { > SubchDev *sch; > char *bus_id; > uint64_t host_features; > + int revision; > VirtioBusState bus; > bool ioeventfd_started; > bool ioeventfd_disabled; > -- > 1.7.9.5
Michael S. Tsirkin
2014-Dec-09 13:46 UTC
[PATCH RFC v5 14/19] s390x/virtio-ccw: enable virtio 1.0
On Tue, Dec 02, 2014 at 02:00:22PM +0100, Cornelia Huck wrote:> virtio-ccw should now have everything in place to operate virtio 1.0 > devices, so let's enable revision 1. > > Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>Looks like this will allow revision 1 for all devices, we only want this for virtio 1 devices. The following should fix it I think: Signed-off-by: Michael S. Tsirkin <mst at redhat.com> diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index d40e3be..f5a1d3e 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -69,9 +69,6 @@ typedef struct VirtIOCCWDeviceClass { int (*exit)(VirtioCcwDevice *dev); } VirtIOCCWDeviceClass; -/* The maximum virtio revision we support. */ -#define VIRTIO_CCW_REV_MAX 1 - /* Performance improves when virtqueue kick processing is decoupled from the * vcpu thread using ioeventfd for some devices. */ #define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1 @@ -104,6 +101,12 @@ struct VirtioCcwDevice { uint64_t ind_bit; }; +/* The maximum virtio revision we support. */ +static int virtio_ccw_rev_max(VirtioCcwDevice *dev) +{ + return dev->host_features & (1ULL << VIRTIO_F_VERSION_1) ? 1 : 0; +} + /* virtual css bus type */ typedef struct VirtualCssBus { BusState parent_obj; diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 3826074..922b021 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -693,7 +693,7 @@ 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) { + revinfo.revision > virtio_ccw_rev_max(dev)) { ret = -ENOSYS; break; }
Cornelia Huck
2014-Dec-10 17:35 UTC
[Qemu-devel] [PATCH RFC v5 05/19] virtio: support more feature bits
On Tue, 2 Dec 2014 14:00:13 +0100 Cornelia Huck <cornelia.huck at de.ibm.com> wrote:> diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h > index 070006c..23d713b 100644 > --- a/include/hw/qdev-properties.h > +++ b/include/hw/qdev-properties.h > @@ -51,6 +51,17 @@ extern PropertyInfo qdev_prop_arraylen; > .defval = (bool)_defval, \ > } > > +#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) { \ > + .name = (_name), \ > + .info = &(qdev_prop_bit), \ > + .bitnr = (_bit), \ > + .offset = offsetof(_state, _field) \ > + + type_check(uint64_t,typeof_field(_state, _field)), \ > + .qtype = QTYPE_QBOOL, \ > + .defval = (bool)_defval, \ > + } > + > + > #define DEFINE_PROP_BOOL(_name, _state, _field, _defval) { \ > .name = (_name), \ > .info = &(qdev_prop_bool), \This one is of course broken. I'll send an updated patch tomorrow.
Cornelia Huck
2014-Dec-10 17:37 UTC
[Qemu-devel] [PATCH RFC v5 18/19] virtio: support revision-specific features
On Tue, 2 Dec 2014 14:00:26 +0100 Cornelia Huck <cornelia.huck at de.ibm.com> wrote:> Devices may support different sets of feature bits depending on which > revision they're operating at. Let's give the transport a way to > re-query the device about its features when the revision has been > changed. > > Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com> > --- > hw/s390x/virtio-ccw.c | 12 ++++++++++-- > hw/virtio/virtio-bus.c | 14 ++++++++++++-- > include/hw/virtio/virtio-bus.h | 3 +++ > include/hw/virtio/virtio.h | 3 +++ > 4 files changed, 28 insertions(+), 4 deletions(-)There seems to be something wrong with this patch - I noticed when I fixed prop_bit64. Needs debugging.
Maybe Matching Threads
- [PATCH RFC v5 18/19] virtio: support revision-specific features
- [PATCH RFC v6 18/20] virtio: support revision-specific features
- [PATCH RFC v6 18/20] virtio: support revision-specific features
- [PATCH RFC v6 18/20] virtio: support revision-specific features
- [PATCH RFC v6 18/20] virtio: support revision-specific features