This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 36f7c85610df91391ece91135470b1f1cfdb9443 Author: wangyongrong <[email protected]> AuthorDate: Mon Jul 6 19:22:50 2026 +0800 drivers/virtio/virtio-rng: map the user buffer instead of copying it virtio-rng allocated a scratch buffer via virtio_zalloc_buf and memcpy'd it back to the caller, adding a copy on MMIO/PCI where the device can write the user buffer directly. Switch to virtio_map_buf and virtio_unmap_buf so MMIO/PCI is zero-copy (map returns the buffer as is), while rptun keeps bouncing through shared memory unchanged. Signed-off-by: wangyongrong <[email protected]> Signed-off-by: Bowen Wang <[email protected]> --- drivers/virtio/virtio-rng.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/virtio/virtio-rng.c b/drivers/virtio/virtio-rng.c index ea9cb1397ae..3f217e588c5 100644 --- a/drivers/virtio/virtio-rng.c +++ b/drivers/virtio/virtio-rng.c @@ -152,6 +152,7 @@ static ssize_t virtio_rng_read(FAR struct file *filep, FAR char *buffer, FAR struct virtqueue *vq = priv->vdev->vrings_info[0].vq; struct virtio_rng_cookie_s cookie; struct virtqueue_buf vb; + FAR void *mapped; irqstate_t flags; int ret; @@ -160,23 +161,34 @@ static ssize_t virtio_rng_read(FAR struct file *filep, FAR char *buffer, cookie.len = 0; nxsem_init(&cookie.sem, 0, 0); + /* Map the user buffer so the device side can access it. On MMIO/PCI + * map returns the buffer itself and the device writes the entropy straight + * into it (zero copy); a transport that cannot reach it (rptun, or a user + * buffer with CONFIG_ARCH_ADDRENV) bounces it and unmap copies the result + * back below. + */ + + ret = virtio_map_buf(priv->vdev, buffer, buflen, VIRTIO_DMA_FROM_DEVICE, + &mapped); + if (ret < 0) + { + return ret; + } + /* Add the input buffer to the virtqueue, and the cookie as the virtqueue * cookie. (virtqueue_get_buffer() will return cookie). */ vb.len = buflen; - vb.buf = virtio_zalloc_buf(priv->vdev, buflen, 16); - if (vb.buf == NULL) - { - return -ENOMEM; - } + vb.buf = mapped; flags = spin_lock_irqsave(&priv->lock); ret = virtqueue_add_buffer(vq, &vb, 0, 1, &cookie); if (ret < 0) { spin_unlock_irqrestore(&priv->lock, flags); - virtio_free_buf(priv->vdev, vb.buf); + virtio_unmap_buf(priv->vdev, buffer, 0, VIRTIO_DMA_FROM_DEVICE, + mapped); return ret; } @@ -188,8 +200,13 @@ static ssize_t virtio_rng_read(FAR struct file *filep, FAR char *buffer, /* Wait for completion */ nxsem_wait_uninterruptible(&cookie.sem); - memcpy(buffer, vb.buf, cookie.len); - virtio_free_buf(priv->vdev, vb.buf); + + /* Unmap copies a bounce back into the user buffer and is a no-op when the + * device wrote it directly. Only cookie.len bytes are valid. + */ + + virtio_unmap_buf(priv->vdev, buffer, cookie.len, VIRTIO_DMA_FROM_DEVICE, + mapped); return cookie.len; }
