virtio: make vring_desc_*() take phys addrs
authorMark McLoughlin <markmc@redhat.com>
Wed, 17 Jun 2009 10:37:32 +0000 (11:37 +0100)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 22 Jun 2009 15:10:50 +0000 (10:10 -0500)
Change the vring descriptor helpers to take the physical
address of the descriptor table rather than a virtqueue.

This is needed in order to allow these helpers to be used
with an indirect descriptor table.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
hw/virtio.c

index 45a49fa..1e8376d 100644 (file)
@@ -85,31 +85,31 @@ static void virtqueue_init(VirtQueue *vq)
                                  VIRTIO_PCI_VRING_ALIGN);
 }
 
-static inline uint64_t vring_desc_addr(VirtQueue *vq, int i)
+static inline uint64_t vring_desc_addr(target_phys_addr_t desc_pa, int i)
 {
     target_phys_addr_t pa;
-    pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
+    pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
     return ldq_phys(pa);
 }
 
-static inline uint32_t vring_desc_len(VirtQueue *vq, int i)
+static inline uint32_t vring_desc_len(target_phys_addr_t desc_pa, int i)
 {
     target_phys_addr_t pa;
-    pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
+    pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
     return ldl_phys(pa);
 }
 
-static inline uint16_t vring_desc_flags(VirtQueue *vq, int i)
+static inline uint16_t vring_desc_flags(target_phys_addr_t desc_pa, int i)
 {
     target_phys_addr_t pa;
-    pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
+    pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
     return lduw_phys(pa);
 }
 
-static inline uint16_t vring_desc_next(VirtQueue *vq, int i)
+static inline uint16_t vring_desc_next(target_phys_addr_t desc_pa, int i)
 {
     target_phys_addr_t pa;
-    pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
+    pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
     return lduw_phys(pa);
 }
 
@@ -269,20 +269,21 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
     return head;
 }
 
-static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
+static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa,
+                                    unsigned int i, unsigned int max)
 {
     unsigned int next;
 
     /* If this descriptor says it doesn't chain, we're done. */
-    if (!(vring_desc_flags(vq, i) & VRING_DESC_F_NEXT))
-        return vq->vring.num;
+    if (!(vring_desc_flags(desc_pa, i) & VRING_DESC_F_NEXT))
+        return max;
 
     /* Check they're not leading us off end of descriptors. */
-    next = vring_desc_next(vq, i);
+    next = vring_desc_next(desc_pa, i);
     /* Make sure compiler knows to grab that: we don't want it changing! */
     wmb();
 
-    if (next >= vq->vring.num) {
+    if (next >= max) {
         fprintf(stderr, "Desc next is %u", next);
         exit(1);
     }
@@ -292,10 +293,12 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
 
 int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
 {
-    unsigned int idx;
+    target_phys_addr_t desc_pa = vq->vring.desc;
+    unsigned int idx, max;
     int num_bufs, in_total, out_total;
 
     idx = vq->last_avail_idx;
+    max = vq->vring.num;
 
     num_bufs = in_total = out_total = 0;
     while (virtqueue_num_heads(vq, idx)) {
@@ -304,21 +307,21 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
         i = virtqueue_get_head(vq, idx++);
         do {
             /* If we've got too many, that implies a descriptor loop. */
-            if (++num_bufs > vq->vring.num) {
+            if (++num_bufs > max) {
                 fprintf(stderr, "Looped descriptor");
                 exit(1);
             }
 
-            if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
+            if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
                 if (in_bytes > 0 &&
-                    (in_total += vring_desc_len(vq, i)) >= in_bytes)
+                    (in_total += vring_desc_len(desc_pa, i)) >= in_bytes)
                     return 1;
             } else {
                 if (out_bytes > 0 &&
-                    (out_total += vring_desc_len(vq, i)) >= out_bytes)
+                    (out_total += vring_desc_len(desc_pa, i)) >= out_bytes)
                     return 1;
             }
-        } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
+        } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
     }
 
     return 0;
@@ -326,7 +329,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
 
 int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
 {
-    unsigned int i, head;
+    unsigned int i, head, max;
+    target_phys_addr_t desc_pa = vq->vring.desc;
     target_phys_addr_t len;
 
     if (!virtqueue_num_heads(vq, vq->last_avail_idx))
@@ -335,23 +339,26 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
     /* When we start there are none of either input nor output. */
     elem->out_num = elem->in_num = 0;
 
+    max = vq->vring.num;
+
     i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
     do {
         struct iovec *sg;
         int is_write = 0;
 
-        if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
-            elem->in_addr[elem->in_num] = vring_desc_addr(vq, i);
+        if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
+            elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
             sg = &elem->in_sg[elem->in_num++];
             is_write = 1;
         } else
             sg = &elem->out_sg[elem->out_num++];
 
         /* Grab the first descriptor, and check it's OK. */
-        sg->iov_len = vring_desc_len(vq, i);
+        sg->iov_len = vring_desc_len(desc_pa, i);
         len = sg->iov_len;
 
-        sg->iov_base = cpu_physical_memory_map(vring_desc_addr(vq, i), &len, is_write);
+        sg->iov_base = cpu_physical_memory_map(vring_desc_addr(desc_pa, i),
+                                               &len, is_write);
 
         if (sg->iov_base == NULL || len != sg->iov_len) {
             fprintf(stderr, "virtio: trying to map MMIO memory\n");
@@ -359,11 +366,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
         }
 
         /* If we've got too many, that implies a descriptor loop. */
-        if ((elem->in_num + elem->out_num) > vq->vring.num) {
+        if ((elem->in_num + elem->out_num) > max) {
             fprintf(stderr, "Looped descriptor");
             exit(1);
         }
-    } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
+    } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
 
     elem->index = head;