diff options
author | Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> | 2016-02-01 11:18:09 +0530 |
---|---|---|
committer | Alexey Kardashevskiy <aik@ozlabs.ru> | 2016-02-08 16:40:39 +1100 |
commit | 69a2f9ae1a191743acb3f68e6e0514eb65beb576 (patch) | |
tree | 95761a7eb67da125f0b10d98ab12045dada8ef50 /lib/libvirtio | |
parent | 940ac04abe83647fd72f13b1efe85bce645d2196 (diff) | |
download | SLOF-69a2f9ae1a191743acb3f68e6e0514eb65beb576.zip SLOF-69a2f9ae1a191743acb3f68e6e0514eb65beb576.tar.gz SLOF-69a2f9ae1a191743acb3f68e6e0514eb65beb576.tar.bz2 |
virtio: 1.0 guest features negotiation
With virtio 1.0, there feature negotiation step needs to be completed
before starting to notify the device.
This includes following steps:
* Read host supported features
* Check if virtio 1.0 is supported
* Set guest supported features
* Read host features and compare with the guest features.
* Write FEATURES_OK and check it back to confirm.
Add virtio_get_status supporting routine.
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'lib/libvirtio')
-rw-r--r-- | lib/libvirtio/virtio.c | 42 | ||||
-rw-r--r-- | lib/libvirtio/virtio.h | 2 |
2 files changed, 44 insertions, 0 deletions
diff --git a/lib/libvirtio/virtio.c b/lib/libvirtio/virtio.c index ba7aced..276d69f 100644 --- a/lib/libvirtio/virtio.c +++ b/lib/libvirtio/virtio.c @@ -297,6 +297,18 @@ void virtio_set_status(struct virtio_device *dev, int status) } } +/** + * Get device status bits + */ +void virtio_get_status(struct virtio_device *dev, int *status) +{ + if (dev->is_modern) { + *status = ci_read_8(dev->common.addr + + offset_of(struct virtio_dev_common, dev_status)); + } else { + *status = ci_read_8(dev->base+VIRTIOHDR_DEVICE_STATUS); + } +} /** * Set guest feature bits @@ -350,6 +362,36 @@ uint64_t virtio_get_host_features(struct virtio_device *dev) return features; } +int virtio_negotiate_guest_features(struct virtio_device *dev, uint64_t features) +{ + uint64_t host_features = 0; + int status; + + /* Negotiate features */ + host_features = virtio_get_host_features(dev); + if (!(host_features & VIRTIO_F_VERSION_1)) { + fprintf(stderr, "Device does not support virtio 1.0 %llx\n", host_features); + return -1; + } + + virtio_set_guest_features(dev, features); + host_features = virtio_get_host_features(dev); + if ((host_features & features) != features) { + fprintf(stderr, "Features error %llx\n", features); + return -1; + } + + virtio_get_status(dev, &status); + status |= VIRTIO_STAT_FEATURES_OK; + virtio_set_status(dev, status); + + /* Read back to verify the FEATURES_OK bit */ + virtio_get_status(dev, &status); + if ((status & VIRTIO_STAT_FEATURES_OK) != VIRTIO_STAT_FEATURES_OK) + return -1; + + return 0; +} /** * Get additional config values diff --git a/lib/libvirtio/virtio.h b/lib/libvirtio/virtio.h index bf8ea28..3ff2bac 100644 --- a/lib/libvirtio/virtio.h +++ b/lib/libvirtio/virtio.h @@ -116,9 +116,11 @@ extern int virtio_queue_init_vq(struct virtio_device *dev, struct vqs *vq, unsig extern void virtio_reset_device(struct virtio_device *dev); extern void virtio_queue_notify(struct virtio_device *dev, int queue); extern void virtio_set_status(struct virtio_device *dev, int status); +extern void virtio_get_status(struct virtio_device *dev, int *status); extern void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned long qaddr); extern void virtio_set_guest_features(struct virtio_device *dev, uint64_t features); extern uint64_t virtio_get_host_features(struct virtio_device *dev); +extern int virtio_negotiate_guest_features(struct virtio_device *dev, uint64_t features); extern uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size); extern int __virtio_read_config(struct virtio_device *dev, void *dst, int offset, int len); |