Patchwork [1/1] Support 2**64 bytes memory regions.

login
register
mail settings
Submitter Alexander Barabash
Date Jan. 7, 2013, 12:08 p.m.
Message ID <1357560487-15988-1-git-send-email-alexander_barabash@mentor.com>
Download mbox | patch
Permalink /patch/209903/
State New
Headers show

Comments

Alexander Barabash - Jan. 7, 2013, 12:08 p.m.
Memory regions created with size UINT64_MAX
are currently treated as regions of size 2**64 bytes.
This patch adds full support for such regions.

Signed-off-by: Alexander Barabash <alexander_barabash@mentor.com>
---
 exec.c   |    4 ++++
 memory.c |   72 ++++++++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 55 insertions(+), 21 deletions(-)

Patch

diff --git a/exec.c b/exec.c
index 140eb56..8ce8ab4 100644
--- a/exec.c
+++ b/exec.c
@@ -789,6 +789,10 @@  static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
         remain.size -= now.size;
         remain.offset_within_address_space += now.size;
         remain.offset_within_region += now.size;
+        if ((remain.size == TARGET_PAGE_SIZE - 1) &&
+            (section->size == UINT64_MAX)) {
+            remain.size = TARGET_PAGE_SIZE;
+        }
     }
     now = remain;
     if (now.size) {
diff --git a/memory.c b/memory.c
index 1652c10..b30edc8 100644
--- a/memory.c
+++ b/memory.c
@@ -84,6 +84,19 @@  static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
     return addrrange_make(start, int128_sub(end, start));
 }
 
+static uint64_t mr_size_get64(Int128 size)
+{
+    if (int128_eq(size, int128_2_64())) {
+        return UINT64_MAX;
+    }
+    return int128_get64(size);
+}
+
+static uint64_t addrrange_size_get64(const AddrRange *r)
+{
+    return mr_size_get64(r->size);
+}
+
 enum ListenerDirection { Forward, Reverse };
 
 static bool memory_listener_match(MemoryListener *listener,
@@ -93,6 +106,18 @@  static bool memory_listener_match(MemoryListener *listener,
         || listener->address_space_filter == section->address_space;
 }
 
+static hwaddr memory_region_get_last_addr(const MemoryRegion *mr, hwaddr base)
+{
+    return int128_get64(int128_sub(int128_add(int128_make64(base + mr->addr),
+                                              mr->size), int128_one()));
+}
+
+static hwaddr memory_region_get_last_offset(const MemoryRegion *mr)
+{
+    return int128_get64(int128_sub(int128_add(int128_make64(mr->alias_offset),
+                                              mr->size), int128_one()));
+}
+
 #define MEMORY_LISTENER_CALL_GLOBAL(_callback, _direction, _args...)    \
     do {                                                                \
         MemoryListener *_listener;                                      \
@@ -150,7 +175,7 @@  static bool memory_listener_match(MemoryListener *listener,
         .mr = (fr)->mr,                                                 \
         .address_space = (as),                                          \
         .offset_within_region = (fr)->offset_in_region,                 \
-        .size = int128_get64((fr)->addr.size),                          \
+                    .size = flatrange_size_get64(fr),                   \
         .offset_within_address_space = int128_get64((fr)->addr.start),  \
         .readonly = (fr)->readonly,                                     \
               }))
@@ -204,6 +229,12 @@  static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
         && !memory_region_ioeventfd_before(b, a);
 }
 
+static
+uint64_t memory_region_ioeventfd_size_get64(const MemoryRegionIoeventfd *fd)
+{
+    return addrrange_size_get64(&fd->addr);
+}
+
 typedef struct FlatRange FlatRange;
 typedef struct FlatView FlatView;
 
@@ -240,6 +271,11 @@  static bool flatrange_equal(FlatRange *a, FlatRange *b)
         && a->readonly == b->readonly;
 }
 
+static uint64_t flatrange_size_get64(const FlatRange *fr)
+{
+    return addrrange_size_get64(&fr->addr);
+}
+
 static void flatview_init(FlatView *view)
 {
     view->ranges = NULL;
@@ -598,7 +634,7 @@  static void address_space_add_del_ioeventfds(AddressSpace *as,
             section = (MemoryRegionSection) {
                 .address_space = as,
                 .offset_within_address_space = int128_get64(fd->addr.start),
-                .size = int128_get64(fd->addr.size),
+                .size = memory_region_ioeventfd_size_get64(fd),
             };
             MEMORY_LISTENER_CALL(eventfd_del, Forward, &section,
                                  fd->match_data, fd->data, fd->e);
@@ -611,7 +647,7 @@  static void address_space_add_del_ioeventfds(AddressSpace *as,
             section = (MemoryRegionSection) {
                 .address_space = as,
                 .offset_within_address_space = int128_get64(fd->addr.start),
-                .size = int128_get64(fd->addr.size),
+                .size = memory_region_ioeventfd_size_get64(fd),
             };
             MEMORY_LISTENER_CALL(eventfd_add, Reverse, &section,
                                  fd->match_data, fd->data, fd->e);
@@ -1030,10 +1066,7 @@  void memory_region_destroy(MemoryRegion *mr)
 
 uint64_t memory_region_size(MemoryRegion *mr)
 {
-    if (int128_eq(mr->size, int128_2_64())) {
-        return UINT64_MAX;
-    }
-    return int128_get64(mr->size);
+    return mr_size_get64(mr->size);
 }
 
 const char *memory_region_name(MemoryRegion *mr)
@@ -1163,12 +1196,12 @@  static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa
             section = (MemoryRegionSection) {
                 .address_space = as,
                 .offset_within_address_space = int128_get64(fr->addr.start),
-                .size = int128_get64(fr->addr.size),
+                .size = flatrange_size_get64(fr),
             };
 
             MEMORY_LISTENER_CALL(coalesced_mmio_del, Reverse, &section,
                                  int128_get64(fr->addr.start),
-                                 int128_get64(fr->addr.size));
+                                 flatrange_size_get64(fr));
             QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
                 tmp = addrrange_shift(cmr->addr,
                                       int128_sub(fr->addr.start,
@@ -1179,7 +1212,7 @@  static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa
                 tmp = addrrange_intersection(tmp, fr->addr);
                 MEMORY_LISTENER_CALL(coalesced_mmio_add, Forward, &section,
                                      int128_get64(tmp.start),
-                                     int128_get64(tmp.size));
+                                     addrrange_size_get64(&tmp));
             }
         }
     }
@@ -1197,7 +1230,7 @@  static void memory_region_update_coalesced_range(MemoryRegion *mr)
 void memory_region_set_coalescing(MemoryRegion *mr)
 {
     memory_region_clear_coalescing(mr);
-    memory_region_add_coalescing(mr, 0, int128_get64(mr->size));
+    memory_region_add_coalescing(mr, 0, memory_region_size(mr));
 }
 
 void memory_region_add_coalescing(MemoryRegion *mr,
@@ -1331,10 +1364,10 @@  static void memory_region_add_subregion_common(MemoryRegion *mr,
         printf("warning: subregion collision %llx/%llx (%s) "
                "vs %llx/%llx (%s)\n",
                (unsigned long long)offset,
-               (unsigned long long)int128_get64(subregion->size),
+               (unsigned long long)memory_region_size(subregion),
                subregion->name,
                (unsigned long long)other->addr,
-               (unsigned long long)int128_get64(other->size),
+               (unsigned long long)memory_region_size(other),
                other->name);
 #endif
     }
@@ -1474,7 +1507,7 @@  MemoryRegionSection memory_region_find(MemoryRegion *address_space,
     ret.offset_within_region = fr->offset_in_region;
     ret.offset_within_region += int128_get64(int128_sub(range.start,
                                                         fr->addr.start));
-    ret.size = int128_get64(range.size);
+    ret.size = addrrange_size_get64(&range);
     ret.offset_within_address_space = int128_get64(range.start);
     ret.readonly = fr->readonly;
     return ret;
@@ -1523,7 +1556,7 @@  static void listener_add_address_space(MemoryListener *listener,
             .mr = fr->mr,
             .address_space = as,
             .offset_within_region = fr->offset_in_region,
-            .size = int128_get64(fr->addr.size),
+            .size = flatrange_size_get64(fr),
             .offset_within_address_space = int128_get64(fr->addr.start),
             .readonly = fr->readonly,
         };
@@ -1652,8 +1685,7 @@  static void mtree_print_mr(fprintf_function mon_printf, void *f,
                    " (prio %d, %c%c): alias %s @%s " TARGET_FMT_plx
                    "-" TARGET_FMT_plx "\n",
                    base + mr->addr,
-                   base + mr->addr
-                   + (hwaddr)int128_get64(mr->size) - 1,
+                   memory_region_get_last_addr(mr, base),
                    mr->priority,
                    mr->readable ? 'R' : '-',
                    !mr->readonly && !(mr->rom_device && mr->readable) ? 'W'
@@ -1661,14 +1693,12 @@  static void mtree_print_mr(fprintf_function mon_printf, void *f,
                    mr->name,
                    mr->alias->name,
                    mr->alias_offset,
-                   mr->alias_offset
-                   + (hwaddr)int128_get64(mr->size) - 1);
+                   memory_region_get_last_offset(mr));
     } else {
         mon_printf(f,
                    TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): %s\n",
                    base + mr->addr,
-                   base + mr->addr
-                   + (hwaddr)int128_get64(mr->size) - 1,
+                   memory_region_get_last_addr(mr, base),
                    mr->priority,
                    mr->readable ? 'R' : '-',
                    !mr->readonly && !(mr->rom_device && mr->readable) ? 'W'