On 2018年05月16日 20:32, Jason Wang wrote:
+static bool vhost_notify_packed(struct vhost_dev *dev,
+                               struct vhost_virtqueue *vq)
+{
+       __virtio16 event_off_wrap, event_flags;
+       __u16 old, new, off_wrap;
+       bool v;
+
+       /* Flush out used descriptors updates. This is paired
+        * with the barrier that the Guest executes when enabling
+        * interrupts.
+        */
+       smp_mb();
+
+       if (vhost_get_avail(vq, event_flags,
+                          &vq->driver_event->flags) < 0) {
+               vq_err(vq, "Failed to get driver desc_event_flags");
+               return true;
+       }
+
+       if (event_flags == cpu_to_vhost16(vq, RING_EVENT_FLAGS_DISABLE))
+               return false;
+       else if (event_flags == cpu_to_vhost16(vq, RING_EVENT_FLAGS_ENABLE))
+               return true;
+
+       /* Read desc event flags before event_off and event_wrap */
+       smp_rmb();
+
+       if (vhost_get_avail(vq, event_off_wrap,
+                           &vq->driver_event->off_warp) < 0) {
+               vq_err(vq, "Failed to get driver desc_event_off/wrap");
+               return true;
+       }
+
+       off_wrap = vhost16_to_cpu(vq, event_off_wrap);
+
+       old = vq->signalled_used;
+       v = vq->signalled_used_valid;
+       new = vq->signalled_used = vq->last_used_idx;
+       vq->signalled_used_valid = true;

We should move those idx tracking before checking event_flags. Otherwise we may lose interrupts because of a wrong signalled_used value.

Thanks

+
+       if (unlikely(!v))
+               return true;
+
+       return vhost_vring_packed_need_event(vq, off_wrap, new, old);
+}

Reply via email to