1 #include <linux/virtio_ring.h> 2 #include <stdint.h> 3 #include <sys/uio.h> 4 #include <asm/system.h> 5 #include "kvm/kvm.h" 6 #include "kvm/virtio.h" 7 8 struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, uint32_t head, uint32_t len) 9 { 10 struct vring_used_elem *used_elem; 11 used_elem = &queue->vring.used->ring[queue->vring.used->idx % queue->vring.num]; 12 used_elem->id = head; 13 used_elem->len = len; 14 15 /* 16 * Use wmb to assure that used elem was updated with head and len. 17 * We need a wmb here since we can't advance idx unless we're ready 18 * to pass the used element to the guest. 19 */ 20 wmb(); 21 queue->vring.used->idx++; 22 23 /* 24 * Use wmb to assure used idx has been increased before we signal the guest. 25 * Without a wmb here the guest may ignore the queue since it won't see 26 * an updated idx. 27 */ 28 wmb(); 29 30 return used_elem; 31 } 32 33 uint16_t virt_queue__get_iov(struct virt_queue *queue, struct iovec iov[], uint16_t *out, uint16_t *in, struct kvm *kvm) 34 { 35 struct vring_desc *desc; 36 uint16_t head, idx; 37 38 idx = head = virt_queue__pop(queue); 39 *out = *in = 0; 40 41 do { 42 desc = virt_queue__get_desc(queue, idx); 43 iov[*out + *in].iov_base = guest_flat_to_host(kvm, desc->addr); 44 iov[*out + *in].iov_len = desc->len; 45 if (desc->flags & VRING_DESC_F_WRITE) 46 (*in)++; 47 else 48 (*out)++; 49 if (desc->flags & VRING_DESC_F_NEXT) 50 idx = desc->next; 51 else 52 break; 53 } while (1); 54 55 return head; 56 } 57