aboutsummaryrefslogtreecommitdiff
path: root/system/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'system/memory.c')
-rw-r--r--system/memory.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/system/memory.c b/system/memory.c
index e11bce5991..a800fbc9e5 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -224,6 +224,7 @@ struct FlatRange {
bool romd_mode;
bool readonly;
bool nonvolatile;
+ bool unmergeable;
};
#define FOR_EACH_FLAT_RANGE(var, view) \
@@ -240,6 +241,7 @@ section_from_flat_range(FlatRange *fr, FlatView *fv)
.offset_within_address_space = int128_get64(fr->addr.start),
.readonly = fr->readonly,
.nonvolatile = fr->nonvolatile,
+ .unmergeable = fr->unmergeable,
};
}
@@ -250,7 +252,8 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b)
&& a->offset_in_region == b->offset_in_region
&& a->romd_mode == b->romd_mode
&& a->readonly == b->readonly
- && a->nonvolatile == b->nonvolatile;
+ && a->nonvolatile == b->nonvolatile
+ && a->unmergeable == b->unmergeable;
}
static FlatView *flatview_new(MemoryRegion *mr_root)
@@ -323,7 +326,8 @@ static bool can_merge(FlatRange *r1, FlatRange *r2)
&& r1->dirty_log_mask == r2->dirty_log_mask
&& r1->romd_mode == r2->romd_mode
&& r1->readonly == r2->readonly
- && r1->nonvolatile == r2->nonvolatile;
+ && r1->nonvolatile == r2->nonvolatile
+ && !r1->unmergeable && !r2->unmergeable;
}
/* Attempt to simplify a view by merging adjacent ranges */
@@ -599,7 +603,8 @@ static void render_memory_region(FlatView *view,
Int128 base,
AddrRange clip,
bool readonly,
- bool nonvolatile)
+ bool nonvolatile,
+ bool unmergeable)
{
MemoryRegion *subregion;
unsigned i;
@@ -616,6 +621,7 @@ static void render_memory_region(FlatView *view,
int128_addto(&base, int128_make64(mr->addr));
readonly |= mr->readonly;
nonvolatile |= mr->nonvolatile;
+ unmergeable |= mr->unmergeable;
tmp = addrrange_make(base, mr->size);
@@ -629,14 +635,14 @@ static void render_memory_region(FlatView *view,
int128_subfrom(&base, int128_make64(mr->alias->addr));
int128_subfrom(&base, int128_make64(mr->alias_offset));
render_memory_region(view, mr->alias, base, clip,
- readonly, nonvolatile);
+ readonly, nonvolatile, unmergeable);
return;
}
/* Render subregions in priority order. */
QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
render_memory_region(view, subregion, base, clip,
- readonly, nonvolatile);
+ readonly, nonvolatile, unmergeable);
}
if (!mr->terminates) {
@@ -652,6 +658,7 @@ static void render_memory_region(FlatView *view,
fr.romd_mode = mr->romd_mode;
fr.readonly = readonly;
fr.nonvolatile = nonvolatile;
+ fr.unmergeable = unmergeable;
/* Render the region itself into any gaps left by the current view. */
for (i = 0; i < view->nr && int128_nz(remain); ++i) {
@@ -753,7 +760,7 @@ static FlatView *generate_memory_topology(MemoryRegion *mr)
if (mr) {
render_memory_region(view, mr, int128_zero(),
addrrange_make(int128_zero(), int128_2_64()),
- false, false);
+ false, false, false);
}
flatview_simplify(view);
@@ -2755,6 +2762,18 @@ void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset)
memory_region_transaction_commit();
}
+void memory_region_set_unmergeable(MemoryRegion *mr, bool unmergeable)
+{
+ if (unmergeable == mr->unmergeable) {
+ return;
+ }
+
+ memory_region_transaction_begin();
+ mr->unmergeable = unmergeable;
+ memory_region_update_pending |= mr->enabled;
+ memory_region_transaction_commit();
+}
+
uint64_t memory_region_get_alignment(const MemoryRegion *mr)
{
return mr->align;