aboutsummaryrefslogtreecommitdiffstats
path: root/src/virtio-ring.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2010-05-20 16:36:32 +0300
committerKevin O'Connor <kevin@koconnor.net>2010-05-26 20:52:06 -0400
commit0f3783b3cc9be767182bce8e7aeadab64db4e0aa (patch)
treeb893dc2ecc86e3027b8162a135fb90773bdc23f3 /src/virtio-ring.c
parentbfe4d6044c579e4b66566d10b4e25f3297f6c4ab (diff)
downloadseabios-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.c13
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));
}