From 6bba19ba4e2b8c89496569439ca38a328cf29a77 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 14 Sep 2011 11:54:58 +0300 Subject: memory: introduce memory_region_set_enabled() This allows users to disable a memory region without removing it from the hierarchy, simplifying the implementation of memory routers. Signed-off-by: Avi Kivity --- memory.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'memory.c') diff --git a/memory.c b/memory.c index adfdf1470c..d0f90ca350 100644 --- a/memory.c +++ b/memory.c @@ -528,6 +528,10 @@ static void render_memory_region(FlatView *view, FlatRange fr; AddrRange tmp; + if (!mr->enabled) { + return; + } + int128_addto(&base, int128_make64(mr->addr)); readonly |= mr->readonly; @@ -750,12 +754,16 @@ static void address_space_update_topology(AddressSpace *as) address_space_update_ioeventfds(as); } -static void memory_region_update_topology(void) +static void memory_region_update_topology(MemoryRegion *mr) { if (memory_region_transaction_depth) { return; } + if (mr && !mr->enabled) { + return; + } + if (address_space_memory.root) { address_space_update_topology(&address_space_memory); } @@ -773,7 +781,7 @@ void memory_region_transaction_commit(void) { assert(memory_region_transaction_depth); --memory_region_transaction_depth; - memory_region_update_topology(); + memory_region_update_topology(NULL); } static void memory_region_destructor_none(MemoryRegion *mr) @@ -813,6 +821,7 @@ void memory_region_init(MemoryRegion *mr, } mr->addr = 0; mr->offset = 0; + mr->enabled = true; mr->terminates = false; mr->readable = true; mr->readonly = false; @@ -1058,7 +1067,7 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) uint8_t mask = 1 << client; mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask); - memory_region_update_topology(); + memory_region_update_topology(mr); } bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, @@ -1090,7 +1099,7 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly) { if (mr->readonly != readonly) { mr->readonly = readonly; - memory_region_update_topology(); + memory_region_update_topology(mr); } } @@ -1098,7 +1107,7 @@ void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable) { if (mr->readable != readable) { mr->readable = readable; - memory_region_update_topology(); + memory_region_update_topology(mr); } } @@ -1203,7 +1212,7 @@ void memory_region_add_eventfd(MemoryRegion *mr, memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i], sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i)); mr->ioeventfds[i] = mrfd; - memory_region_update_topology(); + memory_region_update_topology(mr); } void memory_region_del_eventfd(MemoryRegion *mr, @@ -1233,7 +1242,7 @@ void memory_region_del_eventfd(MemoryRegion *mr, --mr->ioeventfd_nb; mr->ioeventfds = g_realloc(mr->ioeventfds, sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1); - memory_region_update_topology(); + memory_region_update_topology(mr); } static void memory_region_add_subregion_common(MemoryRegion *mr, @@ -1274,7 +1283,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, } QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link); done: - memory_region_update_topology(); + memory_region_update_topology(mr); } @@ -1303,19 +1312,28 @@ void memory_region_del_subregion(MemoryRegion *mr, assert(subregion->parent == mr); subregion->parent = NULL; QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); - memory_region_update_topology(); + memory_region_update_topology(mr); +} + +void memory_region_set_enabled(MemoryRegion *mr, bool enabled) +{ + if (enabled == mr->enabled) { + return; + } + mr->enabled = enabled; + memory_region_update_topology(NULL); } void set_system_memory_map(MemoryRegion *mr) { address_space_memory.root = mr; - memory_region_update_topology(); + memory_region_update_topology(NULL); } void set_system_io_map(MemoryRegion *mr) { address_space_io.root = mr; - memory_region_update_topology(); + memory_region_update_topology(NULL); } typedef struct MemoryRegionList MemoryRegionList; -- cgit 1.4.1 From 2282e1af408db47bab0f900344c0ba0935835f48 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 14 Sep 2011 12:10:12 +0300 Subject: memory: introduce memory_region_set_address() Allow changing the address of a memory region while it is in the memory hierarchy. Signed-off-by: Avi Kivity --- memory.c | 21 +++++++++++++++++++++ memory.h | 11 +++++++++++ 2 files changed, 32 insertions(+) (limited to 'memory.c') diff --git a/memory.c b/memory.c index d0f90ca350..a080d210c1 100644 --- a/memory.c +++ b/memory.c @@ -1324,6 +1324,27 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled) memory_region_update_topology(NULL); } +void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr) +{ + MemoryRegion *parent = mr->parent; + unsigned priority = mr->priority; + bool may_overlap = mr->may_overlap; + + if (addr == mr->addr || !parent) { + mr->addr = addr; + return; + } + + memory_region_transaction_begin(); + memory_region_del_subregion(parent, mr); + if (may_overlap) { + memory_region_add_subregion_overlap(parent, addr, mr, priority); + } else { + memory_region_add_subregion(parent, addr, mr); + } + memory_region_transaction_commit(); +} + void set_system_memory_map(MemoryRegion *mr) { address_space_memory.root = mr; diff --git a/memory.h b/memory.h index c6997c4ee3..db53422b2b 100644 --- a/memory.h +++ b/memory.h @@ -518,6 +518,17 @@ void memory_region_del_subregion(MemoryRegion *mr, */ void memory_region_set_enabled(MemoryRegion *mr, bool enabled); +/* + * memory_region_set_address: dynamically update the address of a region + * + * Dynamically updates the address of a region, relative to its parent. + * May be used on regions are currently part of a memory hierarchy. + * + * @mr: the region to be updated + * @addr: new address, relative to parent region + */ +void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr); + /* Start a transaction; changes will be accumulated and made visible only * when the transaction ends. */ -- cgit 1.4.1 From 4703359e0eeb27c382fdf2951b842cf8bde26672 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 4 Dec 2011 19:16:50 +0200 Subject: memory: introduce memory_region_set_alias_offset() Add an API to update an alias offset of an active alias. This can be used to simplify implementation of dynamic memory banks. Signed-off-by: Avi Kivity --- memory.c | 14 ++++++++++++++ memory.h | 12 ++++++++++++ 2 files changed, 26 insertions(+) (limited to 'memory.c') diff --git a/memory.c b/memory.c index a080d210c1..7e842b3ad5 100644 --- a/memory.c +++ b/memory.c @@ -1345,6 +1345,20 @@ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr) memory_region_transaction_commit(); } +void memory_region_set_alias_offset(MemoryRegion *mr, target_phys_addr_t offset) +{ + target_phys_addr_t old_offset = mr->alias_offset; + + assert(mr->alias); + mr->alias_offset = offset; + + if (offset == old_offset || !mr->parent) { + return; + } + + memory_region_update_topology(mr); +} + void set_system_memory_map(MemoryRegion *mr) { address_space_memory.root = mr; diff --git a/memory.h b/memory.h index db53422b2b..c07bcca306 100644 --- a/memory.h +++ b/memory.h @@ -529,6 +529,18 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled); */ void memory_region_set_address(MemoryRegion *mr, target_phys_addr_t addr); +/* + * memory_region_set_alias_offset: dynamically update a memory alias's offset + * + * Dynamically updates the offset into the target region that an alias points + * to, as if the fourth argument to memory_region_init_alias() has changed. + * + * @mr: the #MemoryRegion to be updated; should be an alias. + * @offset: the new offset into the target memory region + */ +void memory_region_set_alias_offset(MemoryRegion *mr, + target_phys_addr_t offset); + /* Start a transaction; changes will be accumulated and made visible only * when the transaction ends. */ -- cgit 1.4.1 From e87c099f1c9e461dcaa093b1b40b14e7e899e70f Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 14 Sep 2011 12:16:20 +0300 Subject: memory: optimize empty transactions due to mutators The mutating memory APIs can easily cause empty transactions, where the mutators don't actually change anything, or perhaps only modify disabled regions. Detect these conditions and avoid regenerating the memory topology. Signed-off-by: Avi Kivity --- memory.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'memory.c') diff --git a/memory.c b/memory.c index 7e842b3ad5..87639ab6ea 100644 --- a/memory.c +++ b/memory.c @@ -19,6 +19,7 @@ #include unsigned memory_region_transaction_depth = 0; +static bool memory_region_update_pending = false; typedef struct AddrRange AddrRange; @@ -757,6 +758,7 @@ static void address_space_update_topology(AddressSpace *as) static void memory_region_update_topology(MemoryRegion *mr) { if (memory_region_transaction_depth) { + memory_region_update_pending |= !mr || mr->enabled; return; } @@ -770,6 +772,8 @@ static void memory_region_update_topology(MemoryRegion *mr) if (address_space_io.root) { address_space_update_topology(&address_space_io); } + + memory_region_update_pending = false; } void memory_region_transaction_begin(void) @@ -781,7 +785,9 @@ void memory_region_transaction_commit(void) { assert(memory_region_transaction_depth); --memory_region_transaction_depth; - memory_region_update_topology(NULL); + if (!memory_region_transaction_depth && memory_region_update_pending) { + memory_region_update_topology(NULL); + } } static void memory_region_destructor_none(MemoryRegion *mr) -- cgit 1.4.1