mirror of https://github.com/xemu-project/xemu.git
system/physmem: Per-AddressSpace bounce buffering
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>
This commit is contained in:
parent
5c62719710
commit
69e78f1b34
|
@ -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;
|
||||
|
|
|
@ -3174,6 +3174,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);
|
||||
|
@ -3181,6 +3184,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);
|
||||
|
|
|
@ -3047,26 +3047,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);
|
||||
|
@ -3074,10 +3056,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);
|
||||
}
|
||||
|
@ -3085,14 +3067,14 @@ 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_LOCK_GUARD(&map_client_list_lock);
|
||||
QEMU_LOCK_GUARD(&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);
|
||||
}
|
||||
}
|
||||
|
@ -3110,15 +3092,14 @@ 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_LOCK_GUARD(&map_client_list_lock);
|
||||
QLIST_FOREACH(client, &map_client_list, link) {
|
||||
QEMU_LOCK_GUARD(&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;
|
||||
|
@ -3128,7 +3109,7 @@ void address_space_unregister_map_client(AddressSpace *as, QEMUBH *bh)
|
|||
|
||||
static void address_space_notify_map_clients(AddressSpace *as)
|
||||
{
|
||||
QEMU_LOCK_GUARD(&map_client_list_lock);
|
||||
QEMU_LOCK_GUARD(&as->map_client_list_lock);
|
||||
address_space_notify_map_clients_locked(as);
|
||||
}
|
||||
|
||||
|
@ -3220,25 +3201,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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3256,7 +3237,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;
|
||||
|
||||
|
@ -3272,14 +3253,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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue