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