Patchwork [RFC,v2,3/6] memory: add memory_region_to_address()

login
register
mail settings
Submitter Scott Wood
Date April 15, 2013, 11:19 p.m.
Message ID <1366067974-5413-4-git-send-email-scottwood@freescale.com>
Download mbox | patch
Permalink /patch/236764/
State New
Headers show

Comments

Scott Wood - April 15, 2013, 11:19 p.m.
This is useful for when a user of the memory region API needs to
communicate the absolute bus address to something outside QEMU
(in particular, KVM).

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
TODO: Use add/del memory listeners later in the patchset, which would
eliminate the need for this patch.
---
 include/exec/memory.h |    9 +++++++++
 memory.c              |   38 ++++++++++++++++++++++++++++++++++----
 2 files changed, 43 insertions(+), 4 deletions(-)
Peter Maydell - April 16, 2013, 8:25 a.m.
On 16 April 2013 00:19, Scott Wood <scottwood@freescale.com> wrote:
> This is useful for when a user of the memory region API needs to
> communicate the absolute bus address to something outside QEMU
> (in particular, KVM).
>
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> TODO: Use add/del memory listeners later in the patchset, which would
> eliminate the need for this patch.

Yes, please do.

> +/* memory_region_to_address: Find the full address of the start of the
> + *      given #MemoryRegion, ignoring aliases.  There is no guarantee
> + *      that the #MemoryRegion is actually visible at this address, if
> + *      there are overlapping regions.
> + *
> + * @mr: #MemoryRegion being queried
> + * @asp: if non-NULL, returns the #AddressSpace @mr is mapped in, if any
> + */
> +hwaddr memory_region_to_address(MemoryRegion *mr, AddressSpace **asp);

A MemoryRegion can appear in more than one AddressSpace (or none at all),
so I don't think this is a very clearly defined API to put in the
memory API itself. (It's ok to make that kind of assumption as a user
of the memory APIs for particular cases, eg in how a memory listener
callback function behaves. But we shouldn't be baking those assumptions
into new API functions.)

thanks
-- PMM
Peter Maydell - April 17, 2013, 9:14 a.m.
On 17 April 2013 01:10, Scott Wood <scottwood@freescale.com> wrote:
> On 04/16/2013 03:25:50 AM, Peter Maydell wrote:
>> A MemoryRegion can appear in more than one AddressSpace (or none at all),
>> so I don't think this is a very clearly defined API to put in the
>> memory API itself. (It's ok to make that kind of assumption as a user
>> of the memory APIs for particular cases, eg in how a memory listener
>> callback function behaves. But we shouldn't be baking those assumptions
>> into new API functions.)

> I'm not sure how it's different from memory_region_to_address_space in that
> regard, other than its ability to gracefully handle the "or none at all"
> case.

memory_region_to_address_space() is an internal function used by
a couple of functions -- it's passed "a top level (ie parentless)
region", not an arbitrary region [semantically, anyway].

> How does it work to be in more than one AddressSpace, if there's a parent
> chain?  More than one "as" with the same "as->root"?  Or are you referring
> to aliases?

Yes, I had aliases in mind. Ignoring aliases isn't really very
doable since you can't control whether somebody else has taken
an alias of you.

thanks
-- PMM

Patch

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 2322732..b800391 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -892,6 +892,15 @@  void *address_space_map(AddressSpace *as, hwaddr addr,
 void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
                          int is_write, hwaddr access_len);
 
+/* memory_region_to_address: Find the full address of the start of the
+ *      given #MemoryRegion, ignoring aliases.  There is no guarantee
+ *      that the #MemoryRegion is actually visible at this address, if
+ *      there are overlapping regions.
+ *
+ * @mr: #MemoryRegion being queried
+ * @asp: if non-NULL, returns the #AddressSpace @mr is mapped in, if any
+ */
+hwaddr memory_region_to_address(MemoryRegion *mr, AddressSpace **asp);
 
 #endif
 
diff --git a/memory.c b/memory.c
index 75ca281..5d3b13d 100644
--- a/memory.c
+++ b/memory.c
@@ -453,21 +453,51 @@  const IORangeOps memory_region_iorange_ops = {
     .destructor = memory_region_iorange_destructor,
 };
 
-static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
+static AddressSpace *memory_region_root_to_address_space(MemoryRegion *mr)
 {
     AddressSpace *as;
 
-    while (mr->parent) {
-        mr = mr->parent;
-    }
     QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
         if (mr == as->root) {
             return as;
         }
     }
+
+    return NULL;
+}
+
+static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
+{
+    AddressSpace *as;
+
+    while (mr->parent) {
+        mr = mr->parent;
+    }
+
+    as = memory_region_root_to_address_space(mr);
+    if (as) {
+        return as;
+    }
+
     abort();
 }
 
+hwaddr memory_region_to_address(MemoryRegion *mr, AddressSpace **asp)
+{
+    hwaddr addr = mr->addr;
+
+    while (mr->parent) {
+        mr = mr->parent;
+        addr += mr->addr;
+    }
+
+    if (asp) {
+        *asp = memory_region_root_to_address_space(mr);
+    }
+
+    return addr;
+}
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */