void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len, unsigned int idx) { unsigned int offset; int i; trace_virtqueue_fill(vq, elem, len, idx); offset = 0; for (i = 0; i < elem->in_num; i++) { size_t size = MIN(len - offset, elem->in_sg[i].iov_len); cpu_physical_memory_unmap(elem->in_sg[i].iov_base, elem->in_sg[i].iov_len, 1, size); offset += size; } for (i = 0; i < elem->out_num; i++) cpu_physical_memory_unmap(elem->out_sg[i].iov_base, elem->out_sg[i].iov_len, 0, elem->out_sg[i].iov_len); idx = (idx + vring_used_idx(vq)) % vq->vring.num; /* Get a pointer to the next entry in the used ring. */ vring_used_ring_id(vq, idx, elem->index); vring_used_ring_len(vq, idx, len); }
static bool vring_notify(PVOID unused, VirtQueue *vq) { uint16_t old, _new; bool v; /* Always notify when queue is empty (when feature acknowledge) */ //if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) && if ((bVirtioF_NotifyOnEmpty && !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) { return TRUE; } //if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) { if (!bUsePublishedIndices) { return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT); } v = vq->signalled_used_valid; vq->signalled_used_valid = TRUE; old = vq->signalled_used; _new = vq->signalled_used = vring_used_idx(vq); return !v || vring_need_event(vring_used_event(vq), _new, old); }
0, elem->out_sg[i].iov_len); idx = (idx + vring_used_idx(vq)) % vq->vring.num; /* Get a pointer to the next entry in the used ring. */ vring_used_ring_id(vq, idx, elem->index); vring_used_ring_len(vq, idx, len); } void virtqueue_flush(VirtQueue *vq, unsigned int count) { uint16_t old, new; /* Make sure buffer is written before we update index. */ smp_wmb(); trace_virtqueue_flush(vq, count); old = vring_used_idx(vq); new = old + count; vring_used_idx_set(vq, new); vq->inuse -= count; if (unlikely((int16_t)(new - vq->signalled_used) < (uint16_t)(new - old))) vq->signalled_used_valid = false; } void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len) { virtqueue_fill(vq, elem, len, 0); virtqueue_flush(vq, 1); } static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
static inline void vring_used_idx_increment(VirtQueue *vq, uint16_t val) { target_phys_addr_t pa; pa = vq->vring.used + offsetof(VRingUsed, idx); stw_phys(pa, vring_used_idx(vq) + val); }