diff --git a/qemu/aarch64.h b/qemu/aarch64.h index bc7bda24..e1dce13d 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -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 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 1693d98c..c303099f 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -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 diff --git a/qemu/arm.h b/qemu/arm.h index 1948188d..2c127406 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -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 diff --git a/qemu/armeb.h b/qemu/armeb.h index 4c6f3026..b61ed70c 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -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 diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 8267baef..f644c37c 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -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', diff --git a/qemu/include/exec/memory.h b/qemu/include/exec/memory.h index 893249ab..b0a6289a 100644 --- a/qemu/include/exec/memory.h +++ b/qemu/include/exec/memory.h @@ -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 diff --git a/qemu/m68k.h b/qemu/m68k.h index 0cd208ef..bf6a87d8 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -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 diff --git a/qemu/memory.c b/qemu/memory.c index d4b8f977..7be7cd96 100644 --- a/qemu/memory.c +++ b/qemu/memory.c @@ -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; diff --git a/qemu/mips.h b/qemu/mips.h index 81d1dd2f..35853c2c 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -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 diff --git a/qemu/mips64.h b/qemu/mips64.h index e93a1c06..209e4bf0 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -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 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 45a117e2..763c0f1e 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -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 diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 2d8dd39f..1582aa7b 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -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 diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 7cdcb05e..fbca936e 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -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 diff --git a/qemu/sparc.h b/qemu/sparc.h index fb76eced..c9cc139f 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -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 diff --git a/qemu/sparc64.h b/qemu/sparc64.h index ae0536ef..8d942b6e 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -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 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 6f9c1d63..d0f05acf 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -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