From: Ruslan Ruslichenko <Ruslan_Ruslichenko@epam.com>
Currently, MemoryRegion properties such as addr, size,
priority and container are read-only and don't have setters.
This patch implements the missing setters function, so that
properties can be modified dynamically.
The changes allow MemoryRegions objects to be fully configured
via properties, which enables them be created from a device
tree description.
Signed-off-by: Ruslan Ruslichenko <Ruslan_Ruslichenko@epam.com>
---
system/memory.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 161 insertions(+), 5 deletions(-)
diff --git a/system/memory.c b/system/memory.c
index 4bf00d82bc..a683af525a 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -55,6 +55,9 @@ static GHashTable *flat_views;
typedef struct AddrRange AddrRange;
+static void memory_region_update_container_subregions(MemoryRegion *subregion);
+static void memory_region_readd_subregion(MemoryRegion *mr);
+
/*
* Note that signed integers are needed for negative offsetting in aliases
* (large MemoryRegion::alias_offset).
@@ -1251,6 +1254,73 @@ void memory_region_init(MemoryRegion *mr,
memory_region_do_init(mr, owner, name, size);
}
+static void memory_region_get_addr(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ MemoryRegion *mr = MEMORY_REGION(obj);
+ uint64_t value = mr->addr;
+
+ visit_type_uint64(v, name, &value, errp);
+}
+
+static void memory_region_set_addr(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ MemoryRegion *mr = MEMORY_REGION(obj);
+ Error *local_err = NULL;
+ uint64_t value;
+
+ visit_type_uint64(v, name, &value, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ memory_region_set_address(mr, value);
+}
+
+static void memory_region_set_container(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ MemoryRegion *mr = MEMORY_REGION(obj);
+ Error *local_err = NULL;
+ MemoryRegion *old_container = mr->container;
+ MemoryRegion *new_container = NULL;
+ char *path = NULL;
+
+ visit_type_str(v, name, &path, &local_err);
+
+ if (!local_err && strcmp(path, "") != 0) {
+ new_container = MEMORY_REGION(object_resolve_link(obj, name, path,
+ &local_err));
+ while (new_container->alias) {
+ new_container = new_container->alias;
+ }
+ }
+
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ object_ref(OBJECT(new_container));
+
+ memory_region_transaction_begin();
+ memory_region_ref(mr);
+ if (old_container) {
+ memory_region_del_subregion(old_container, mr);
+ }
+ mr->container = new_container;
+ if (new_container) {
+ memory_region_update_container_subregions(mr);
+ }
+ memory_region_unref(mr);
+ memory_region_transaction_commit();
+
+ object_unref(OBJECT(old_container));
+}
+
static void memory_region_get_container(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
@@ -1285,6 +1355,70 @@ static void memory_region_get_priority(Object *obj, Visitor *v,
visit_type_int32(v, name, &value, errp);
}
+static void memory_region_set_priority(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ MemoryRegion *mr = MEMORY_REGION(obj);
+ Error *local_err = NULL;
+ int32_t value;
+
+ visit_type_uint32(v, name, (uint32_t *)&value, &error_abort);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ if (mr->priority != value) {
+ mr->priority = value;
+ memory_region_readd_subregion(mr);
+ }
+}
+
+static void memory_region_do_set_ram(MemoryRegion *mr)
+{
+ if (mr->addr) {
+ qemu_ram_free(mr->ram_block);
+ }
+ if (int128_eq(mr->size, int128_make64(0))) {
+ return;
+ }
+ if (mr->ram) {
+ mr->ram_block = qemu_ram_alloc(int128_get64(mr->size),
+ RAM_SHARED, mr, &error_abort);
+ }
+}
+
+static void memory_region_set_ram(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ MemoryRegion *mr = MEMORY_REGION(obj);
+ Error *local_err = NULL;
+ uint8_t value;
+
+ visit_type_uint8(v, name, &value, &error_abort);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ mr->dirty_log_mask |= tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
+ /* FIXME: Sanitize error handling */
+ /* FIXME: Probably need all that transactions stuff */
+ if (mr->ram == value) {
+ return;
+ }
+
+ mr->ram = value;
+ mr->terminates = !!value; /*FIXME: Wrong */
+
+ if (int128_eq(int128_2_64(), mr->size)) {
+ return;
+ }
+
+ memory_region_do_set_ram(mr);
+}
+
static void memory_region_get_size(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -1294,6 +1428,19 @@ static void memory_region_get_size(Object *obj, Visitor *v, const char *name,
visit_type_uint64(v, name, &value, errp);
}
+static void memory_region_set_object_size(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ MemoryRegion *mr = MEMORY_REGION(obj);
+ Error *local_err = NULL;
+ uint64_t size;
+
+ visit_type_uint64(v, name, &size, &local_err);
+
+ memory_region_set_size(mr, size);
+}
+
static void memory_region_initfn(Object *obj)
{
MemoryRegion *mr = MEMORY_REGION(obj);
@@ -1309,19 +1456,25 @@ static void memory_region_initfn(Object *obj)
op = object_property_add(OBJECT(mr), "container",
"link<" TYPE_MEMORY_REGION ">",
memory_region_get_container,
- NULL, /* memory_region_set_container */
+ memory_region_set_container,
NULL, NULL);
op->resolve = memory_region_resolve_container;
- object_property_add_uint64_ptr(OBJECT(mr), "addr",
- &mr->addr, OBJ_PROP_FLAG_READ);
+ object_property_add(OBJECT(mr), "addr", "uint64",
+ memory_region_get_addr,
+ memory_region_set_addr,
+ NULL, NULL);
object_property_add(OBJECT(mr), "priority", "uint32",
memory_region_get_priority,
- NULL, /* memory_region_set_priority */
+ memory_region_set_priority,
+ NULL, NULL);
+ object_property_add(OBJECT(mr), "ram", "uint8",
+ NULL, /* FIXME: Add getter */
+ memory_region_set_ram,
NULL, NULL);
object_property_add(OBJECT(mr), "size", "uint64",
memory_region_get_size,
- NULL, /* memory_region_set_size, */
+ memory_region_set_object_size,
NULL, NULL);
}
@@ -2751,6 +2904,9 @@ void memory_region_set_size(MemoryRegion *mr, uint64_t size)
}
memory_region_transaction_begin();
mr->size = s;
+ if (mr->ram) {
+ memory_region_do_set_ram(mr);
+ }
memory_region_update_pending = true;
memory_region_transaction_commit();
}
--
2.43.0