Re: [PATCH v9 1/5] softmmu: Per-AddressSpace bounce buffering

2024-05-07 Thread Philippe Mathieu-Daudé

On 7/5/24 11:42, Mattias Nissler wrote:

Instead of using a single global bounce buffer, give each AddressSpace
its own bounce buffer. The MapClient callback mechanism moves to
AddressSpace accordingly.

This is in preparation for generalizing bounce buffer handling further
to allow multiple bounce buffers, with a total allocation limit
configured per AddressSpace.

Reviewed-by: Peter Xu 
Tested-by: Jonathan Cameron 
Signed-off-by: Mattias Nissler 
---
  include/exec/cpu-common.h |   2 -
  include/exec/memory.h |  45 -
  system/dma-helpers.c  |   4 +-
  system/memory.c   |   7 +++
  system/physmem.c  | 101 --
  5 files changed, 93 insertions(+), 66 deletions(-)


This patch has been split in 2 simpler -- IMHO -- parts here:
https://lore.kernel.org/qemu-devel/20240507123025.93391-1-phi...@linaro.org/




[PATCH v9 1/5] softmmu: Per-AddressSpace bounce buffering

2024-05-07 Thread Mattias Nissler
Instead of using a single global bounce buffer, give each AddressSpace
its own bounce buffer. The MapClient callback mechanism moves to
AddressSpace accordingly.

This is in preparation for generalizing bounce buffer handling further
to allow multiple bounce buffers, with a total allocation limit
configured per AddressSpace.

Reviewed-by: Peter Xu 
Tested-by: Jonathan Cameron 
Signed-off-by: Mattias Nissler 
---
 include/exec/cpu-common.h |   2 -
 include/exec/memory.h |  45 -
 system/dma-helpers.c  |   4 +-
 system/memory.c   |   7 +++
 system/physmem.c  | 101 --
 5 files changed, 93 insertions(+), 66 deletions(-)

diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 8bc397e251..815342d043 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -147,8 +147,6 @@ void *cpu_physical_memory_map(hwaddr addr,
   bool is_write);
 void cpu_physical_memory_unmap(void *buffer, hwaddr len,
bool is_write, hwaddr access_len);
-void cpu_register_map_client(QEMUBH *bh);
-void cpu_unregister_map_client(QEMUBH *bh);
 
 bool cpu_physical_memory_is_io(hwaddr phys_addr);
 
diff --git a/include/exec/memory.h b/include/exec/memory.h
index dadb5cd65a..d417d7f363 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1112,6 +1112,19 @@ struct MemoryListener {
 QTAILQ_ENTRY(MemoryListener) link_as;
 };
 
+typedef struct AddressSpaceMapClient {
+QEMUBH *bh;
+QLIST_ENTRY(AddressSpaceMapClient) link;
+} AddressSpaceMapClient;
+
+typedef struct {
+MemoryRegion *mr;
+void *buffer;
+hwaddr addr;
+hwaddr len;
+bool in_use;
+} BounceBuffer;
+
 /**
  * struct AddressSpace: describes a mapping of addresses to #MemoryRegion 
objects
  */
@@ -1129,6 +1142,12 @@ struct AddressSpace {
 struct MemoryRegionIoeventfd *ioeventfds;
 QTAILQ_HEAD(, MemoryListener) listeners;
 QTAILQ_ENTRY(AddressSpace) address_spaces_link;
+
+/* Bounce buffer to use for this address space. */
+BounceBuffer bounce;
+/* List of callbacks to invoke when buffers free up */
+QemuMutex map_client_list_lock;
+QLIST_HEAD(, AddressSpaceMapClient) map_client_list;
 };
 
 typedef struct AddressSpaceDispatch AddressSpaceDispatch;
@@ -2946,8 +2965,8 @@ bool address_space_access_valid(AddressSpace *as, hwaddr 
addr, hwaddr len,
  * May return %NULL and set *@plen to zero(0), if resources needed to perform
  * the mapping are exhausted.
  * Use only for reads OR writes - not for read-modify-write operations.
- * Use cpu_register_map_client() to know when retrying the map operation is
- * likely to succeed.
+ * Use address_space_register_map_client() to know when retrying the map
+ * operation is likely to succeed.
  *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
@@ -2972,6 +2991,28 @@ void *address_space_map(AddressSpace *as, hwaddr addr,
 void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
  bool is_write, hwaddr access_len);
 
+/*
+ * address_space_register_map_client: Register a callback to invoke when
+ * resources for address_space_map() are available again.
+ *
+ * address_space_map may fail when there are not enough resources available,
+ * such as when bounce buffer memory would exceed the limit. The callback can
+ * be used to retry the address_space_map operation. Note that the callback
+ * gets automatically removed after firing.
+ *
+ * @as: #AddressSpace to be accessed
+ * @bh: callback to invoke when address_space_map() retry is appropriate
+ */
+void address_space_register_map_client(AddressSpace *as, QEMUBH *bh);
+
+/*
+ * address_space_unregister_map_client: Unregister a callback that has
+ * previously been registered and not fired yet.
+ *
+ * @as: #AddressSpace to be accessed
+ * @bh: callback to unregister
+ */
+void address_space_unregister_map_client(AddressSpace *as, QEMUBH *bh);
 
 /* Internal functions, part of the implementation of address_space_read.  */
 MemTxResult address_space_read_full(AddressSpace *as, hwaddr addr,
diff --git a/system/dma-helpers.c b/system/dma-helpers.c
index 9b221cf94e..74013308f5 100644
--- a/system/dma-helpers.c
+++ b/system/dma-helpers.c
@@ -169,7 +169,7 @@ static void dma_blk_cb(void *opaque, int ret)
 if (dbs->iov.size == 0) {
 trace_dma_map_wait(dbs);
 dbs->bh = aio_bh_new(ctx, reschedule_dma, dbs);
-cpu_register_map_client(dbs->bh);
+address_space_register_map_client(dbs->sg->as, dbs->bh);
 return;
 }
 
@@ -197,7 +197,7 @@ static void dma_aio_cancel(BlockAIOCB *acb)
 }
 
 if (dbs->bh) {
-cpu_unregister_map_client(dbs->bh);
+address_space_unregister_map_client(dbs->sg->as, dbs->bh);
 qemu_bh_delete(dbs->bh);
 dbs->bh = NULL;
 }
diff --git a/system/memory.c b/system/memory.c
index 49f1cb2c38..642a449f8c 100644