From b4fefef9d52003b6d09866501275a9a57995c6b0 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Thu, 5 Jun 2014 23:15:52 -0700 Subject: memory: MemoryRegion: QOMify QOMify memory regions as an Object. The former init() and destroy() routines become instance_init() and instance_finalize() resp. memory_region_init() is re-implemented to be: object_initialize() + set fields memory_region_destroy() is re-implemented to call unparent(). Signed-off-by: Peter Crosthwaite [Add newly-created MR as child, unparent on destruction. - Paolo] Signed-off-by: Paolo Bonzini --- exec.c | 4 +- include/exec/memory.h | 6 +++ memory.c | 121 +++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 109 insertions(+), 22 deletions(-) diff --git a/exec.c b/exec.c index 18d6c35942..df4a080619 100644 --- a/exec.c +++ b/exec.c @@ -883,7 +883,7 @@ static void phys_section_destroy(MemoryRegion *mr) if (mr->subpage) { subpage_t *subpage = container_of(mr, subpage_t, iomem); - memory_region_destroy(&subpage->iomem); + object_unref(OBJECT(&subpage->iomem)); g_free(subpage); } } @@ -1768,7 +1768,7 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base) mmio->as = as; mmio->base = base; memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio, - "subpage", TARGET_PAGE_SIZE); + NULL, TARGET_PAGE_SIZE); mmio->iomem.subpage = true; #if defined(DEBUG_SUBPAGE) printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__, diff --git a/include/exec/memory.h b/include/exec/memory.h index 3d778d70f0..85b56e2e0c 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -32,10 +32,15 @@ #include "qemu/int128.h" #include "qemu/notify.h" #include "qapi/error.h" +#include "qom/object.h" #define MAX_PHYS_ADDR_SPACE_BITS 62 #define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1) +#define TYPE_MEMORY_REGION "qemu:memory-region" +#define MEMORY_REGION(obj) \ + OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION) + typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegionMmio MemoryRegionMmio; @@ -131,6 +136,7 @@ typedef struct CoalescedMemoryRange CoalescedMemoryRange; typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; struct MemoryRegion { + Object parent_obj; /* All fields are private - violators will be prosecuted */ const MemoryRegionOps *ops; const MemoryRegionIOMMUOps *iommu_ops; diff --git a/memory.c b/memory.c index 7eaa1e9fd4..9397fecd2c 100644 --- a/memory.c +++ b/memory.c @@ -842,40 +842,94 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr) qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK); } +static bool memory_region_need_escape(char c) +{ + return c == '/' || c == '[' || c == '\\' || c == ']'; +} + +static char *memory_region_escape_name(const char *name) +{ + const char *p; + char *escaped, *q; + uint8_t c; + size_t bytes = 0; + + for (p = name; *p; p++) { + bytes += memory_region_need_escape(*p) ? 4 : 1; + } + if (bytes == p - name) { + return g_memdup(name, bytes + 1); + } + + escaped = g_malloc(bytes + 1); + for (p = name, q = escaped; *p; p++) { + c = *p; + if (unlikely(memory_region_need_escape(c))) { + *q++ = '\\'; + *q++ = 'x'; + *q++ = "0123456789abcdef"[c >> 4]; + c = "0123456789abcdef"[c & 15]; + } + *q++ = c; + } + *q = 0; + return escaped; +} + +static void object_property_add_child_array(Object *owner, + const char *name, + Object *child) +{ + int i; + char *base_name = memory_region_escape_name(name); + + for (i = 0; ; i++) { + char *full_name = g_strdup_printf("%s[%d]", base_name, i); + Error *local_err = NULL; + + object_property_add_child(owner, full_name, child, &local_err); + g_free(full_name); + if (!local_err) { + break; + } + + error_free(local_err); + } + + g_free(base_name); +} + + void memory_region_init(MemoryRegion *mr, Object *owner, const char *name, uint64_t size) { - mr->ops = &unassigned_mem_ops; - mr->opaque = NULL; + object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION); + mr->owner = owner ? owner : qdev_get_machine(); - mr->iommu_ops = NULL; - mr->container = NULL; mr->size = int128_make64(size); if (size == UINT64_MAX) { mr->size = int128_2_64(); } - mr->addr = 0; - mr->subpage = false; + mr->name = g_strdup(name); + + if (name) { + object_property_add_child_array(mr->owner, name, OBJECT(mr)); + object_unref(OBJECT(mr)); + } +} + +static void memory_region_initfn(Object *obj) +{ + MemoryRegion *mr = MEMORY_REGION(obj); + + mr->ops = &unassigned_mem_ops; mr->enabled = true; - mr->terminates = false; - mr->ram = false; mr->romd_mode = true; - mr->readonly = false; - mr->rom_device = false; mr->destructor = memory_region_destructor_none; - mr->priority = 0; - mr->may_overlap = false; - mr->alias = NULL; QTAILQ_INIT(&mr->subregions); - memset(&mr->subregions_link, 0, sizeof mr->subregions_link); QTAILQ_INIT(&mr->coalesced); - mr->name = g_strdup(name); - mr->dirty_log_mask = 0; - mr->ioeventfd_nb = 0; - mr->ioeventfds = NULL; - mr->flush_coalesced_mmio = false; } static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, @@ -1113,8 +1167,10 @@ void memory_region_init_reservation(MemoryRegion *mr, memory_region_init_io(mr, owner, &unassigned_mem_ops, mr, name, size); } -void memory_region_destroy(MemoryRegion *mr) +static void memory_region_finalize(Object *obj) { + MemoryRegion *mr = MEMORY_REGION(obj); + assert(QTAILQ_EMPTY(&mr->subregions)); assert(memory_region_transaction_depth == 0); mr->destructor(mr); @@ -1123,6 +1179,12 @@ void memory_region_destroy(MemoryRegion *mr) g_free(mr->ioeventfds); } +void memory_region_destroy(MemoryRegion *mr) +{ + object_unparent(OBJECT(mr)); +} + + Object *memory_region_owner(MemoryRegion *mr) { return mr->owner; @@ -1132,6 +1194,8 @@ void memory_region_ref(MemoryRegion *mr) { if (mr && mr->owner) { object_ref(mr->owner); + } else { + object_ref(OBJECT(mr)); } } @@ -1139,6 +1203,8 @@ void memory_region_unref(MemoryRegion *mr) { if (mr && mr->owner) { object_unref(mr->owner); + } else { + object_unref(OBJECT(mr)); } } @@ -1946,3 +2012,18 @@ void mtree_info(fprintf_function mon_printf, void *f) g_free(ml); } } + +static const TypeInfo memory_region_info = { + .parent = TYPE_OBJECT, + .name = TYPE_MEMORY_REGION, + .instance_size = sizeof(MemoryRegion), + .instance_init = memory_region_initfn, + .instance_finalize = memory_region_finalize, +}; + +static void memory_register_types(void) +{ + type_register_static(&memory_region_info); +} + +type_init(memory_register_types) -- cgit v1.2.1