* GNU GPL, version 2 or (at your option) any later version.
*/
+#include "qemu/osdep.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
#include "exec/ioport.h"
#include "qemu/error-report.h"
#include "qom/object.h"
#include "trace.h"
-#include <assert.h>
#include "exec/memory-internal.h"
#include "exec/ram_addr.h"
const char *name,
uint64_t size)
{
- if (!owner) {
- owner = container_get(qdev_get_machine(), "/unattached");
- }
-
object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
mr->size = int128_make64(size);
if (size == UINT64_MAX) {
mr->size = int128_2_64();
}
mr->name = g_strdup(name);
+ mr->owner = owner;
if (name) {
char *escaped_name = memory_region_escape_name(name);
char *name_array = g_strdup_printf("%s[*]", escaped_name);
+
+ if (!owner) {
+ owner = container_get(qdev_get_machine(), "/unattached");
+ }
+
object_property_add_child(owner, name_array, OBJECT(mr), &error_abort);
object_unref(OBJECT(mr));
g_free(name_array);
}
}
-static void memory_region_get_addr(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+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, &value, name, errp);
+ visit_type_uint64(v, name, &value, errp);
}
-static void memory_region_get_container(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void memory_region_get_container(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
MemoryRegion *mr = MEMORY_REGION(obj);
gchar *path = (gchar *)"";
if (mr->container) {
path = object_get_canonical_path(OBJECT(mr->container));
}
- visit_type_str(v, &path, name, errp);
+ visit_type_str(v, name, &path, errp);
if (mr->container) {
g_free(path);
}
return OBJECT(mr->container);
}
-static void memory_region_get_priority(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void memory_region_get_priority(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
MemoryRegion *mr = MEMORY_REGION(obj);
int32_t value = mr->priority;
- visit_type_int32(v, &value, name, errp);
+ visit_type_int32(v, name, &value, errp);
}
static bool memory_region_get_may_overlap(Object *obj, Error **errp)
return mr->may_overlap;
}
-static void memory_region_get_size(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void memory_region_get_size(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
MemoryRegion *mr = MEMORY_REGION(obj);
uint64_t value = memory_region_size(mr);
- visit_type_uint64(v, &value, name, errp);
+ visit_type_uint64(v, name, &value, errp);
}
static void memory_region_initfn(Object *obj)
* The memory region is a child of its owner. As long as the
* owner doesn't call unparent itself on the memory region,
* ref-ing the owner will also keep the memory region alive.
- * Memory regions without an owner are supposed to never go away,
- * but we still ref/unref them for debugging purposes.
+ * Memory regions without an owner are supposed to never go away;
+ * we do not ref/unref them because it slows down DMA sensibly.
*/
- Object *obj = OBJECT(mr);
- if (obj && obj->parent) {
- object_ref(obj->parent);
- } else {
- object_ref(obj);
+ if (mr && mr->owner) {
+ object_ref(mr->owner);
}
}
void memory_region_unref(MemoryRegion *mr)
{
- Object *obj = OBJECT(mr);
- if (obj && obj->parent) {
- object_unref(obj->parent);
- } else {
- object_unref(obj);
+ if (mr && mr->owner) {
+ object_unref(mr->owner);
}
}
return mr->name;
}
-bool memory_region_is_ram(MemoryRegion *mr)
-{
- return mr->ram;
-}
-
bool memory_region_is_skip_dump(MemoryRegion *mr)
{
return mr->skip_dump;
return memory_region_get_dirty_log_mask(mr) & (1 << client);
}
-bool memory_region_is_rom(MemoryRegion *mr)
-{
- return mr->ram && mr->readonly;
-}
-
-bool memory_region_is_iommu(MemoryRegion *mr)
-{
- return mr->iommu_ops;
-}
-
void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n)
{
notifier_list_add(&mr->iommu_notify, n);
memory_region_transaction_commit();
}
-ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
-{
- return mr->ram_addr;
-}
-
uint64_t memory_region_get_alignment(const MemoryRegion *mr)
{
return mr->align;
{
memory_region_ref(root);
memory_region_transaction_begin();
+ as->ref_count = 1;
as->root = root;
+ as->malloced = false;
as->current_map = g_new(FlatView, 1);
flatview_init(as->current_map);
as->ioeventfd_nb = 0;
static void do_address_space_destroy(AddressSpace *as)
{
MemoryListener *listener;
+ bool do_free = as->malloced;
address_space_destroy_dispatch(as);
g_free(as->name);
g_free(as->ioeventfds);
memory_region_unref(as->root);
+ if (do_free) {
+ g_free(as);
+ }
+}
+
+AddressSpace *address_space_init_shareable(MemoryRegion *root, const char *name)
+{
+ AddressSpace *as;
+
+ QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
+ if (root == as->root && as->malloced) {
+ as->ref_count++;
+ return as;
+ }
+ }
+
+ as = g_malloc0(sizeof *as);
+ address_space_init(as, root, name);
+ as->malloced = true;
+ return as;
}
void address_space_destroy(AddressSpace *as)
{
MemoryRegion *root = as->root;
+ as->ref_count--;
+ if (as->ref_count) {
+ return;
+ }
/* Flush out anything from MemoryListeners listening in on this */
memory_region_transaction_begin();
as->root = NULL;