diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2011-11-24 13:28:52 +0100 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2011-11-28 11:36:28 -0600 |
commit | ad0c93328dcb7a0ad68a68d0f66ea1949ebaaa2d (patch) | |
tree | d63b95103e8003a2aa5592b3d6bf9b8fbd92ff40 /hw/virtio.c | |
parent | ae0f940e6b4f5177892dd6a12762282fa9089972 (diff) |
virtio: add and use virtio_set_features
vdev->guest_features is not masking features that are not supported by
the guest. Fix this by introducing a common wrapper to be used by all
virtio bus implementations.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/virtio.c')
-rw-r--r-- | hw/virtio.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/hw/virtio.c b/hw/virtio.c index 7011b5b398..81ecc40b31 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -763,12 +763,25 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) } } +int virtio_set_features(VirtIODevice *vdev, uint32_t val) +{ + uint32_t supported_features = + vdev->binding->get_features(vdev->binding_opaque); + bool bad = (val & ~supported_features) != 0; + + val &= supported_features; + if (vdev->set_features) { + vdev->set_features(vdev, val); + } + vdev->guest_features = val; + return bad ? -1 : 0; +} + int virtio_load(VirtIODevice *vdev, QEMUFile *f) { int num, i, ret; uint32_t features; - uint32_t supported_features = - vdev->binding->get_features(vdev->binding_opaque); + uint32_t supported_features; if (vdev->binding->load_config) { ret = vdev->binding->load_config(vdev->binding_opaque, f); @@ -780,14 +793,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) qemu_get_8s(f, &vdev->isr); qemu_get_be16s(f, &vdev->queue_sel); qemu_get_be32s(f, &features); - if (features & ~supported_features) { + + if (virtio_set_features(vdev, features) < 0) { + supported_features = vdev->binding->get_features(vdev->binding_opaque); error_report("Features 0x%x unsupported. Allowed features: 0x%x", features, supported_features); return -1; } - if (vdev->set_features) - vdev->set_features(vdev, features); - vdev->guest_features = features; vdev->config_len = qemu_get_be32(f); qemu_get_buffer(f, vdev->config, vdev->config_len); |