aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2015-06-01 10:45:40 +0200
committerMichael S. Tsirkin <mst@redhat.com>2015-06-01 14:18:55 +0200
commit019a3edbb25f1571e876f8af1ce4c55412939e5d (patch)
tree2af699ef896ecdeb322a8775641299acccdd255a /hw/virtio
parentfdba6d967e00864edd21275a6ee1d23a383510e8 (diff)
virtio: make features 64bit wide
Make features 64bit wide everywhere. On migration a full 64bit guest_features field is sent if one of the high bits is set, in addition to the lower 32bit guest_features field which must stay for compatibility reasons. That way we send the lower 32 feature bits twice, but the code is simpler because we don't have to split and compose the 64bit features into two 32bit fields. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio')
-rw-r--r--hw/virtio/virtio-balloon.c2
-rw-r--r--hw/virtio/virtio-rng.c2
-rw-r--r--hw/virtio/virtio.c51
3 files changed, 47 insertions, 8 deletions
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index cfff542f38..f915c7bd73 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 06e71782b2..420c39fb50 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 a0637d9763..596e3d8aaf 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -906,6 +906,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,
@@ -916,6 +923,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,
@@ -929,6 +946,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 }
}
};
@@ -938,6 +959,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) {
@@ -947,7 +969,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);
@@ -1024,11 +1046,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);
/*
@@ -1094,6 +1111,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;