static void vring_kick(struct virtqueue *_vq) { u16 prev_avail_idx; struct vring_virtqueue *vq = to_vvq(_vq); /* Descriptors and available array need to be set before we expose the * new available array entries. */ mb(); prev_avail_idx = vq->vring.avail->idx - (u16) vq->num_added; DPrintf(4, ("%s>>> vq->vring.avail->idx %d\n", __FUNCTION__, vq->vring.avail->idx)); vq->num_added = 0; /* Need to update avail index before checking if we should notify */ mb(); if(vq->use_published_indices) { if(vring_need_event(vring_last_avail(&vq->vring), vq->vring.avail->idx, prev_avail_idx)) vq->notify(&vq->vq); } else { if (!(vq->vring.used->flags & VRING_USED_F_NO_NOTIFY)) /* Prod other side to tell it about changes. */ vq->notify(&vq->vq); } }
void call_used(void) { /* Flush in previous flags write */ /* Barrier D (for pairing) */ smp_mb(); if (!vring_need_event(vring_used_event(&ring), host.used_idx, host.called_used_idx)) return; host.called_used_idx = host.used_idx; call(); }
void kick_available(void) { /* Flush in previous flags write */ /* Barrier C (for pairing) */ smp_mb(); if (!vring_need_event(vring_avail_event(&ring), guest.avail_idx, guest.kicked_avail_idx)) return; guest.kicked_avail_idx = guest.avail_idx; kick(); }
/** * * vq_ring_must_notify_host * */ static int vq_ring_must_notify_host(struct virtqueue *vq) { uint16_t new_idx, prev_idx, event_idx; if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { new_idx = vq->vq_ring.avail->idx; prev_idx = new_idx - vq->vq_queued_cnt; event_idx = vring_avail_event(&vq->vq_ring); return (vring_need_event(event_idx, new_idx, prev_idx) != 0); } return ((vq->vq_ring.used->flags & VRING_USED_F_NO_NOTIFY) == 0); }
bool virtio_queue_should_signal(struct virtio_queue *vq) { u16 old_idx, new_idx, event_idx; if (!vq->addr) { return FALSE; } old_idx = vq->last_used_signalled; new_idx = vq->vring.used->idx; event_idx = vring_used_event(&vq->vring); if (vring_need_event(event_idx, new_idx, old_idx)) { vq->last_used_signalled = new_idx; return TRUE; } return FALSE; }
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); }