From: wafer Xie <[email protected]>

Use a shared indirect descriptor array to store all indirect descriptors.
If the current indirect buffer does not have enough freed descriptors 
to accommodate the SVQ descriptors, 
descriptors can be borrowed from the next indirect buffer.

Suggested-by: Eugenio P??rez <[email protected]>
Signed-off-by: wafer Xie <[email protected]>
---
 hw/virtio/vhost-shadow-virtqueue.h | 48 ++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/hw/virtio/vhost-shadow-virtqueue.h 
b/hw/virtio/vhost-shadow-virtqueue.h
index 9c273739d6..a50baff615 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,44 @@ 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 segment
+ * Each SVQ has multiple segments that share a contiguous memory region
+ */
+typedef struct SVQIndirectDescBuf {
+    uint16_t start_idx;         /* Start index in the shared descriptor table 
*/
+    uint16_t num_descs;         /* Current number of descs in this segment */
+    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 (relative) */
+    uint16_t borrowed_descs;    /* Number of descs borrowed from next buffer */
+    SVQIndirectBufState state;  /* Current state of this buffer */
+} SVQIndirectDescBuf;
+
+/* Number of indirect descriptor buffers per SVQ for mulit-buffering */
+#define SVQ_NUM_INDIRECT_BUFS 4
+
+/**
+ * Indirect descriptor information for a shadow virtqueue
+ */
+typedef struct SVQIndirectInfo {
+    vring_desc_t *desc;           /* Shared descriptor table */
+    hwaddr iova;                  /* IOVA of the shared table */
+    size_t size;                  /* Size of the mmap'd region */
+    uint16_t total_descs;         /* Total number of descs in shared table */
+    int current_buf;              /* Current active buffer index, -1 if none */
+    bool enabled;                 /* Whether indirect descriptors are enabled 
*/
+    SVQIndirectDescBuf bufs[SVQ_NUM_INDIRECT_BUFS]; /* Buffer segments */
+} SVQIndirectInfo;
+
 /* Shadow virtqueue to relay notifications */
 typedef struct VhostShadowVirtqueue {
     /* Shadow vring */
@@ -96,6 +141,9 @@ typedef struct VhostShadowVirtqueue {
     /* Caller callbacks opaque */
     void *ops_opaque;
 
+    /* Indirect descriptor info */
+    SVQIndirectInfo indirect;
+
     /* Next head to expose to the device */
     uint16_t shadow_avail_idx;
 
-- 
2.34.1


Reply via email to