diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2015-06-04 12:34:14 +0200 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2015-06-10 18:15:04 +0200 |
commit | 6c0196d702e8482a17638ee79f45ce27cdd1ef5d (patch) | |
tree | fa1acb490639089eaf69d9684f95b5b54ca877d5 | |
parent | f5a5628cf0b65b223fa0c9031714578dfac4cf04 (diff) | |
download | hqemu-6c0196d702e8482a17638ee79f45ce27cdd1ef5d.zip hqemu-6c0196d702e8482a17638ee79f45ce27cdd1ef5d.tar.gz |
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@de.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r-- | hw/virtio/virtio.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index c27e975..3367100 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1021,7 +1021,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) vmstate_save_state(f, &vmstate_virtio, vdev, NULL); } -int virtio_set_features(VirtIODevice *vdev, uint64_t val) +static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val) { VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); bool bad = (val & ~(vdev->host_features)) != 0; @@ -1034,6 +1034,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_nocheck(vdev, val); +} + int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) { int i, ret; @@ -1137,14 +1149,14 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) * host_features. */ uint64_t features64 = vdev->guest_features; - if (virtio_set_features(vdev, features64) < 0) { + if (virtio_set_features_nocheck(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) { + if (virtio_set_features_nocheck(vdev, features) < 0) { error_report("Features 0x%x unsupported. " "Allowed features: 0x%" PRIx64, features, vdev->host_features); |