diff options
author | Avi Kivity <avi@redhat.com> | 2011-11-28 15:41:26 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-11-28 15:41:26 +0200 |
commit | abdce1e35744aed90f45470b1b8df50cacabbefe (patch) | |
tree | 4c7c2311a94fad9fc0f3c496c057ce1b29924494 | |
parent | bc75c9e50d308b2ec6623a40179c5cdc84b63dae (diff) | |
parent | 7249105319a0ceb5d6f629853c42195ed58c5d70 (diff) |
Merge branch 'memory/mutators' into memory/master
* memory/mutators:
memory: optimize empty transactions due to mutators
memory: introduce memory_region_set_address()
memory: introduce memory_region_set_enabled()
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | memory.c | 66 | ||||
-rw-r--r-- | memory.h | 28 |
2 files changed, 83 insertions, 11 deletions
@@ -19,6 +19,7 @@ #include <assert.h> unsigned memory_region_transaction_depth = 0; +static bool memory_region_update_pending = false; typedef struct AddrRange AddrRange; @@ -528,6 +529,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,9 +755,14 @@ 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) { + memory_region_update_pending |= !mr || mr->enabled; + return; + } + + if (mr && !mr->enabled) { return; } @@ -762,6 +772,8 @@ static void memory_region_update_topology(void) if (address_space_io.root) { address_space_update_topology(&address_space_io); } + + memory_region_update_pending = false; } void memory_region_transaction_begin(void) @@ -773,7 +785,9 @@ void memory_region_transaction_commit(void) { assert(memory_region_transaction_depth); --memory_region_transaction_depth; - memory_region_update_topology(); + if (!memory_region_transaction_depth && memory_region_update_pending) { + memory_region_update_topology(NULL); + } } static void memory_region_destructor_none(MemoryRegion *mr) @@ -813,6 +827,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; @@ -1052,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, @@ -1084,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); } } @@ -1092,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); } } @@ -1197,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, @@ -1227,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, @@ -1268,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); } @@ -1297,19 +1312,48 @@ 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 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) { + 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; - 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; @@ -116,6 +116,7 @@ struct MemoryRegion { bool terminates; bool readable; bool readonly; /* For RAM regions */ + bool enabled; MemoryRegion *alias; target_phys_addr_t alias_offset; unsigned priority; @@ -494,6 +495,33 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr, void memory_region_del_subregion(MemoryRegion *mr, MemoryRegion *subregion); + +/* + * memory_region_set_enabled: dynamically enable or disable a region + * + * Enables or disables a memory region. A disabled memory region + * ignores all accesses to itself and its subregions. It does not + * obscure sibling subregions with lower priority - it simply behaves as + * if it was removed from the hierarchy. + * + * Regions default to being enabled. + * + * @mr: the region to be updated + * @enabled: whether to enable or disable the region + */ +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. */ |