memory: Add address_space_init_shareable()

This will either create a new AS or return a pointer to an
already existing equivalent one, if we have already created
an AS for the specified root memory region.

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.

Backports commit f0c02d15b57da6f5463e3768aa0cfeedccf4b8f4 from qemu
This commit is contained in:
Peter Crosthwaite 2018-02-17 23:37:43 -05:00 committed by Lioncash
parent 73efe6cda3
commit b82e711a65
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
16 changed files with 88 additions and 9 deletions

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_aarch64
#define address_space_init address_space_init_aarch64
#define address_space_init_dispatch address_space_init_dispatch_aarch64
#define address_space_init_shareable address_space_init_shareable_aarch64
#define address_space_lookup_region address_space_lookup_region_aarch64
#define address_space_map address_space_map_aarch64
#define address_space_read address_space_read_aarch64

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_aarch64eb
#define address_space_init address_space_init_aarch64eb
#define address_space_init_dispatch address_space_init_dispatch_aarch64eb
#define address_space_init_shareable address_space_init_shareable_aarch64eb
#define address_space_lookup_region address_space_lookup_region_aarch64eb
#define address_space_map address_space_map_aarch64eb
#define address_space_read address_space_read_aarch64eb

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_arm
#define address_space_init address_space_init_arm
#define address_space_init_dispatch address_space_init_dispatch_arm
#define address_space_init_shareable address_space_init_shareable_arm
#define address_space_lookup_region address_space_lookup_region_arm
#define address_space_map address_space_map_arm
#define address_space_read address_space_read_arm

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_armeb
#define address_space_init address_space_init_armeb
#define address_space_init_dispatch address_space_init_dispatch_armeb
#define address_space_init_shareable address_space_init_shareable_armeb
#define address_space_lookup_region address_space_lookup_region_armeb
#define address_space_map address_space_map_armeb
#define address_space_read address_space_read_armeb

View file

@ -97,6 +97,7 @@ symbols = (
'address_space_get_flatview',
'address_space_init',
'address_space_init_dispatch',
'address_space_init_shareable',
'address_space_lookup_region',
'address_space_map',
'address_space_read',

View file

@ -219,6 +219,8 @@ struct AddressSpace {
/* All fields are private. */
char *name;
MemoryRegion *root;
int ref_count;
bool malloced;
struct FlatView *current_map;
struct AddressSpaceDispatch *dispatch;
struct AddressSpaceDispatch *next_dispatch;
@ -901,6 +903,23 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
*/
void address_space_init(struct uc_struct *uc, AddressSpace *as, MemoryRegion *root, const char *name);
/**
* address_space_init_shareable: return an address space for a memory region,
* creating it if it does not already exist
*
* @root: a #MemoryRegion that routes addresses for the address space
* @name: an address space name. The name is only used for debugging
* output.
*
* This function will return a pointer to an existing AddressSpace
* which was initialized with the specified MemoryRegion, or it will
* create and initialize one if it does not already exist. The ASes
* are reference-counted, so the memory will be freed automatically
* when the AddressSpace is destroyed via address_space_destroy.
*/
AddressSpace *address_space_init_shareable(struct uc_struct* uc,
MemoryRegion *root,
const char *name);
/**
* address_space_destroy: destroy an address space

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_m68k
#define address_space_init address_space_init_m68k
#define address_space_init_dispatch address_space_init_dispatch_m68k
#define address_space_init_shareable address_space_init_shareable_m68k
#define address_space_lookup_region address_space_lookup_region_m68k
#define address_space_map address_space_map_m68k
#define address_space_read address_space_read_m68k

View file

@ -1679,8 +1679,10 @@ void address_space_init(struct uc_struct *uc, AddressSpace *as, MemoryRegion *ro
}
memory_region_transaction_begin(uc);
as->ref_count = 1;
as->uc = uc;
as->root = root;
as->malloced = false;
as->current_map = g_new(FlatView, 1);
flatview_init(as->current_map);
QTAILQ_INSERT_TAIL(&uc->address_spaces, as, address_spaces_link);
@ -1690,9 +1692,53 @@ void address_space_init(struct uc_struct *uc, AddressSpace *as, MemoryRegion *ro
memory_region_transaction_commit(uc);
}
void address_space_destroy(AddressSpace *as)
static void do_address_space_destroy(AddressSpace *as)
{
MemoryListener *listener;
bool do_free = as->malloced;
address_space_destroy_dispatch(as);
// TODO(danghvu): why assert fail here?
//QTAILQ_FOREACH(listener, &as->uc->memory_listeners, link) {
// assert(listener->address_space_filter != as);
//}
flatview_unref(as->current_map);
g_free(as->name);
// Unicorn: commented out
//g_free(as->ioeventfds);
memory_region_unref(as->root);
if (do_free) {
g_free(as);
}
}
AddressSpace *address_space_init_shareable(struct uc_struct *uc, MemoryRegion *root, const char *name)
{
AddressSpace *as;
QTAILQ_FOREACH(as, &uc->address_spaces, address_spaces_link) {
if (root == as->root && as->malloced) {
as->ref_count++;
return as;
}
}
as = g_malloc0(sizeof *as);
address_space_init(uc, as, root, name);
as->malloced = true;
return as;
}
void address_space_destroy(AddressSpace *as)
{
MemoryRegion *root = as->root;
as->ref_count--;
if (as->ref_count) {
return;
}
/* Flush out anything from MemoryListeners listening in on this */
memory_region_transaction_begin(as->uc);
@ -1701,15 +1747,15 @@ void address_space_destroy(AddressSpace *as)
QTAILQ_REMOVE(&as->uc->address_spaces, as, address_spaces_link);
address_space_unregister(as);
address_space_destroy_dispatch(as);
/* At this point, as->dispatch and as->current_map are dummy
* entries that the guest should never use. Wait for the old
* values to expire before freeing the data.
*/
as->root = root;
do_address_space_destroy(as);
// TODO(danghvu): why assert fail here?
QTAILQ_FOREACH(listener, &as->uc->memory_listeners, link) {
// assert(listener->address_space_filter != as);
}
flatview_unref(as->current_map);
g_free(as->name);
// Unicorn: Commented out and call it directly
// call_rcu(as, do_address_space_destroy, rcu);
}
typedef struct MemoryRegionList MemoryRegionList;

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_mips
#define address_space_init address_space_init_mips
#define address_space_init_dispatch address_space_init_dispatch_mips
#define address_space_init_shareable address_space_init_shareable_mips
#define address_space_lookup_region address_space_lookup_region_mips
#define address_space_map address_space_map_mips
#define address_space_read address_space_read_mips

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_mips64
#define address_space_init address_space_init_mips64
#define address_space_init_dispatch address_space_init_dispatch_mips64
#define address_space_init_shareable address_space_init_shareable_mips64
#define address_space_lookup_region address_space_lookup_region_mips64
#define address_space_map address_space_map_mips64
#define address_space_read address_space_read_mips64

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_mips64el
#define address_space_init address_space_init_mips64el
#define address_space_init_dispatch address_space_init_dispatch_mips64el
#define address_space_init_shareable address_space_init_shareable_mips64el
#define address_space_lookup_region address_space_lookup_region_mips64el
#define address_space_map address_space_map_mips64el
#define address_space_read address_space_read_mips64el

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_mipsel
#define address_space_init address_space_init_mipsel
#define address_space_init_dispatch address_space_init_dispatch_mipsel
#define address_space_init_shareable address_space_init_shareable_mipsel
#define address_space_lookup_region address_space_lookup_region_mipsel
#define address_space_map address_space_map_mipsel
#define address_space_read address_space_read_mipsel

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_powerpc
#define address_space_init address_space_init_powerpc
#define address_space_init_dispatch address_space_init_dispatch_powerpc
#define address_space_init_shareable address_space_init_shareable_powerpc
#define address_space_lookup_region address_space_lookup_region_powerpc
#define address_space_map address_space_map_powerpc
#define address_space_read address_space_read_powerpc

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_sparc
#define address_space_init address_space_init_sparc
#define address_space_init_dispatch address_space_init_dispatch_sparc
#define address_space_init_shareable address_space_init_shareable_sparc
#define address_space_lookup_region address_space_lookup_region_sparc
#define address_space_map address_space_map_sparc
#define address_space_read address_space_read_sparc

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_sparc64
#define address_space_init address_space_init_sparc64
#define address_space_init_dispatch address_space_init_dispatch_sparc64
#define address_space_init_shareable address_space_init_shareable_sparc64
#define address_space_lookup_region address_space_lookup_region_sparc64
#define address_space_map address_space_map_sparc64
#define address_space_read address_space_read_sparc64

View file

@ -91,6 +91,7 @@
#define address_space_get_flatview address_space_get_flatview_x86_64
#define address_space_init address_space_init_x86_64
#define address_space_init_dispatch address_space_init_dispatch_x86_64
#define address_space_init_shareable address_space_init_shareable_x86_64
#define address_space_lookup_region address_space_lookup_region_x86_64
#define address_space_map address_space_map_x86_64
#define address_space_read address_space_read_x86_64