mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-25 04:16:45 +00:00
memory: Open code FlatView rendering
We are going to share FlatView's between AddressSpace's and per-AS memory listeners won't suit the purpose anymore so open code the dispatch tree rendering. Since there is a good chance that dispatch_listener was the only listener, this avoids address_space_update_topology_pass() if there is no registered listeners; this should improve starting time. This should cause no behavioural change. Backports commit 1b04a1580917d9e41fd37ca62cbff9b4bf061e96 from qemu
This commit is contained in:
parent
f74fcb194f
commit
e723b8dd49
30
qemu/exec.c
30
qemu/exec.c
|
@ -1080,9 +1080,8 @@ static void register_multipage(struct uc_struct *uc,
|
||||||
phys_page_set(uc, d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index);
|
phys_page_set(uc, d, start_addr >> TARGET_PAGE_BITS, num_pages, section_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
|
void mem_add(AddressSpace *as, MemoryRegionSection *section)
|
||||||
{
|
{
|
||||||
AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
|
|
||||||
AddressSpaceDispatch *d = as->next_dispatch;
|
AddressSpaceDispatch *d = as->next_dispatch;
|
||||||
MemoryRegionSection now = *section, remain = *section;
|
MemoryRegionSection now = *section, remain = *section;
|
||||||
Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
|
Int128 page_size = int128_make64(TARGET_PAGE_SIZE);
|
||||||
|
@ -1845,9 +1844,8 @@ void phys_mem_clean(AddressSpace *as)
|
||||||
g_free(d->map.sections);
|
g_free(d->map.sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mem_begin(MemoryListener *listener)
|
void mem_begin(AddressSpace *as)
|
||||||
{
|
{
|
||||||
AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
|
|
||||||
AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1);
|
AddressSpaceDispatch *d = g_new0(AddressSpaceDispatch, 1);
|
||||||
uint16_t n;
|
uint16_t n;
|
||||||
PhysPageEntry ppe = { 1, PHYS_MAP_NODE_NIL };
|
PhysPageEntry ppe = { 1, PHYS_MAP_NODE_NIL };
|
||||||
|
@ -1867,9 +1865,8 @@ static void mem_begin(MemoryListener *listener)
|
||||||
as->next_dispatch = d;
|
as->next_dispatch = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mem_commit(MemoryListener *listener)
|
void mem_commit(AddressSpace *as)
|
||||||
{
|
{
|
||||||
AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener);
|
|
||||||
AddressSpaceDispatch *cur = as->dispatch;
|
AddressSpaceDispatch *cur = as->dispatch;
|
||||||
AddressSpaceDispatch *next = as->next_dispatch;
|
AddressSpaceDispatch *next = as->next_dispatch;
|
||||||
|
|
||||||
|
@ -1903,31 +1900,10 @@ static void tcg_commit(MemoryListener *listener)
|
||||||
tlb_flush(cpuas->cpu);
|
tlb_flush(cpuas->cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void address_space_init_dispatch(AddressSpace *as)
|
|
||||||
{
|
|
||||||
MemoryListener ml = { 0 };
|
|
||||||
|
|
||||||
ml.begin = mem_begin;
|
|
||||||
ml.commit = mem_commit;
|
|
||||||
ml.region_add = mem_add;
|
|
||||||
ml.region_nop = mem_add;
|
|
||||||
ml.priority = 0;
|
|
||||||
|
|
||||||
as->dispatch = NULL;
|
|
||||||
as->dispatch_listener = ml;
|
|
||||||
memory_listener_register(as->uc, &as->dispatch_listener, as);
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_unregister(AddressSpace *as)
|
|
||||||
{
|
|
||||||
memory_listener_unregister(as->uc, &as->dispatch_listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
void address_space_destroy_dispatch(AddressSpace *as)
|
void address_space_destroy_dispatch(AddressSpace *as)
|
||||||
{
|
{
|
||||||
AddressSpaceDispatch *d = as->dispatch;
|
AddressSpaceDispatch *d = as->dispatch;
|
||||||
|
|
||||||
memory_listener_unregister(as->uc, &as->dispatch_listener);
|
|
||||||
g_free(d->map.nodes);
|
g_free(d->map.nodes);
|
||||||
g_free(d);
|
g_free(d);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
typedef struct AddressSpaceDispatch AddressSpaceDispatch;
|
typedef struct AddressSpaceDispatch AddressSpaceDispatch;
|
||||||
|
|
||||||
void address_space_init_dispatch(AddressSpace *as);
|
|
||||||
void address_space_destroy_dispatch(AddressSpace *as);
|
void address_space_destroy_dispatch(AddressSpace *as);
|
||||||
|
|
||||||
extern const MemoryRegionOps unassigned_mem_ops;
|
extern const MemoryRegionOps unassigned_mem_ops;
|
||||||
|
@ -30,7 +29,9 @@ extern const MemoryRegionOps unassigned_mem_ops;
|
||||||
bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
|
bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
|
||||||
unsigned size, bool is_write);
|
unsigned size, bool is_write);
|
||||||
|
|
||||||
void address_space_unregister(AddressSpace *as);
|
void mem_add(AddressSpace *as, MemoryRegionSection *section);
|
||||||
|
void mem_begin(AddressSpace *as);
|
||||||
|
void mem_commit(AddressSpace *as);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -236,7 +236,6 @@ struct AddressSpace {
|
||||||
struct FlatView *current_map;
|
struct FlatView *current_map;
|
||||||
struct AddressSpaceDispatch *dispatch;
|
struct AddressSpaceDispatch *dispatch;
|
||||||
struct AddressSpaceDispatch *next_dispatch;
|
struct AddressSpaceDispatch *next_dispatch;
|
||||||
MemoryListener dispatch_listener;
|
|
||||||
struct uc_struct* uc;
|
struct uc_struct* uc;
|
||||||
|
|
||||||
QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners;
|
QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners;
|
||||||
|
|
|
@ -757,9 +757,20 @@ static void address_space_update_topology(AddressSpace *as)
|
||||||
{
|
{
|
||||||
FlatView *old_view = address_space_get_flatview(as);
|
FlatView *old_view = address_space_get_flatview(as);
|
||||||
FlatView *new_view = generate_memory_topology(as->root);
|
FlatView *new_view = generate_memory_topology(as->root);
|
||||||
|
int i;
|
||||||
|
|
||||||
address_space_update_topology_pass(as, old_view, new_view, false);
|
mem_begin(as);
|
||||||
address_space_update_topology_pass(as, old_view, new_view, true);
|
for (i = 0; i < new_view->nr; i++) {
|
||||||
|
MemoryRegionSection mrs =
|
||||||
|
section_from_flat_range(&new_view->ranges[i], as);
|
||||||
|
mem_add(as, &mrs);
|
||||||
|
}
|
||||||
|
mem_commit(as);
|
||||||
|
|
||||||
|
if (!QTAILQ_EMPTY(&as->listeners)) {
|
||||||
|
address_space_update_topology_pass(as, old_view, new_view, false);
|
||||||
|
address_space_update_topology_pass(as, old_view, new_view, true);
|
||||||
|
}
|
||||||
|
|
||||||
flatview_unref(as->current_map);
|
flatview_unref(as->current_map);
|
||||||
as->current_map = new_view;
|
as->current_map = new_view;
|
||||||
|
@ -1798,7 +1809,7 @@ void address_space_init(struct uc_struct *uc, AddressSpace *as, MemoryRegion *ro
|
||||||
QTAILQ_INIT(&as->listeners);
|
QTAILQ_INIT(&as->listeners);
|
||||||
QTAILQ_INSERT_TAIL(&uc->address_spaces, as, address_spaces_link);
|
QTAILQ_INSERT_TAIL(&uc->address_spaces, as, address_spaces_link);
|
||||||
as->name = g_strdup(name ? name : "anonymous");
|
as->name = g_strdup(name ? name : "anonymous");
|
||||||
address_space_init_dispatch(as);
|
as->dispatch = NULL;
|
||||||
uc->memory_region_update_pending |= root->enabled;
|
uc->memory_region_update_pending |= root->enabled;
|
||||||
memory_region_transaction_commit(uc);
|
memory_region_transaction_commit(uc);
|
||||||
}
|
}
|
||||||
|
@ -1856,7 +1867,6 @@ void address_space_destroy(AddressSpace *as)
|
||||||
as->root = NULL;
|
as->root = NULL;
|
||||||
memory_region_transaction_commit(as->uc);
|
memory_region_transaction_commit(as->uc);
|
||||||
QTAILQ_REMOVE(&as->uc->address_spaces, as, address_spaces_link);
|
QTAILQ_REMOVE(&as->uc->address_spaces, as, address_spaces_link);
|
||||||
address_space_unregister(as);
|
|
||||||
|
|
||||||
/* At this point, as->dispatch and as->current_map are dummy
|
/* At this point, as->dispatch and as->current_map are dummy
|
||||||
* entries that the guest should never use. Wait for the old
|
* entries that the guest should never use. Wait for the old
|
||||||
|
|
Loading…
Reference in a new issue