[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2] virtio: make features 64bit wide
From: |
Michael S. Tsirkin |
Subject: |
Re: [Qemu-devel] [PATCH v2] virtio: make features 64bit wide |
Date: |
Fri, 29 May 2015 16:53:31 +0200 |
On Fri, May 29, 2015 at 09:51:20AM +0200, Gerd Hoffmann wrote:
> Make features 64bit wide everywhere. Exception: command line flags
> remain 32bit and are copyed into the lower 32 host_features at
> initialization time.
>
> On migration a full 64bit guest_features field is sent if one of the
> high bits is set, additionally to the lower 32bit guest_features field
> which must stay for compatibility reasons. That way we send the lower
> 32 feature bits twice, but that way the code is simpler because we don't
> have to split and compose the 64bit features into two 32bit fields.
>
> This depends on "move host_features" patch by cornelia.
>
> Signed-off-by: Gerd Hoffmann <address@hidden>
Thanks, this is very close to what I had in mind.
Question: why do we need the feature_flags field?
What's wrong with setting bits in host_features directly?
> ---
> 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 | 18 ++++++++-------
> hw/scsi/vhost-scsi.c | 4 ++--
> hw/scsi/virtio-scsi.c | 4 ++--
> hw/virtio/virtio-balloon.c | 2 +-
> hw/virtio/virtio-rng.c | 2 +-
> hw/virtio/virtio.c | 54
> +++++++++++++++++++++++++++++++++++++++------
> include/hw/virtio/virtio.h | 21 +++++++++---------
> 10 files changed, 77 insertions(+), 34 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 e6afe97..cd539aa 100644
> --- a/hw/block/virtio-blk.c
> +++ b/hw/block/virtio-blk.c
> @@ -718,7 +718,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 6e2ad82..95be9fc 100644
> --- a/hw/char/virtio-serial-bus.c
> +++ b/hw/char/virtio-serial-bus.c
> @@ -498,7 +498,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 3af6faf..b21ef6b 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -435,7 +435,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);
> @@ -468,9 +468,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: */
> @@ -1032,10 +1032,12 @@ static ssize_t virtio_net_receive(NetClientState *nc,
> const uint8_t *buf, size_t
> if (i == 0)
> 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",
> - i, n->mergeable_rx_bufs, offset, size,
> - n->guest_hdr_len, n->host_hdr_len, vdev->guest_features);
> + "i %zd mergeable %d offset %zd, size %zd, "
> + "guest hdr len %zd, host hdr len %zd "
> + "guest features 0x%" PRIx64,
> + i, n->mergeable_rx_bufs, offset, size,
> + n->guest_hdr_len, n->host_hdr_len,
> + vdev->guest_features);
> exit(1);
> }
>
> @@ -1549,7 +1551,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice
> *vdev, int idx,
> vdev, idx, mask);
> }
>
> -static void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
> +static 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/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
> index 335f442..9c76486 100644
> --- a/hw/scsi/vhost-scsi.c
> +++ b/hw/scsi/vhost-scsi.c
> @@ -151,8 +151,8 @@ 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 e242fef..36ae66e 100644
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c
> @@ -628,8 +628,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)
> {
> VirtIOSCSI *s = VIRTIO_SCSI(vdev);
>
> diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
> index 484c3c3..734f35b 100644
> --- a/hw/virtio/virtio-balloon.c
> +++ b/hw/virtio/virtio-balloon.c
> @@ -310,7 +310,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
> trace_virtio_balloon_set_config(dev->actual, oldactual);
> }
>
> -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-rng.c b/hw/virtio/virtio-rng.c
> index 06e7178..420c39f 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 96d9c6a..4c2911a 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -893,6 +893,13 @@ static bool virtio_device_endian_needed(void *opaque)
> return vdev->device_endian != virtio_default_endian();
> }
>
> +static bool virtio_64bit_features_needed(void *opaque)
> +{
> + VirtIODevice *vdev = opaque;
> +
> + return (vdev->host_features >> 32) != 0;
> +}
> +
> static const VMStateDescription vmstate_virtio_device_endian = {
> .name = "virtio/device_endian",
> .version_id = 1,
> @@ -903,6 +910,16 @@ static const VMStateDescription
> vmstate_virtio_device_endian = {
> }
> };
>
> +static const VMStateDescription vmstate_virtio_64bit_features = {
> + .name = "virtio/64bit_features",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT64(guest_features, VirtIODevice),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> static const VMStateDescription vmstate_virtio = {
> .name = "virtio",
> .version_id = 1,
> @@ -916,6 +933,10 @@ static const VMStateDescription vmstate_virtio = {
> .vmsd = &vmstate_virtio_device_endian,
> .needed = &virtio_device_endian_needed
> },
> + {
> + .vmsd = &vmstate_virtio_64bit_features,
> + .needed = &virtio_64bit_features_needed
> + },
> { 0 }
> }
> };
> @@ -925,6 +946,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
> BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
> VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
> VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
> + uint32_t guest_features_lo = (vdev->guest_features & 0xffffffff);
> int i;
>
> if (k->save_config) {
> @@ -934,7 +956,7 @@ 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);
> + qemu_put_be32s(f, &guest_features_lo);
> qemu_put_be32(f, vdev->config_len);
> qemu_put_buffer(f, vdev->config, vdev->config_len);
>
> @@ -1011,11 +1033,6 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int
> version_id)
> }
> qemu_get_be32s(f, &features);
>
> - if (virtio_set_features(vdev, features) < 0) {
> - error_report("Features 0x%x unsupported. Allowed features: 0x%x",
> - features, vdev->host_features);
> - return -1;
> - }
> config_len = qemu_get_be32(f);
>
> /*
> @@ -1081,6 +1098,28 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int
> version_id)
> vdev->device_endian = virtio_default_endian();
> }
>
> + if (virtio_64bit_features_needed(vdev)) {
> + /*
> + * Subsection load filled vdev->guest_features. Run them
> + * through virtio_set_features to sanity-check them against
> + * host_features.
> + */
> + uint64_t features64 = vdev->guest_features;
> + if (virtio_set_features(vdev, features64) < 0) {
> + error_report("Features 0x%" PRIx64 " unsupported. "
> + "Allowed features: 0x%" PRIx64,
> + features64, vdev->host_features);
> + return -1;
> + }
> + } else {
> + if (virtio_set_features(vdev, features) < 0) {
> + error_report("Features 0x%x unsupported. "
> + "Allowed features: 0x%" PRIx64,
> + features, vdev->host_features);
> + return -1;
> + }
> + }
> +
> for (i = 0; i < num; i++) {
> if (vdev->vq[i].pa) {
> uint16_t nheads;
> @@ -1176,6 +1215,7 @@ void virtio_init(VirtIODevice *vdev, const char *name,
> vdev->vmstate = qemu_add_vm_change_state_handler(virtio_vmstate_change,
> vdev);
> vdev->device_endian = virtio_default_endian();
> + vdev->host_features = vdev->feature_flags;
> }
>
> hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n)
> @@ -1347,7 +1387,7 @@ static void virtio_device_unrealize(DeviceState *dev,
> Error **errp)
> }
>
> static Property virtio_properties[] = {
> - DEFINE_VIRTIO_COMMON_FEATURES(VirtIODevice, host_features),
> + DEFINE_VIRTIO_COMMON_FEATURES(VirtIODevice, feature_flags),
> DEFINE_PROP_END_OF_LIST(),
> };
>
> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> index b620da5..261a208 100644
> --- a/include/hw/virtio/virtio.h
> +++ b/include/hw/virtio/virtio.h
> @@ -73,8 +73,9 @@ struct VirtIODevice
> uint8_t status;
> uint8_t isr;
> uint16_t queue_sel;
> - uint32_t guest_features;
> - uint32_t host_features;
> + uint64_t guest_features;
> + uint64_t host_features;
> + uint32_t feature_flags;
> size_t config_len;
> void *config;
> uint16_t config_vector;
> @@ -96,8 +97,8 @@ 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);
> + uint64_t (*get_features)(VirtIODevice *vdev, uint64_t
> requested_features);
> + uint64_t (*bad_features)(VirtIODevice *vdev);
> void (*set_features)(VirtIODevice *vdev, uint32_t val);
> void (*get_config)(VirtIODevice *vdev, uint8_t *config);
> void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
> @@ -223,21 +224,21 @@ void virtio_irq(VirtQueue *vq);
> VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
> VirtQueue *virtio_vector_next_queue(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);
> + assert(fbit < 64);
> *features |= (1 << 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);
> + assert(fbit < 64);
> *features &= ~(1 << 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);
> + assert(fbit < 64);
> return !!(features & (1 << fbit));
> }
>
> --
> 1.8.3.1