The guest side must not manipulate the index for the used buffers. Instead, remember the state of the used buffer locally and wait until it has moved.
Signed-off-by: Cornelia Huck <[email protected]> --- pc-bios/s390-ccw/virtio.c | 10 +++++++--- pc-bios/s390-ccw/virtio.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 49f2d29..03f6fde 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -150,8 +150,6 @@ static void vring_send_buf(struct vring *vr, void *p, int len, int flags) if (!(flags & VRING_DESC_F_NEXT)) { vr->avail->idx++; } - - vr->used->idx = vr->next_idx; } static u64 get_clock(void) @@ -180,7 +178,13 @@ static int vring_wait_reply(struct vring *vr, int timeout) struct subchannel_id schid = vr->schid; int r = 0; - while (vr->used->idx == vr->next_idx) { + vr->used_idx = vr->used->idx; + /* + * Wait until the used index has moved. + * Note: This is only race-free if the host doesn't start draining + * the queue out of its own accord. + */ + while (vr->used->idx == vr->used_idx) { vring_notify(schid); if (timeout && (get_second() >= target_second)) { r = 1; diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index 86fdd57..772a63f 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -115,6 +115,7 @@ struct vring_used { struct vring { unsigned int num; int next_idx; + int used_idx; struct vring_desc *desc; struct vring_avail *avail; struct vring_used *used; -- 1.8.3.4
