@@ -208,6 +208,7 @@ struct AddressSpace {
char *name;
MemoryRegion *root;
int ref_count;
+ bool malloced;
struct FlatView *current_map;
int ioeventfd_nb;
struct MemoryRegionIoeventfd *ioeventfds;
@@ -977,6 +978,8 @@ void mtree_info(fprintf_function mon_printf, void *f);
*/
void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name);
+AddressSpace *address_space_init_shareable(MemoryRegion *root,
+ const char *name);
/**
* address_space_destroy: destroy an address space
@@ -1932,6 +1932,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
memory_region_transaction_begin();
as->ref_count = 1;
as->root = root;
+ as->malloced = false;
as->current_map = g_new(FlatView, 1);
flatview_init(as->current_map);
as->ioeventfd_nb = 0;
@@ -1943,6 +1944,27 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
memory_region_transaction_commit();
}
+AddressSpace *address_space_init_shareable(MemoryRegion *root, const char *name)
+{
+ AddressSpace *as;
+
+ if (!root) {
+ return NULL;
+ }
+
+ QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
+ if (root == as->root && !strcmp(name ? name : "anonymous", as->name)) {
+ as->ref_count++;
+ return as;
+ }
+ }
+
+ as = g_malloc0(sizeof *as);
+ address_space_init(as, root, name);
+ as->malloced = true;
+ return as;
+}
+
void address_space_destroy(AddressSpace *as)
{
MemoryListener *listener;
@@ -1965,6 +1987,9 @@ void address_space_destroy(AddressSpace *as)
flatview_unref(as->current_map);
g_free(as->name);
g_free(as->ioeventfds);
+ if (as->malloced) {
+ g_free(as);
+ }
}
bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
This will either create a new AS or return a pointer to an already existing equivalent one. Both name and root mr must match. The motivation is to reuse address spaces as much as possible. It's going to be quite common that bus masters out in device land have pointers to the same memory region for their mastering yet each will need to create its own address space. Let the memory API implement sharing for them. Aside from the perf optimisations, this should reduce the amount of redundant output on info mtree as well. Thee returned value will be malloced, but the malloc will be automatically freed when the AS runs out of refs. Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com> --- We could change the equivalency test only match mr to support device specific naming of these shared ASes. The singleton AS can ultimately only have one name however. So perhaps some strcatting each time a new sharer is added to the share. That or first-in-best-dressed. Changed since v1: Implement ref counting and garbage collection. include/exec/memory.h | 3 +++ memory.c | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+)