aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2011-11-28 15:41:26 +0200
committerAvi Kivity <avi@redhat.com>2011-11-28 15:41:26 +0200
commitabdce1e35744aed90f45470b1b8df50cacabbefe (patch)
tree4c7c2311a94fad9fc0f3c496c057ce1b29924494
parentbc75c9e50d308b2ec6623a40179c5cdc84b63dae (diff)
parent7249105319a0ceb5d6f629853c42195ed58c5d70 (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.c66
-rw-r--r--memory.h28
2 files changed, 83 insertions, 11 deletions
diff --git a/memory.c b/memory.c
index 7c20a0703..c20ac13b2 100644
--- a/memory.c
+++ b/memory.c
@@ -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;
diff --git a/memory.h b/memory.h
index 7fb36d16e..4105d6ddf 100644
--- a/memory.h
+++ b/memory.h
@@ -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.
*/