Patchwork [06/30] memory: allow memory_region_find() to run on non-root memory regions

login
register
mail settings
Submitter Paolo Bonzini
Date May 21, 2013, 10:57 a.m.
Message ID <1369133851-1894-7-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/245291/
State New
Headers show

Comments

Paolo Bonzini - May 21, 2013, 10:57 a.m.
memory_region_find() is similar to registering a MemoryListener and
checking for the MemoryRegionSections that come from a particular
region.  There is no reason for this to be limited to a root memory
region.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/exec/memory.h | 13 +++++++------
 memory.c              | 20 +++++++++++++++-----
 2 files changed, 22 insertions(+), 11 deletions(-)
Peter Maydell - May 23, 2013, 5:52 p.m.
On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> memory_region_find() is similar to registering a MemoryListener and
> checking for the MemoryRegionSections that come from a particular
> region.  There is no reason for this to be limited to a root memory
> region.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  include/exec/memory.h | 13 +++++++------
>  memory.c              | 20 +++++++++++++++-----
>  2 files changed, 22 insertions(+), 11 deletions(-)
>
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 9e88320..efe210b 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -725,17 +725,18 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
>   *
>   * Returns a #MemoryRegionSection that describes a contiguous overlap.
>   * It will have the following characteristics:
> - *    .@offset_within_address_space >= @addr
> - *    .@offset_within_address_space + .@size <= @addr + @size
>   *    .@size = 0 iff no overlap was found
>   *    .@mr is non-%NULL iff an overlap was found
>   *
> - * @address_space: a top-level (i.e. parentless) region that contains
> - *       the region to be found
> - * @addr: start of the area within @address_space to be searched
> + * If @mr has no parent, @addr is an absolute address in an AddressSpace, hence:
> + *    .@offset_within_address_space >= @addr
> + *    .@offset_within_address_space + .@size <= @addr + @size
> + *
> + * @mr: a MemoryRegion within which @addr is a relative address
> + * @addr: start of the area within @as to be searched
>   * @size: size of the area to be searched
>   */

You need to change the first para of the doc comment, which
still says @address_space. In fact the entire doc comment is
pretty confusing now. The code looks OK but I forget what the
rationale for this change is; it would be nice if the comment
was informative enough to remind me :-)

-- PMM

Patch

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 9e88320..efe210b 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -725,17 +725,18 @@  void memory_region_set_alias_offset(MemoryRegion *mr,
  *
  * Returns a #MemoryRegionSection that describes a contiguous overlap.
  * It will have the following characteristics:
- *    .@offset_within_address_space >= @addr
- *    .@offset_within_address_space + .@size <= @addr + @size
  *    .@size = 0 iff no overlap was found
  *    .@mr is non-%NULL iff an overlap was found
  *
- * @address_space: a top-level (i.e. parentless) region that contains
- *       the region to be found
- * @addr: start of the area within @address_space to be searched
+ * If @mr has no parent, @addr is an absolute address in an AddressSpace, hence:
+ *    .@offset_within_address_space >= @addr
+ *    .@offset_within_address_space + .@size <= @addr + @size
+ *
+ * @mr: a MemoryRegion within which @addr is a relative address
+ * @addr: start of the area within @as to be searched
  * @size: size of the area to be searched
  */
-MemoryRegionSection memory_region_find(MemoryRegion *address_space,
+MemoryRegionSection memory_region_find(MemoryRegion *mr,
                                        hwaddr addr, uint64_t size);
 
 /**
diff --git a/memory.c b/memory.c
index 75ca281..34bfb13 100644
--- a/memory.c
+++ b/memory.c
@@ -1451,15 +1451,24 @@  static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr)
                    sizeof(FlatRange), cmp_flatrange_addr);
 }
 
-MemoryRegionSection memory_region_find(MemoryRegion *address_space,
+MemoryRegionSection memory_region_find(MemoryRegion *mr,
                                        hwaddr addr, uint64_t size)
 {
-    AddressSpace *as = memory_region_to_address_space(address_space);
-    AddrRange range = addrrange_make(int128_make64(addr),
-                                     int128_make64(size));
-    FlatRange *fr = address_space_lookup(as, range);
     MemoryRegionSection ret = { .mr = NULL, .size = 0 };
+    MemoryRegion *root;
+    AddressSpace *as;
+    AddrRange range;
+    FlatRange *fr;
+
+    addr += mr->addr;
+    for (root = mr; root->parent; ) {
+        root = root->parent;
+        addr += root->addr;
+    }
 
+    as = memory_region_to_address_space(root);
+    range = addrrange_make(int128_make64(addr), int128_make64(size));
+    fr = address_space_lookup(as, range);
     if (!fr) {
         return ret;
     }
@@ -1470,6 +1479,7 @@  MemoryRegionSection memory_region_find(MemoryRegion *address_space,
     }
 
     ret.mr = fr->mr;
+    ret.address_space = as;
     range = addrrange_intersection(range, fr->addr);
     ret.offset_within_region = fr->offset_in_region;
     ret.offset_within_region += int128_get64(int128_sub(range.start,