summary refs log tree commit diff stats
path: root/memory.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-01-21 15:00:39 +0000
committerPeter Maydell <peter.maydell@linaro.org>2016-01-21 15:00:39 +0000
commit1a4f446f81c63151efc30f3ce60a749e8a4cf680 (patch)
tree7fb7c5695aad485d9a3a3830177493afb9c704ee /memory.c
parent3c9331c47f22224118d5019b0af8eac704824d8d (diff)
parent03fbf20f4da58f41998dc10ec7542f65d37ba759 (diff)
downloadfocaccia-qemu-1a4f446f81c63151efc30f3ce60a749e8a4cf680.tar.gz
focaccia-qemu-1a4f446f81c63151efc30f3ce60a749e8a4cf680.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160121' into staging
target-arm queue:
 * connect SPI devices in Xilinx Zynq platforms
 * multiple-address-space support
 * use multiple-address-space support for ARM TrustZone
 * arm_gic: return correct ID registers for 11MPCore/v1/v2 GICs
 * various fixes for (currently disabled) AArch64 EL2 and EL3 support
 * add 'always-on' property to the virt board timer DT entry

# gpg: Signature made Thu 21 Jan 2016 14:54:56 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"

* remotes/pmaydell/tags/pull-target-arm-20160121: (36 commits)
  target-arm: Implement FPEXC32_EL2 system register
  target-arm: ignore ELR_ELx[1] for exception return to 32-bit ARM mode
  target-arm: Implement remaining illegal return event checks
  target-arm: Handle exception return from AArch64 to non-EL0 AArch32
  target-arm: Fix wrong AArch64 entry offset for EL2/EL3 target
  target-arm: Pull semihosting handling out to arm_cpu_do_interrupt()
  target-arm: Use a single entry point for AArch64 and AArch32 exceptions
  target-arm: Move aarch64_cpu_do_interrupt() to helper.c
  target-arm: Properly support EL2 and EL3 in arm_el_is_aa64()
  arm_gic: Update ID registers based on revision
  hw/arm/virt: Add always-on property to the virt board timer
  hw/arm/virt: add secure memory region and UART
  hw/arm/virt: Wire up memory region to CPUs explicitly
  target-arm: Support multiple address spaces in page table walks
  target-arm: Implement cpu_get_phys_page_attrs_debug
  target-arm: Implement asidx_from_attrs
  target-arm: Add QOM property for Secure memory region
  qom/cpu: Add MemoryRegion property
  memory: Add address_space_init_shareable()
  exec.c: Use correct AddressSpace in watch_mem_read and watch_mem_write
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'memory.c')
-rw-r--r--memory.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/memory.c b/memory.c
index 93bd8ed7bc..d2d0a92810 100644
--- a/memory.c
+++ b/memory.c
@@ -2124,7 +2124,9 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 {
     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;
@@ -2139,6 +2141,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 static void do_address_space_destroy(AddressSpace *as)
 {
     MemoryListener *listener;
+    bool do_free = as->malloced;
 
     address_space_destroy_dispatch(as);
 
@@ -2150,12 +2153,36 @@ static void do_address_space_destroy(AddressSpace *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;