diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2010-05-20 16:36:32 +0300 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2010-05-26 20:52:06 -0400 |
commit | 0f3783b3cc9be767182bce8e7aeadab64db4e0aa (patch) | |
tree | b893dc2ecc86e3027b8162a135fb90773bdc23f3 /src/virtio-ring.c | |
parent | bfe4d6044c579e4b66566d10b4e25f3297f6c4ab (diff) | |
download | seabios-0f3783b3cc9be767182bce8e7aeadab64db4e0aa.tar.gz |
virtio: clean up memory barrier usage
cleanup memory barrier usage bringing it
in sync with what linux guest does.
The rules are simple:
- read barrier after index read
- write barrier before index write
Also, call macros smp_rmb/smp_wmb to stress
we are not syncing with a real io device here.
While I don't think compiler is crazy/powerful
enough to reorder these, anyway, the bogus
barriers we currently have in code will confuse
anyone who tries to copy/reuse it.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Cc: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'src/virtio-ring.c')
-rw-r--r-- | src/virtio-ring.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/src/virtio-ring.c b/src/virtio-ring.c index 493d8b5e..97a3ffee 100644 --- a/src/virtio-ring.c +++ b/src/virtio-ring.c @@ -38,8 +38,10 @@ int vring_more_used(struct vring_virtqueue *vq) { struct vring_used *used = GET_FLATPTR(vq->vring.used); - wmb(); - return GET_FLATPTR(vq->last_used_idx) != GET_FLATPTR(used->idx); + int more = GET_FLATPTR(vq->last_used_idx) != GET_FLATPTR(used->idx); + /* Make sure ring reads are done after idx read above. */ + smp_rmb(); + return more; } /* @@ -63,7 +65,6 @@ void vring_detach(struct vring_virtqueue *vq, unsigned int head) /* link it with free list and point to it */ SET_FLATPTR(desc[i].next, GET_FLATPTR(vq->free_head)); - wmb(); SET_FLATPTR(vq->free_head, head); } @@ -85,7 +86,6 @@ int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len) // BUG_ON(!vring_more_used(vq)); elem = &used->ring[GET_FLATPTR(vq->last_used_idx) % GET_FLATPTR(vr->num)]; - wmb(); id = GET_FLATPTR(elem->id); if (len != NULL) *len = GET_FLATPTR(elem->len); @@ -136,7 +136,6 @@ void vring_add_buf(struct vring_virtqueue *vq, av = (GET_FLATPTR(avail->idx) + num_added) % GET_FLATPTR(vr->num); SET_FLATPTR(avail->ring[av], head); - wmb(); } void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) @@ -144,9 +143,9 @@ void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) struct vring *vr = &vq->vring; struct vring_avail *avail = GET_FLATPTR(vr->avail); - wmb(); + /* Make sure idx update is done after ring write. */ + smp_wmb(); SET_FLATPTR(avail->idx, GET_FLATPTR(avail->idx) + num_added); - mb(); vp_notify(ioaddr, GET_FLATPTR(vq->queue_index)); } |