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
+ */
+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