aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-10-07 12:59:55 +0200
committerAvi Kivity <avi@redhat.com>2012-10-22 14:50:08 +0200
commit83f3c251422b0724044f976a7ff26b2e8a47c374 (patch)
treeed5bdab5dd91f6e102eb228691c133485c0a8aa5
parentb90600eed3c0efe5f3260853c873caf51c0677b1 (diff)
memory: add address_space_destroy()
Since address spaces can be created dynamically by device hotplug, they can also be destroyed dynamically. Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--exec.c10
-rw-r--r--memory-internal.h1
-rw-r--r--memory.c18
-rw-r--r--memory.h12
4 files changed, 39 insertions, 2 deletions
diff --git a/exec.c b/exec.c
index bfc4acc20..17e8ba21d 100644
--- a/exec.c
+++ b/exec.c
@@ -3234,6 +3234,16 @@ void address_space_init_dispatch(AddressSpace *as)
memory_listener_register(&d->listener, as);
}
+void address_space_destroy_dispatch(AddressSpace *as)
+{
+ AddressSpaceDispatch *d = as->dispatch;
+
+ memory_listener_unregister(&d->listener);
+ destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1);
+ g_free(d);
+ as->dispatch = NULL;
+}
+
static void memory_map_init(void)
{
system_memory = g_malloc(sizeof(*system_memory));
diff --git a/memory-internal.h b/memory-internal.h
index 6d8711bb1..4d33cc953 100644
--- a/memory-internal.h
+++ b/memory-internal.h
@@ -41,6 +41,7 @@ struct AddressSpaceDispatch {
};
void address_space_init_dispatch(AddressSpace *as);
+void address_space_destroy_dispatch(AddressSpace *as);
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr);
diff --git a/memory.c b/memory.c
index 13be84849..2f68d67c2 100644
--- a/memory.c
+++ b/memory.c
@@ -564,8 +564,10 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
flatview_init(&view);
- render_memory_region(&view, mr, int128_zero(),
- addrrange_make(int128_zero(), int128_2_64()), false);
+ if (mr) {
+ render_memory_region(&view, mr, int128_zero(),
+ addrrange_make(int128_zero(), int128_2_64()), false);
+ }
flatview_simplify(&view);
return view;
@@ -1542,6 +1544,18 @@ void address_space_init(AddressSpace *as, MemoryRegion *root)
address_space_init_dispatch(as);
}
+void address_space_destroy(AddressSpace *as)
+{
+ /* Flush out anything from MemoryListeners listening in on this */
+ memory_region_transaction_begin();
+ as->root = NULL;
+ memory_region_transaction_commit();
+ QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
+ address_space_destroy_dispatch(as);
+ flatview_destroy(as->current_map);
+ g_free(as->current_map);
+}
+
uint64_t io_mem_read(MemoryRegion *mr, target_phys_addr_t addr, unsigned size)
{
return memory_region_dispatch_read(mr, addr, size);
diff --git a/memory.h b/memory.h
index d36c2baa2..79393f1a7 100644
--- a/memory.h
+++ b/memory.h
@@ -804,6 +804,18 @@ void mtree_info(fprintf_function mon_printf, void *f);
*/
void address_space_init(AddressSpace *as, MemoryRegion *root);
+
+/**
+ * address_space_destroy: destroy an address space
+ *
+ * Releases all resources associated with an address space. After an address space
+ * is destroyed, its root memory region (given by address_space_init()) may be destroyed
+ * as well.
+ *
+ * @as: address space to be destroyed
+ */
+void address_space_destroy(AddressSpace *as);
+
/**
* address_space_rw: read from or write to an address space.
*