On Tue, Dec 16, 2025 at 2:55 AM Wafer Xie <[email protected]> wrote:
>
> From: wafer Xie <[email protected]>
>
> Using multiple statically allocated buffers to store virtio indirect
> descriptors
>
> Signed-off-by: wafer Xie <[email protected]>
> ---
> hw/virtio/vhost-shadow-virtqueue.h | 46 ++++++++++++++++++++++++++++++
> 1 file changed, 46 insertions(+)
>
> diff --git a/hw/virtio/vhost-shadow-virtqueue.h
> b/hw/virtio/vhost-shadow-virtqueue.h
> index 9c273739d6..b0f236f049 100644
> --- a/hw/virtio/vhost-shadow-virtqueue.h
> +++ b/hw/virtio/vhost-shadow-virtqueue.h
> @@ -23,6 +23,13 @@ typedef struct SVQDescState {
> * guest's
> */
> unsigned int ndescs;
> +
> + /*
> + * Index into the indirect descriptor
> + * buffer (0 to SVQ_NUM_INDIRECT_BUFS - 1) if using indirect.
> + * -1 if not using indirect descriptors.
> + */
> + int indirect_buf_idx;
> } SVQDescState;
>
> typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
> @@ -46,6 +53,32 @@ typedef struct VhostShadowVirtqueueOps {
> VirtQueueAvailCallback avail_handler;
> } VhostShadowVirtqueueOps;
>
> +/**
> + * State of an indirect descriptor buffer
> + */
> +typedef enum SVQIndirectBufState {
> + SVQ_INDIRECT_BUF_FREED, /* Buffer is free and can be used */
> + SVQ_INDIRECT_BUF_FREEING, /* Buffer is being freed */
> +} SVQIndirectBufState;
> +
> +/**
> + * Pre-allocated indirect descriptor buffer
> + * Each SVQ has two of these buffers for double-buffering
What does the double buffering improve here compared to just doubling the size?
> + */
> +typedef struct SVQIndirectDescBuf {
> + vring_desc_t *desc; /* Descriptor table size = num_descs) */
> + hwaddr iova; /* IOVA of the descriptor table */
> + size_t size; /* Size of the mmap'd region */
> + SVQIndirectBufState state; /* Current state of this buffer */
> + uint16_t num_descs; /* Total number of descs (N * vring.num) */
> + uint16_t freed_descs; /* Number of descriptors available for use */
> + uint16_t freeing_descs; /* Number of descs being freed from used
> ring */
> + uint16_t freed_head; /* Next free descriptor index in this buffer
> */
> +} SVQIndirectDescBuf;
> +
> +/* Number of indirect descriptor buffers per SVQ for double-buffering */
> +#define SVQ_NUM_INDIRECT_BUFS 2
> +
> /* Shadow virtqueue to relay notifications */
> typedef struct VhostShadowVirtqueue {
> /* Shadow vring */
> @@ -96,6 +129,19 @@ typedef struct VhostShadowVirtqueue {
> /* Caller callbacks opaque */
> void *ops_opaque;
>
> + /*
> + * Pre-allocated indirect descriptor buffers for double-buffering.
> + * These are allocated when SVQ starts if VIRTIO_RING_F_INDIRECT_DESC
> + * is negotiated.
> + */
> + SVQIndirectDescBuf indirect_bufs[SVQ_NUM_INDIRECT_BUFS];
> +
> + /* Index of the current active indirect buffer, -1 if not using */
> + int current_indirect_buf;
> +
> + /* Whether indirect descriptors are enabled */
> + bool indirect_enabled;
> +
> /* Next head to expose to the device */
> uint16_t shadow_avail_idx;
>
> --
> 2.48.1
>