/* Enable guest->host notifies * * Return true if the vring is empty, false if there are more requests. */ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring) { if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = vring->vr.avail->idx; } else { vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY); } smp_mb(); /* ensure update is seen before reading avail_idx */ return !vring_more_avail(vdev, vring); }
/* Enable guest->host notifies * * Return true if the vring is empty, false if there are more requests. */ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring) { if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = vring->vr.avail->idx; } else { vring->vr.used->flags &= ~VRING_USED_F_NO_NOTIFY; } smp_mb(); /* ensure update is seen before reading avail_idx */ return !vring_more_avail(vring); }
bool virtio_queue_available(struct virtio_queue *vq) { if (!vq->addr || !vq->vring.avail) { return FALSE; } vring_avail_event(&vq->vring) = vq->last_avail_idx; return vq->vring.avail->idx != vq->last_avail_idx; }
void virtio_queue_set_notification(VirtQueue *vq, int enable) { vq->notification = enable; if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(vq, vring_avail_idx(vq)); } else if (enable) { vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY); } else { vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY); } }
void virtio_queue_set_notification(VirtQueue *vq, int enable) { vq->notification = enable; if (bUsePublishedIndices) { vring_avail_event(vq, vring_avail_idx(vq)); } else if (enable) { vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY); } else { vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY); } }
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); }
void virtio_queue_set_notification(VirtQueue *vq, int enable) { vq->notification = enable; if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(vq, vring_avail_idx(vq)); } else if (enable) { vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY); } else { vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY); } if (enable) { /* Expose avail event/used flags before caller checks the avail idx. */ smp_mb(); } }
bool enable_kick() { unsigned head = host.used_idx; vring_avail_event(&ring) = head; /* Barrier C (for pairing) */ smp_mb(); #ifdef RING_POLL { unsigned index = ring.avail->ring[head & (ring_size - 1)]; return (index ^ head ^ 0x8000) & ~(ring_size - 1); } #else return head == ring.avail->idx; #endif }