summaryrefslogtreecommitdiff
path: root/hw/virtio/virtio.c
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/virtio.c
parentfdba6d967e00864edd21275a6ee1d23a383510e8 (diff)
downloadqemu-019a3edbb25f1571e876f8af1ce4c55412939e5d.tar.gz
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/virtio.c')
-rw-r--r--hw/virtio/virtio.c51
1 files changed, 45 insertions, 6 deletions
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;