virtio: make vring_desc_*() take phys addrs

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>
This commit is contained in:
Mark McLoughlin 2009-06-17 11:37:32 +01:00 committed by Anthony Liguori
parent 024431b3d8
commit 5774cf98ca
1 changed files with 33 additions and 26 deletions

View File

@ -85,31 +85,31 @@ static void virtqueue_init(VirtQueue *vq)
VIRTIO_PCI_VRING_ALIGN); 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; 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); 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; 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); 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; 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); 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; 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); return lduw_phys(pa);
} }
@ -269,20 +269,21 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
return head; 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; unsigned int next;
/* If this descriptor says it doesn't chain, we're done. */ /* If this descriptor says it doesn't chain, we're done. */
if (!(vring_desc_flags(vq, i) & VRING_DESC_F_NEXT)) if (!(vring_desc_flags(desc_pa, i) & VRING_DESC_F_NEXT))
return vq->vring.num; return max;
/* Check they're not leading us off end of descriptors. */ /* 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! */ /* Make sure compiler knows to grab that: we don't want it changing! */
wmb(); wmb();
if (next >= vq->vring.num) { if (next >= max) {
fprintf(stderr, "Desc next is %u", next); fprintf(stderr, "Desc next is %u", next);
exit(1); 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) 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; int num_bufs, in_total, out_total;
idx = vq->last_avail_idx; idx = vq->last_avail_idx;
max = vq->vring.num;
num_bufs = in_total = out_total = 0; num_bufs = in_total = out_total = 0;
while (virtqueue_num_heads(vq, idx)) { 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++); i = virtqueue_get_head(vq, idx++);
do { do {
/* If we've got too many, that implies a descriptor loop. */ /* 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"); fprintf(stderr, "Looped descriptor");
exit(1); 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 && 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; return 1;
} else { } else {
if (out_bytes > 0 && 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; return 1;
} }
} while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num); } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
} }
return 0; 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) 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; target_phys_addr_t len;
if (!virtqueue_num_heads(vq, vq->last_avail_idx)) 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. */ /* When we start there are none of either input nor output. */
elem->out_num = elem->in_num = 0; elem->out_num = elem->in_num = 0;
max = vq->vring.num;
i = head = virtqueue_get_head(vq, vq->last_avail_idx++); i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
do { do {
struct iovec *sg; struct iovec *sg;
int is_write = 0; int is_write = 0;
if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) { if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
elem->in_addr[elem->in_num] = vring_desc_addr(vq, i); elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
sg = &elem->in_sg[elem->in_num++]; sg = &elem->in_sg[elem->in_num++];
is_write = 1; is_write = 1;
} else } else
sg = &elem->out_sg[elem->out_num++]; sg = &elem->out_sg[elem->out_num++];
/* Grab the first descriptor, and check it's OK. */ /* 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; 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) { if (sg->iov_base == NULL || len != sg->iov_len) {
fprintf(stderr, "virtio: trying to map MMIO memory\n"); 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 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"); fprintf(stderr, "Looped descriptor");
exit(1); 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; elem->index = head;