memory: Share special empty FlatView

This shares an cached empty FlatView among address spaces. The empty
FV is used every time when a root MR renders into a FV without memory
sections which happens when MR or its children are not enabled or
zero-sized. The empty_view is not NULL to keep the rest of memory
API intact; it also has a dispatch tree for the same reason.

On POWER8 with 255 CPUs, 255 virtio-net, 40 PCI bridges guest this halves
the amount of FlatView's in use (557 -> 260) and dispatch tables
(~800000 -> ~370000). In an unrelated experiment with 112 non-virtio
devices on x86 ("-M pc"), only 4 FlatViews are alive, and about ~2000
are created at startup.

Backports commit 092aa2fc65b7a35121616aad8f39d47b8f921618 from qemu
This commit is contained in:
Alexey Kardashevskiy 2018-03-11 22:23:21 -04:00 committed by Lioncash
parent 20b1bd767f
commit b90333a531
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
18 changed files with 41 additions and 5 deletions

View file

@ -199,6 +199,7 @@ struct uc_struct {
uintptr_t helper_retaddr; uintptr_t helper_retaddr;
// qemu/memory.c // qemu/memory.c
FlatView *empty_view;
GHashTable *flat_views; GHashTable *flat_views;
bool global_dirty_log; bool global_dirty_log;

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_aarch64 #define unassigned_mem_ops unassigned_mem_ops_aarch64
#define unassigned_mem_read unassigned_mem_read_aarch64 #define unassigned_mem_read unassigned_mem_read_aarch64
#define unassigned_mem_write unassigned_mem_write_aarch64 #define unassigned_mem_write unassigned_mem_write_aarch64
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_aarch64
#define update_spsel update_spsel_aarch64 #define update_spsel update_spsel_aarch64
#define use_idiv_instructions_rt use_idiv_instructions_rt_aarch64 #define use_idiv_instructions_rt use_idiv_instructions_rt_aarch64
#define v6_cp_reginfo v6_cp_reginfo_aarch64 #define v6_cp_reginfo v6_cp_reginfo_aarch64

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_aarch64eb #define unassigned_mem_ops unassigned_mem_ops_aarch64eb
#define unassigned_mem_read unassigned_mem_read_aarch64eb #define unassigned_mem_read unassigned_mem_read_aarch64eb
#define unassigned_mem_write unassigned_mem_write_aarch64eb #define unassigned_mem_write unassigned_mem_write_aarch64eb
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_aarch64eb
#define update_spsel update_spsel_aarch64eb #define update_spsel update_spsel_aarch64eb
#define use_idiv_instructions_rt use_idiv_instructions_rt_aarch64eb #define use_idiv_instructions_rt use_idiv_instructions_rt_aarch64eb
#define v6_cp_reginfo v6_cp_reginfo_aarch64eb #define v6_cp_reginfo v6_cp_reginfo_aarch64eb

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_arm #define unassigned_mem_ops unassigned_mem_ops_arm
#define unassigned_mem_read unassigned_mem_read_arm #define unassigned_mem_read unassigned_mem_read_arm
#define unassigned_mem_write unassigned_mem_write_arm #define unassigned_mem_write unassigned_mem_write_arm
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_arm
#define update_spsel update_spsel_arm #define update_spsel update_spsel_arm
#define use_idiv_instructions_rt use_idiv_instructions_rt_arm #define use_idiv_instructions_rt use_idiv_instructions_rt_arm
#define v6_cp_reginfo v6_cp_reginfo_arm #define v6_cp_reginfo v6_cp_reginfo_arm

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_armeb #define unassigned_mem_ops unassigned_mem_ops_armeb
#define unassigned_mem_read unassigned_mem_read_armeb #define unassigned_mem_read unassigned_mem_read_armeb
#define unassigned_mem_write unassigned_mem_write_armeb #define unassigned_mem_write unassigned_mem_write_armeb
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_armeb
#define update_spsel update_spsel_armeb #define update_spsel update_spsel_armeb
#define use_idiv_instructions_rt use_idiv_instructions_rt_armeb #define use_idiv_instructions_rt use_idiv_instructions_rt_armeb
#define v6_cp_reginfo v6_cp_reginfo_armeb #define v6_cp_reginfo v6_cp_reginfo_armeb

View file

@ -3004,6 +3004,7 @@ symbols = (
'unassigned_mem_ops', 'unassigned_mem_ops',
'unassigned_mem_read', 'unassigned_mem_read',
'unassigned_mem_write', 'unassigned_mem_write',
'unicorn_free_empty_flat_view',
'update_spsel', 'update_spsel',
'use_idiv_instructions_rt', 'use_idiv_instructions_rt',
'v6_cp_reginfo', 'v6_cp_reginfo',

View file

@ -1379,6 +1379,8 @@ address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
address_space_write(cache->as, cache->xlat + addr, MEMTXATTRS_UNSPECIFIED, buf, len); address_space_write(cache->as, cache->xlat + addr, MEMTXATTRS_UNSPECIFIED, buf, len);
} }
void unicorn_free_empty_flat_view(struct uc_struct *uc);
#endif #endif
#endif #endif

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_m68k #define unassigned_mem_ops unassigned_mem_ops_m68k
#define unassigned_mem_read unassigned_mem_read_m68k #define unassigned_mem_read unassigned_mem_read_m68k
#define unassigned_mem_write unassigned_mem_write_m68k #define unassigned_mem_write unassigned_mem_write_m68k
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_m68k
#define update_spsel update_spsel_m68k #define update_spsel update_spsel_m68k
#define use_idiv_instructions_rt use_idiv_instructions_rt_m68k #define use_idiv_instructions_rt use_idiv_instructions_rt_m68k
#define v6_cp_reginfo v6_cp_reginfo_m68k #define v6_cp_reginfo v6_cp_reginfo_m68k

View file

@ -346,6 +346,15 @@ static void flatview_unref(FlatView *view)
} }
} }
void unicorn_free_empty_flat_view(struct uc_struct *uc)
{
if (!uc->empty_view) {
return;
}
flatview_destroy(uc->empty_view);
}
FlatView *address_space_to_flatview(AddressSpace *as) FlatView *address_space_to_flatview(AddressSpace *as)
{ {
// Unicorn: atomic_read used instead of atomic_rcu_read // Unicorn: atomic_read used instead of atomic_rcu_read
@ -728,7 +737,7 @@ static MemoryRegion *memory_region_get_flatview_root(MemoryRegion *mr)
} }
/* Render a memory topology into a list of disjoint absolute ranges. */ /* Render a memory topology into a list of disjoint absolute ranges. */
static FlatView *generate_memory_topology(MemoryRegion *mr) static FlatView *generate_memory_topology(struct uc_struct *uc, MemoryRegion *mr)
{ {
int i; int i;
FlatView *view; FlatView *view;
@ -741,14 +750,14 @@ static FlatView *generate_memory_topology(MemoryRegion *mr)
} }
flatview_simplify(view); flatview_simplify(view);
view->dispatch = address_space_dispatch_new(mr->uc, view); view->dispatch = address_space_dispatch_new(uc, view);
for (i = 0; i < view->nr; i++) { for (i = 0; i < view->nr; i++) {
MemoryRegionSection mrs = MemoryRegionSection mrs =
section_from_flat_range(&view->ranges[i], view); section_from_flat_range(&view->ranges[i], view);
flatview_add_to_dispatch(view, &mrs); flatview_add_to_dispatch(view, &mrs);
} }
address_space_dispatch_compact(view->dispatch); address_space_dispatch_compact(view->dispatch);
g_hash_table_replace(mr->uc->flat_views, mr, view); g_hash_table_replace(uc->flat_views, mr, view);
return view; return view;
} }
@ -838,6 +847,15 @@ static void flatviews_init(struct uc_struct *uc)
uc->flat_views = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, uc->flat_views = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) flatview_unref); (GDestroyNotify) flatview_unref);
if (!uc->empty_view) {
uc->empty_view = generate_memory_topology(uc, NULL);
/* We keep it alive forever in the global variable. */
flatview_ref(uc->empty_view);
} else {
g_hash_table_replace(uc->flat_views, NULL, uc->empty_view);
flatview_ref(uc->empty_view);
}
} }
static void flatviews_reset(struct uc_struct *uc) static void flatviews_reset(struct uc_struct *uc)
@ -858,7 +876,7 @@ static void flatviews_reset(struct uc_struct *uc)
continue; continue;
} }
generate_memory_topology(physmr); generate_memory_topology(uc, physmr);
} }
} }
@ -915,7 +933,7 @@ static void address_space_update_topology(AddressSpace *as)
flatviews_init(uc); flatviews_init(uc);
if (!g_hash_table_lookup(uc->flat_views, physmr)) { if (!g_hash_table_lookup(uc->flat_views, physmr)) {
generate_memory_topology(physmr); generate_memory_topology(uc, physmr);
} }
address_space_set_flatview(as); address_space_set_flatview(as);
} }

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_mips #define unassigned_mem_ops unassigned_mem_ops_mips
#define unassigned_mem_read unassigned_mem_read_mips #define unassigned_mem_read unassigned_mem_read_mips
#define unassigned_mem_write unassigned_mem_write_mips #define unassigned_mem_write unassigned_mem_write_mips
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_mips
#define update_spsel update_spsel_mips #define update_spsel update_spsel_mips
#define use_idiv_instructions_rt use_idiv_instructions_rt_mips #define use_idiv_instructions_rt use_idiv_instructions_rt_mips
#define v6_cp_reginfo v6_cp_reginfo_mips #define v6_cp_reginfo v6_cp_reginfo_mips

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_mips64 #define unassigned_mem_ops unassigned_mem_ops_mips64
#define unassigned_mem_read unassigned_mem_read_mips64 #define unassigned_mem_read unassigned_mem_read_mips64
#define unassigned_mem_write unassigned_mem_write_mips64 #define unassigned_mem_write unassigned_mem_write_mips64
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_mips64
#define update_spsel update_spsel_mips64 #define update_spsel update_spsel_mips64
#define use_idiv_instructions_rt use_idiv_instructions_rt_mips64 #define use_idiv_instructions_rt use_idiv_instructions_rt_mips64
#define v6_cp_reginfo v6_cp_reginfo_mips64 #define v6_cp_reginfo v6_cp_reginfo_mips64

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_mips64el #define unassigned_mem_ops unassigned_mem_ops_mips64el
#define unassigned_mem_read unassigned_mem_read_mips64el #define unassigned_mem_read unassigned_mem_read_mips64el
#define unassigned_mem_write unassigned_mem_write_mips64el #define unassigned_mem_write unassigned_mem_write_mips64el
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_mips64el
#define update_spsel update_spsel_mips64el #define update_spsel update_spsel_mips64el
#define use_idiv_instructions_rt use_idiv_instructions_rt_mips64el #define use_idiv_instructions_rt use_idiv_instructions_rt_mips64el
#define v6_cp_reginfo v6_cp_reginfo_mips64el #define v6_cp_reginfo v6_cp_reginfo_mips64el

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_mipsel #define unassigned_mem_ops unassigned_mem_ops_mipsel
#define unassigned_mem_read unassigned_mem_read_mipsel #define unassigned_mem_read unassigned_mem_read_mipsel
#define unassigned_mem_write unassigned_mem_write_mipsel #define unassigned_mem_write unassigned_mem_write_mipsel
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_mipsel
#define update_spsel update_spsel_mipsel #define update_spsel update_spsel_mipsel
#define use_idiv_instructions_rt use_idiv_instructions_rt_mipsel #define use_idiv_instructions_rt use_idiv_instructions_rt_mipsel
#define v6_cp_reginfo v6_cp_reginfo_mipsel #define v6_cp_reginfo v6_cp_reginfo_mipsel

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_powerpc #define unassigned_mem_ops unassigned_mem_ops_powerpc
#define unassigned_mem_read unassigned_mem_read_powerpc #define unassigned_mem_read unassigned_mem_read_powerpc
#define unassigned_mem_write unassigned_mem_write_powerpc #define unassigned_mem_write unassigned_mem_write_powerpc
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_powerpc
#define update_spsel update_spsel_powerpc #define update_spsel update_spsel_powerpc
#define use_idiv_instructions_rt use_idiv_instructions_rt_powerpc #define use_idiv_instructions_rt use_idiv_instructions_rt_powerpc
#define v6_cp_reginfo v6_cp_reginfo_powerpc #define v6_cp_reginfo v6_cp_reginfo_powerpc

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_sparc #define unassigned_mem_ops unassigned_mem_ops_sparc
#define unassigned_mem_read unassigned_mem_read_sparc #define unassigned_mem_read unassigned_mem_read_sparc
#define unassigned_mem_write unassigned_mem_write_sparc #define unassigned_mem_write unassigned_mem_write_sparc
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_sparc
#define update_spsel update_spsel_sparc #define update_spsel update_spsel_sparc
#define use_idiv_instructions_rt use_idiv_instructions_rt_sparc #define use_idiv_instructions_rt use_idiv_instructions_rt_sparc
#define v6_cp_reginfo v6_cp_reginfo_sparc #define v6_cp_reginfo v6_cp_reginfo_sparc

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_sparc64 #define unassigned_mem_ops unassigned_mem_ops_sparc64
#define unassigned_mem_read unassigned_mem_read_sparc64 #define unassigned_mem_read unassigned_mem_read_sparc64
#define unassigned_mem_write unassigned_mem_write_sparc64 #define unassigned_mem_write unassigned_mem_write_sparc64
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_sparc64
#define update_spsel update_spsel_sparc64 #define update_spsel update_spsel_sparc64
#define use_idiv_instructions_rt use_idiv_instructions_rt_sparc64 #define use_idiv_instructions_rt use_idiv_instructions_rt_sparc64
#define v6_cp_reginfo v6_cp_reginfo_sparc64 #define v6_cp_reginfo v6_cp_reginfo_sparc64

View file

@ -80,6 +80,7 @@ static void release_common(void *t)
// Destory flat view hash table // Destory flat view hash table
g_hash_table_destroy(s->uc->flat_views); g_hash_table_destroy(s->uc->flat_views);
unicorn_free_empty_flat_view(s->uc);
// TODO(danghvu): these function is not available outside qemu // TODO(danghvu): these function is not available outside qemu
// so we keep them here instead of outside uc_close. // so we keep them here instead of outside uc_close.

View file

@ -2998,6 +2998,7 @@
#define unassigned_mem_ops unassigned_mem_ops_x86_64 #define unassigned_mem_ops unassigned_mem_ops_x86_64
#define unassigned_mem_read unassigned_mem_read_x86_64 #define unassigned_mem_read unassigned_mem_read_x86_64
#define unassigned_mem_write unassigned_mem_write_x86_64 #define unassigned_mem_write unassigned_mem_write_x86_64
#define unicorn_free_empty_flat_view unicorn_free_empty_flat_view_x86_64
#define update_spsel update_spsel_x86_64 #define update_spsel update_spsel_x86_64
#define use_idiv_instructions_rt use_idiv_instructions_rt_x86_64 #define use_idiv_instructions_rt use_idiv_instructions_rt_x86_64
#define v6_cp_reginfo v6_cp_reginfo_x86_64 #define v6_cp_reginfo v6_cp_reginfo_x86_64