aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikunj A Dadhania <nikunj@linux.vnet.ibm.com>2016-02-01 11:18:07 +0530
committerAlexey Kardashevskiy <aik@ozlabs.ru>2016-02-08 16:40:39 +1100
commite3a281624b47c98dacd63572ed7ce0ed8dc61391 (patch)
tree1e03fdd9c5a160cd5e452b6462fdca9acb5cc8d9 /lib
parent66c156d0dec4234fe7f423dda719f728ac898896 (diff)
downloadSLOF-e3a281624b47c98dacd63572ed7ce0ed8dc61391.zip
SLOF-e3a281624b47c98dacd63572ed7ce0ed8dc61391.tar.gz
SLOF-e3a281624b47c98dacd63572ed7ce0ed8dc61391.tar.bz2
virtio: make all virtio apis 1.0 aware
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@linux.vnet.ibm.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'lib')
-rw-r--r--lib/libvirtio/virtio.c149
-rw-r--r--lib/libvirtio/virtio.h2
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);