- mac_dbdma: Remove leftover `dma_memory_unmap` calls(CVE-2024-8612) - softmmu: Support concurrent bounce buffers(CVE-2024-8612) - system/physmem: Per-AddressSpace bounce buffering - system/physmem: Propagate AddressSpace to MapClient helpers Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com>
266 lines
8.9 KiB
Diff
266 lines
8.9 KiB
Diff
From 215731d484366474a90a2e14f3a75bb84fd314a3 Mon Sep 17 00:00:00 2001
|
|
From: Mattias Nissler <mnissler@rivosinc.com>
|
|
Date: Thu, 7 Sep 2023 06:04:23 -0700
|
|
Subject: [PATCH 2/4] system/physmem: Per-AddressSpace bounce buffering
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
cherry-pick from 69e78f1b3484e429274352a464a94fa1d78be339
|
|
|
|
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 <peterx@redhat.com>
|
|
Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
|
Signed-off-by: Mattias Nissler <mnissler@rivosinc.com>
|
|
Message-ID: <20240507094210.300566-2-mnissler@rivosinc.com>
|
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
|
[PMD: Split patch, part 2/2]
|
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
|
Signed-off-by: liuxiangdong <liuxiangdong5@huawei.com>
|
|
---
|
|
include/exec/memory.h | 19 +++++++++++
|
|
system/memory.c | 7 ++++
|
|
system/physmem.c | 79 ++++++++++++++++---------------------------
|
|
3 files changed, 56 insertions(+), 49 deletions(-)
|
|
|
|
diff --git a/include/exec/memory.h b/include/exec/memory.h
|
|
index 4b7dc7f055..40dcf70530 100644
|
|
--- a/include/exec/memory.h
|
|
+++ b/include/exec/memory.h
|
|
@@ -1106,6 +1106,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
|
|
*/
|
|
@@ -1124,6 +1137,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;
|
|
diff --git a/system/memory.c b/system/memory.c
|
|
index fb817e54bc..026e47dcb8 100644
|
|
--- a/system/memory.c
|
|
+++ b/system/memory.c
|
|
@@ -3117,6 +3117,9 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
|
|
as->ioeventfds = NULL;
|
|
QTAILQ_INIT(&as->listeners);
|
|
QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
|
|
+ as->bounce.in_use = false;
|
|
+ qemu_mutex_init(&as->map_client_list_lock);
|
|
+ QLIST_INIT(&as->map_client_list);
|
|
as->name = g_strdup(name ? name : "anonymous");
|
|
address_space_update_topology(as);
|
|
address_space_update_ioeventfds(as);
|
|
@@ -3124,6 +3127,10 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
|
|
|
|
static void do_address_space_destroy(AddressSpace *as)
|
|
{
|
|
+ assert(!qatomic_read(&as->bounce.in_use));
|
|
+ assert(QLIST_EMPTY(&as->map_client_list));
|
|
+ qemu_mutex_destroy(&as->map_client_list_lock);
|
|
+
|
|
assert(QTAILQ_EMPTY(&as->listeners));
|
|
|
|
flatview_unref(as->current_map);
|
|
diff --git a/system/physmem.c b/system/physmem.c
|
|
index 1d01e7a32b..4491a7dbd1 100644
|
|
--- a/system/physmem.c
|
|
+++ b/system/physmem.c
|
|
@@ -3021,26 +3021,8 @@ void cpu_flush_icache_range(hwaddr start, hwaddr len)
|
|
NULL, len, FLUSH_CACHE);
|
|
}
|
|
|
|
-typedef struct {
|
|
- MemoryRegion *mr;
|
|
- void *buffer;
|
|
- hwaddr addr;
|
|
- hwaddr len;
|
|
- bool in_use;
|
|
-} BounceBuffer;
|
|
-
|
|
-static BounceBuffer bounce;
|
|
-
|
|
-typedef struct MapClient {
|
|
- QEMUBH *bh;
|
|
- QLIST_ENTRY(MapClient) link;
|
|
-} MapClient;
|
|
-
|
|
-QemuMutex map_client_list_lock;
|
|
-static QLIST_HEAD(, MapClient) map_client_list
|
|
- = QLIST_HEAD_INITIALIZER(map_client_list);
|
|
-
|
|
-static void address_space_unregister_map_client_do(MapClient *client)
|
|
+static void
|
|
+address_space_unregister_map_client_do(AddressSpaceMapClient *client)
|
|
{
|
|
QLIST_REMOVE(client, link);
|
|
g_free(client);
|
|
@@ -3048,10 +3030,10 @@ static void address_space_unregister_map_client_do(MapClient *client)
|
|
|
|
static void address_space_notify_map_clients_locked(AddressSpace *as)
|
|
{
|
|
- MapClient *client;
|
|
+ AddressSpaceMapClient *client;
|
|
|
|
- while (!QLIST_EMPTY(&map_client_list)) {
|
|
- client = QLIST_FIRST(&map_client_list);
|
|
+ while (!QLIST_EMPTY(&as->map_client_list)) {
|
|
+ client = QLIST_FIRST(&as->map_client_list);
|
|
qemu_bh_schedule(client->bh);
|
|
address_space_unregister_map_client_do(client);
|
|
}
|
|
@@ -3059,17 +3041,17 @@ static void address_space_notify_map_clients_locked(AddressSpace *as)
|
|
|
|
void address_space_register_map_client(AddressSpace *as, QEMUBH *bh)
|
|
{
|
|
- MapClient *client = g_malloc(sizeof(*client));
|
|
+ AddressSpaceMapClient *client = g_malloc(sizeof(*client));
|
|
|
|
- qemu_mutex_lock(&map_client_list_lock);
|
|
+ qemu_mutex_lock(&as->map_client_list_lock);
|
|
client->bh = bh;
|
|
- QLIST_INSERT_HEAD(&map_client_list, client, link);
|
|
+ QLIST_INSERT_HEAD(&as->map_client_list, client, link);
|
|
/* Write map_client_list before reading in_use. */
|
|
smp_mb();
|
|
- if (!qatomic_read(&bounce.in_use)) {
|
|
+ if (!qatomic_read(&as->bounce.in_use)) {
|
|
address_space_notify_map_clients_locked(as);
|
|
}
|
|
- qemu_mutex_unlock(&map_client_list_lock);
|
|
+ qemu_mutex_unlock(&as->map_client_list_lock);
|
|
}
|
|
|
|
void cpu_exec_init_all(void)
|
|
@@ -3085,28 +3067,27 @@ void cpu_exec_init_all(void)
|
|
finalize_target_page_bits();
|
|
io_mem_init();
|
|
memory_map_init();
|
|
- qemu_mutex_init(&map_client_list_lock);
|
|
}
|
|
|
|
void address_space_unregister_map_client(AddressSpace *as, QEMUBH *bh)
|
|
{
|
|
- MapClient *client;
|
|
+ AddressSpaceMapClient *client;
|
|
|
|
- qemu_mutex_lock(&map_client_list_lock);
|
|
- QLIST_FOREACH(client, &map_client_list, link) {
|
|
+ qemu_mutex_lock(&as->map_client_list_lock);
|
|
+ QLIST_FOREACH(client, &as->map_client_list, link) {
|
|
if (client->bh == bh) {
|
|
address_space_unregister_map_client_do(client);
|
|
break;
|
|
}
|
|
}
|
|
- qemu_mutex_unlock(&map_client_list_lock);
|
|
+ qemu_mutex_unlock(&as->map_client_list_lock);
|
|
}
|
|
|
|
static void address_space_notify_map_clients(AddressSpace *as)
|
|
{
|
|
- qemu_mutex_lock(&map_client_list_lock);
|
|
+ qemu_mutex_lock(&as->map_client_list_lock);
|
|
address_space_notify_map_clients_locked(as);
|
|
- qemu_mutex_unlock(&map_client_list_lock);
|
|
+ qemu_mutex_unlock(&as->map_client_list_lock);
|
|
}
|
|
|
|
static bool flatview_access_valid(FlatView *fv, hwaddr addr, hwaddr len,
|
|
@@ -3197,25 +3178,25 @@ void *address_space_map(AddressSpace *as,
|
|
mr = flatview_translate(fv, addr, &xlat, &l, is_write, attrs);
|
|
|
|
if (!memory_access_is_direct(mr, is_write)) {
|
|
- if (qatomic_xchg(&bounce.in_use, true)) {
|
|
+ if (qatomic_xchg(&as->bounce.in_use, true)) {
|
|
*plen = 0;
|
|
return NULL;
|
|
}
|
|
/* Avoid unbounded allocations */
|
|
l = MIN(l, TARGET_PAGE_SIZE);
|
|
- bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l);
|
|
- bounce.addr = addr;
|
|
- bounce.len = l;
|
|
+ as->bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, l);
|
|
+ as->bounce.addr = addr;
|
|
+ as->bounce.len = l;
|
|
|
|
memory_region_ref(mr);
|
|
- bounce.mr = mr;
|
|
+ as->bounce.mr = mr;
|
|
if (!is_write) {
|
|
flatview_read(fv, addr, MEMTXATTRS_UNSPECIFIED,
|
|
- bounce.buffer, l);
|
|
+ as->bounce.buffer, l);
|
|
}
|
|
|
|
*plen = l;
|
|
- return bounce.buffer;
|
|
+ return as->bounce.buffer;
|
|
}
|
|
|
|
|
|
@@ -3233,7 +3214,7 @@ void *address_space_map(AddressSpace *as,
|
|
void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
|
|
bool is_write, hwaddr access_len)
|
|
{
|
|
- if (buffer != bounce.buffer) {
|
|
+ if (buffer != as->bounce.buffer) {
|
|
MemoryRegion *mr;
|
|
ram_addr_t addr1;
|
|
|
|
@@ -3249,14 +3230,14 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
|
|
return;
|
|
}
|
|
if (is_write) {
|
|
- address_space_write(as, bounce.addr, MEMTXATTRS_UNSPECIFIED,
|
|
- bounce.buffer, access_len);
|
|
+ address_space_write(as, as->bounce.addr, MEMTXATTRS_UNSPECIFIED,
|
|
+ as->bounce.buffer, access_len);
|
|
}
|
|
- qemu_vfree(bounce.buffer);
|
|
- bounce.buffer = NULL;
|
|
- memory_region_unref(bounce.mr);
|
|
+ qemu_vfree(as->bounce.buffer);
|
|
+ as->bounce.buffer = NULL;
|
|
+ memory_region_unref(as->bounce.mr);
|
|
/* Clear in_use before reading map_client_list. */
|
|
- qatomic_set_mb(&bounce.in_use, false);
|
|
+ qatomic_set_mb(&as->bounce.in_use, false);
|
|
address_space_notify_map_clients(as);
|
|
}
|
|
|
|
--
|
|
2.45.1.windows.1
|
|
|