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
>


Reply via email to