[SLOF] [PATCH v6 17/23] virtio: make all virtio apis 1.0 aware

Nikunj A Dadhania nikunj at linux.vnet.ibm.com
Mon Feb 1 16:48:07 AEDT 2016


Convert the following routines:
    virtio_get_qsize
    virtio_vring_desc
    virtio_get_vring_avail
    virtio_get_vring_used
    virtio_set_status: also use it in device reset.
    virtio_queue_notify
    virtio_set_qaddr
    virtio_{get,read}_config
    virtio_fill_desc

Signed-off-by: Nikunj A Dadhania <nikunj at linux.vnet.ibm.com>
Reviewed-by: Thomas Huth <thuth at redhat.com>
---
 lib/libvirtio/virtio.c | 149 ++++++++++++++++++++++++++++++++++++++-----------
 lib/libvirtio/virtio.h |   2 +-
 2 files changed, 118 insertions(+), 33 deletions(-)

diff --git a/lib/libvirtio/virtio.c b/lib/libvirtio/virtio.c
index 467c619..24d3bb8 100644
--- a/lib/libvirtio/virtio.c
+++ b/lib/libvirtio/virtio.c
@@ -94,14 +94,23 @@ unsigned long virtio_vring_size(unsigned int qsize)
  * @param   queue virtio queue number
  * @return  number of elements
  */
-int virtio_get_qsize(struct virtio_device *dev, int queue)
+unsigned int virtio_get_qsize(struct virtio_device *dev, int queue)
 {
-	int size = 0;
-
-	ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
-		    cpu_to_le16(queue));
-	eieio();
-	size = le16_to_cpu(ci_read_16(dev->base+VIRTIOHDR_QUEUE_SIZE));
+	unsigned int size = 0;
+
+	if (dev->is_modern) {
+		void *addr = dev->common.addr + offset_of(struct virtio_dev_common, q_select);
+		ci_write_16(addr, cpu_to_le16(queue));
+		eieio();
+		addr = dev->common.addr + offset_of(struct virtio_dev_common, q_size);
+		size = le16_to_cpu(ci_read_16(addr));
+	}
+	else {
+		ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
+			    cpu_to_le16(queue));
+		eieio();
+		size = le16_to_cpu(ci_read_16(dev->base+VIRTIOHDR_QUEUE_SIZE));
+	}
 
 	return size;
 }
@@ -117,11 +126,20 @@ struct vring_desc *virtio_get_vring_desc(struct virtio_device *dev, int queue)
 {
 	struct vring_desc *desc = 0;
 
-	ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
-		    cpu_to_le16(queue));
-	eieio();
-	desc = (void*)(4096L *
-		       le32_to_cpu(ci_read_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS)));
+	if (dev->is_modern) {
+		void *q_sel = dev->common.addr + offset_of(struct virtio_dev_common, q_select);
+		void *q_desc = dev->common.addr + offset_of(struct virtio_dev_common, q_desc);
+
+		ci_write_16(q_sel, cpu_to_le16(queue));
+		eieio();
+		desc = (void *)(virtio_pci_read64(q_desc));
+	} else {
+		ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
+			    cpu_to_le16(queue));
+		eieio();
+		desc = (void*)(4096L *
+			       le32_to_cpu(ci_read_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS)));
+	}
 
 	return desc;
 }
@@ -135,8 +153,18 @@ struct vring_desc *virtio_get_vring_desc(struct virtio_device *dev, int queue)
  */
 struct vring_avail *virtio_get_vring_avail(struct virtio_device *dev, int queue)
 {
-	return (void*)((uint64_t)virtio_get_vring_desc(dev, queue)
-		       + virtio_get_qsize(dev, queue) * sizeof(struct vring_desc));
+	if (dev->is_modern) {
+		void *q_sel = dev->common.addr + offset_of(struct virtio_dev_common, q_select);
+		void *q_avail = dev->common.addr + offset_of(struct virtio_dev_common, q_avail);
+
+		ci_write_16(q_sel, cpu_to_le16(queue));
+		eieio();
+		return (void *)(virtio_pci_read64(q_avail));
+	}
+	else {
+		return (void*)((uint64_t)virtio_get_vring_desc(dev, queue) +
+			       virtio_get_qsize(dev, queue) * sizeof(struct vring_desc));
+	}
 }
 
 
@@ -148,9 +176,18 @@ struct vring_avail *virtio_get_vring_avail(struct virtio_device *dev, int queue)
  */
 struct vring_used *virtio_get_vring_used(struct virtio_device *dev, int queue)
 {
-	return (void*)VQ_ALIGN((uint64_t)virtio_get_vring_avail(dev, queue)
-			       + virtio_get_qsize(dev, queue)
-			       * sizeof(struct vring_avail));
+	if (dev->is_modern) {
+		void *q_sel = dev->common.addr + offset_of(struct virtio_dev_common, q_select);
+		void *q_used = dev->common.addr + offset_of(struct virtio_dev_common, q_used);
+
+		ci_write_16(q_sel, cpu_to_le16(queue));
+		eieio();
+		return (void *)(virtio_pci_read64(q_used));
+	} else {
+		return (void*)VQ_ALIGN((uint64_t)virtio_get_vring_avail(dev, queue)
+				       + virtio_get_qsize(dev, queue)
+				       * sizeof(struct vring_avail));
+	}
 }
 
 /**
@@ -178,7 +215,7 @@ void virtio_fill_desc(struct vring_desc *desc, bool is_modern,
  */
 void virtio_reset_device(struct virtio_device *dev)
 {
-	ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, 0);
+	virtio_set_status(dev, 0);
 }
 
 
@@ -187,7 +224,20 @@ void virtio_reset_device(struct virtio_device *dev)
  */
 void virtio_queue_notify(struct virtio_device *dev, int queue)
 {
-	ci_write_16(dev->base+VIRTIOHDR_QUEUE_NOTIFY, cpu_to_le16(queue));
+	if (dev->is_modern) {
+		void *q_sel = dev->common.addr + offset_of(struct virtio_dev_common, q_select);
+		void *q_ntfy = dev->common.addr + offset_of(struct virtio_dev_common, q_notify_off);
+		void *addr;
+		uint16_t q_notify_off;
+
+		ci_write_16(q_sel, cpu_to_le16(queue));
+		eieio();
+		q_notify_off = le16_to_cpu(ci_read_16(q_ntfy));
+		addr = dev->notify.addr + q_notify_off * dev->notify_off_mul;
+		ci_write_16(addr, cpu_to_le16(queue));
+	} else {
+		ci_write_16(dev->base+VIRTIOHDR_QUEUE_NOTIFY, cpu_to_le16(queue));
+	}
 }
 
 /**
@@ -195,13 +245,27 @@ void virtio_queue_notify(struct virtio_device *dev, int queue)
  */
 void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned long qaddr)
 {
-	uint32_t val = qaddr;
-	val = val >> 12;
-	ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
-		    cpu_to_le16(queue));
-	eieio();
-	ci_write_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS,
-		    cpu_to_le32(val));
+	if (dev->is_modern) {
+		uint64_t q_desc = qaddr;
+		uint64_t q_avail;
+		uint64_t q_used;
+		uint32_t q_size = virtio_get_qsize(dev, queue);
+
+		virtio_pci_write64(dev->common.addr + offset_of(struct virtio_dev_common, q_desc), q_desc);
+		q_avail = q_desc + q_size * sizeof(struct vring_desc);
+		virtio_pci_write64(dev->common.addr + offset_of(struct virtio_dev_common, q_avail), q_avail);
+		q_used = VQ_ALIGN(q_avail + sizeof(struct vring_avail) + sizeof(uint16_t) * q_size);
+		virtio_pci_write64(dev->common.addr + offset_of(struct virtio_dev_common, q_used), q_used);
+		ci_write_16(dev->common.addr + offset_of(struct virtio_dev_common, q_enable), cpu_to_le16(1));
+	} else {
+		uint32_t val = qaddr;
+		val = val >> 12;
+		ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
+			    cpu_to_le16(queue));
+		eieio();
+		ci_write_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS,
+			    cpu_to_le32(val));
+	}
 }
 
 int virtio_queue_init_vq(struct virtio_device *dev, struct vqs *vq, unsigned int id)
@@ -225,7 +289,12 @@ int virtio_queue_init_vq(struct virtio_device *dev, struct vqs *vq, unsigned int
  */
 void virtio_set_status(struct virtio_device *dev, int status)
 {
-	ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, status);
+	if (dev->is_modern) {
+		ci_write_8(dev->common.addr +
+			   offset_of(struct virtio_dev_common, dev_status), status);
+	} else {
+		ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, status);
+	}
 }
 
 
@@ -254,26 +323,38 @@ void virtio_get_host_features(struct virtio_device *dev, int *features)
 uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size)
 {
 	uint64_t val = ~0ULL;
+	uint32_t hi, lo;
 	void *confbase;
 
-	confbase = dev->base + VIRTIOHDR_DEVICE_CONFIG;
+	if (dev->is_modern)
+		confbase = dev->device.addr;
+	else
+		confbase = dev->base+VIRTIOHDR_DEVICE_CONFIG;
+
 	switch (size) {
 	case 1:
 		val = ci_read_8(confbase+offset);
 		break;
 	case 2:
 		val = ci_read_16(confbase+offset);
+		if (dev->is_modern)
+			val = le16_to_cpu(val);
 		break;
 	case 4:
 		val = ci_read_32(confbase+offset);
+		if (dev->is_modern)
+			val = le32_to_cpu(val);
 		break;
 	case 8:
 		/* We don't support 8 bytes PIO accesses
 		 * in qemu and this is all PIO
 		 */
-		val = ci_read_32(confbase+offset);
-		val <<= 32;
-		val |= ci_read_32(confbase+offset+4);
+		lo = ci_read_32(confbase+offset);
+		hi = ci_read_32(confbase+offset+4);
+		if (dev->is_modern)
+			val = (uint64_t)le32_to_cpu(hi) << 32 | le32_to_cpu(lo);
+		else
+			val = (uint64_t)hi << 32 | lo;
 		break;
 	}
 
@@ -290,7 +371,11 @@ int __virtio_read_config(struct virtio_device *dev, void *dst,
 	unsigned char *buf = dst;
 	int i;
 
-	confbase = dev->base + VIRTIOHDR_DEVICE_CONFIG;
+	if (dev->is_modern)
+		confbase = dev->device.addr;
+	else
+		confbase = dev->base+VIRTIOHDR_DEVICE_CONFIG;
+
 	for (i = 0; i < len; i++)
 		buf[i] = ci_read_8(confbase + offset + i);
 
diff --git a/lib/libvirtio/virtio.h b/lib/libvirtio/virtio.h
index ebfc726..e2543a1 100644
--- a/lib/libvirtio/virtio.h
+++ b/lib/libvirtio/virtio.h
@@ -104,7 +104,7 @@ struct vqs {
 #define VQ_ALIGN(addr)	(((addr) + 0xfff) & ~0xfff)
 
 extern unsigned long virtio_vring_size(unsigned int qsize);
-extern int virtio_get_qsize(struct virtio_device *dev, int queue);
+extern unsigned int virtio_get_qsize(struct virtio_device *dev, int queue);
 extern struct vring_desc *virtio_get_vring_desc(struct virtio_device *dev, int queue);
 extern struct vring_avail *virtio_get_vring_avail(struct virtio_device *dev, int queue);
 extern struct vring_used *virtio_get_vring_used(struct virtio_device *dev, int queue);
-- 
2.5.0



More information about the SLOF mailing list