DF-5120 / fix.diff
--- virtio_random.c.orig +++ virtio_random.c @@ -193,7 +193,7 @@ static void vtrnd_harvest(struct vtrnd_softc *sc) { struct sglist_seg segs[1]; struct sglist sg; struct virtqueue *vq; uint32_t value; - int error; + int error, i; vq = sc->vtrnd_vq; @@ -209,9 +209,24 @@ vtrnd_harvest(struct vtrnd_softc *sc) /* * Poll for the response, but the command is likely already * done when we return from the notify. + * + * Bound the wait: virtqueue_poll() never returns while the host + * has not advanced the used ring, and this runs from the periodic + * softclock callout. A wedged host entropy backend must degrade + * to "no virtio entropy", not hang softclock forever. */ virtqueue_notify(vq, NULL); - virtqueue_poll(vq, NULL); + for (i = 0; i < 1000 && !virtqueue_pending(vq); i++) + DELAY(10); + if (!virtqueue_pending(vq)) { + /* + * Device did not complete within ~10ms. Leave the + * descriptor queued; the virtqueue_empty() check above + * then keeps disabling future harvests until reattach. + */ + return; + } + virtqueue_poll(vq, NULL); add_buffer_randomness_src((const char *)&value, sizeof(value), RAND_SRC_VIRTIO); |