[SLOF] [PATCH v2 15/19] virtio: 1.0 guest features negotiation

Nikunj A Dadhania nikunj at linux.vnet.ibm.com
Wed Jan 20 23:10:29 AEDT 2016


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 at linux.vnet.ibm.com>
---
 lib/libvirtio/virtio.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
 lib/libvirtio/virtio.h |  4 +++-
 2 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/lib/libvirtio/virtio.c b/lib/libvirtio/virtio.c
index b88aa61..0b939fc 100644
--- a/lib/libvirtio/virtio.c
+++ b/lib/libvirtio/virtio.c
@@ -299,7 +299,7 @@ int virtio_queue_init_vq(struct virtio_device *dev, struct vqs *vq, unsigned int
 /**
  * Set device status bits
  */
-void virtio_set_status(struct virtio_device *dev, int status)
+void virtio_set_status(struct virtio_device *dev, uint32_t status)
 {
 	if (dev->type != VIRTIO_TYPE_PCI)
 		return;
@@ -311,6 +311,20 @@ void virtio_set_status(struct virtio_device *dev, int status)
 	}
 }
 
+/**
+ * Get device status bits
+ */
+void virtio_get_status(struct virtio_device *dev, uint32_t *status)
+{
+	if (dev->type != VIRTIO_TYPE_PCI)
+		return;
+	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
@@ -380,6 +394,37 @@ void virtio_get_host_features_long(struct virtio_device *dev, uint64_t *features
 	}
 }
 
+int virtio_negotiate_guest_features(struct virtio_device *dev, uint64_t features)
+{
+	uint64_t host_features = 0;
+	uint32_t status;
+
+	/* Negotiate features */
+	virtio_get_host_features_long(dev, &host_features);
+	if (!(host_features & VIRTIO_F_VERSION_1)) {
+		fprintf(stderr, "Device does not support virtio 1.0 %llx\n", host_features);
+		return false;
+	}
+
+	virtio_set_guest_features_long(dev,  features);
+	virtio_get_host_features_long(dev, &host_features);
+	if ((host_features & features) != features) {
+		fprintf(stderr, "Features error %llx\n", features);
+		return false;
+	}
+
+	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 false;
+
+	return true;
+}
+
 /**
  * Get additional config values
  */
diff --git a/lib/libvirtio/virtio.h b/lib/libvirtio/virtio.h
index c272bd5..011732d 100644
--- a/lib/libvirtio/virtio.h
+++ b/lib/libvirtio/virtio.h
@@ -118,12 +118,14 @@ 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_set_status(struct virtio_device *dev, uint32_t status);
+extern void virtio_get_status(struct virtio_device *dev, uint32_t *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, int features);
 extern void virtio_get_host_features(struct virtio_device *dev, int *features);
 extern void virtio_set_guest_features_long(struct virtio_device *dev, uint64_t features);
 extern void virtio_get_host_features_long(struct virtio_device *dev, uint64_t *features);
+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);
-- 
2.5.0



More information about the SLOF mailing list