From: Ruslan Ruslichenko <[email protected]> The patch implements TYPE_FDT_GENERIC_MMAP interface for the MemoryRegion class.
This enables memory region objects to be automatically constructed by FDT parser based on the 'reg' property in the Device tree. The implementation parses register tuples and set base address, size and priority properties. Optionally parent container can be set of newly created memory region. Signed-off-by: Ruslan Ruslichenko <[email protected]> --- system/memory.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/system/memory.c b/system/memory.c index a683af525a..866c741973 100644 --- a/system/memory.c +++ b/system/memory.c @@ -38,6 +38,8 @@ #include "memory-internal.h" +#include "hw/core/fdt_generic_util.h" + //#define DEBUG_UNASSIGNED static unsigned memory_region_transaction_depth; @@ -3749,6 +3751,57 @@ static gboolean mtree_info_flatview_free(gpointer key, gpointer value, return true; } +static bool memory_region_parse_reg(FDTGenericMMap *obj, + FDTGenericRegPropInfo reg, Error **errp) +{ + MemoryRegion *mr = MEMORY_REGION(obj); + uint64_t base_addr = ~0ull; + uint64_t total_size = 0; + uint64_t max_addr = 0; + int i; + + if (!reg.n) { + return false; + } + + for (i = 0; i < reg.n; ++i) { + base_addr = MIN(base_addr, reg.a[i]); + max_addr = MAX(max_addr, reg.a[i] + reg.s[i]); + total_size += reg.s[i]; + if (reg.p[i] != reg.p[0]) { + error_setg(errp, "FDT generic memory parser does not support" + "mixed priorities"); + return false; + } + } + + if (total_size != max_addr - base_addr) { + error_setg(errp, "FDT generic memory parse does not " + "spport discontiguous or overlapping memory regions"); + return false; + } + + /* + * FIXME: parent should not be optional but we need to implement + * reg-extended in kernel before we can do things properly + */ + if (reg.parents[0]) { + object_property_set_link(OBJECT(mr), "container", reg.parents[0], + &error_abort); + } + object_property_set_int(OBJECT(mr), "size", total_size, &error_abort); + object_property_set_int(OBJECT(mr), "addr", base_addr, &error_abort); + object_property_set_int(OBJECT(mr), "priority", reg.p[0], &error_abort); + return false; +} + +static void memory_region_class_init(ObjectClass *oc, const void *data) +{ + FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_CLASS(oc); + + fmc->parse_reg = memory_region_parse_reg; +} + static void mtree_info_flatview(bool dispatch_tree, bool owner) { struct FlatViewInfo fvi = { @@ -3994,6 +4047,11 @@ static const TypeInfo memory_region_info = { .instance_size = sizeof(MemoryRegion), .instance_init = memory_region_initfn, .instance_finalize = memory_region_finalize, + .class_init = memory_region_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_FDT_GENERIC_MMAP }, + { }, + }, }; static const TypeInfo iommu_memory_region_info = { -- 2.43.0
