mem: mmap the backing store with MAP_NORESERVE
authorAndreas Hansson <andreas.hansson@arm.com>
Mon, 16 Feb 2015 08:33:47 +0000 (03:33 -0500)
committerAndreas Hansson <andreas.hansson@arm.com>
Mon, 16 Feb 2015 08:33:47 +0000 (03:33 -0500)
This patch ensures we can run simulations with very large simulated
memories (at least 64 TB based on some quick runs on a Linux
workstation). In essence this allows us to efficiently deal with
sparse address maps without having to implement a redirection layer in
the backing store.

This opens up for run-time errors if we eventually exhausts the hosts
memory and swap space, but this should hopefully never happen.

src/mem/physical.cc
src/mem/physical.hh
src/sim/System.py
src/sim/system.cc

index b5627cfa2ec46546ed22df66c86cb6e25c595854..e6d68262498e45c66b4210a32c1489fd06bc7bde 100644 (file)
 #include "mem/abstract_mem.hh"
 #include "mem/physical.hh"
 
+/**
+ * On Linux, MAP_NORESERVE allow us to simulate a very large memory
+ * without committing to actually providing the swap space on the
+ * host. On OSX the MAP_NORESERVE flag does not exist, so simply make
+ * it 0.
+ */
+#if defined(__APPLE__)
+#ifndef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+#endif
+
 using namespace std;
 
 PhysicalMemory::PhysicalMemory(const string& _name,
-                               const vector<AbstractMemory*>& _memories) :
-    _name(_name), rangeCache(addrMap.end()), size(0)
+                               const vector<AbstractMemory*>& _memories,
+                               bool mmap_using_noreserve) :
+    _name(_name), rangeCache(addrMap.end()), size(0),
+    mmapUsingNoReserve(mmap_using_noreserve)
 {
+    if (mmap_using_noreserve)
+        warn("Not reserving swap space. May cause SIGSEGV on actual usage\n");
+
     // add the memories from the system to the address map as
     // appropriate
     for (const auto& m : _memories) {
@@ -148,6 +165,13 @@ PhysicalMemory::createBackingStore(AddrRange range,
     DPRINTF(AddrRanges, "Creating backing store for range %s with size %d\n",
             range.to_string(), range.size());
     int map_flags = MAP_ANON | MAP_PRIVATE;
+
+    // to be able to simulate very large memories, the user can opt to
+    // pass noreserve to mmap
+    if (mmapUsingNoReserve) {
+        map_flags |= MAP_NORESERVE;
+    }
+
     uint8_t* pmem = (uint8_t*) mmap(NULL, range.size(),
                                     PROT_READ | PROT_WRITE,
                                     map_flags, -1, 0);
index b8d26fd4b05db00fc357877c1b954475ea4e2dec..0f53b1d9d264019bf04fe658197097a68fad105c 100644 (file)
@@ -85,6 +85,9 @@ class PhysicalMemory : public Serializable
     // The total memory size
     uint64_t size;
 
+    // Let the user choose if we reserve swap space when calling mmap
+    const bool mmapUsingNoReserve;
+
     // The physical memory used to provide the memory in the simulated
     // system
     std::vector<std::pair<AddrRange, uint8_t*>> backingStore;
@@ -112,7 +115,8 @@ class PhysicalMemory : public Serializable
      * Create a physical memory object, wrapping a number of memories.
      */
     PhysicalMemory(const std::string& _name,
-                   const std::vector<AbstractMemory*>& _memories);
+                   const std::vector<AbstractMemory*>& _memories,
+                   bool mmap_using_noreserve);
 
     /**
      * Unmap all the backing store we have used.
index 630cd2a84bac2adc6f914a78734461b2c7a3e9ce..e24a1e6b20f8c0e0a39304b082e588fd87dbfe27 100644 (file)
@@ -59,6 +59,13 @@ class System(MemObject):
                                           "All memories in the system")
     mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
 
+    # When reserving memory on the host, we have the option of
+    # reserving swap space or not (by passing MAP_NORESERVE to
+    # mmap). By enabling this flag, we accomodate cases where a large
+    # (but sparse) memory is simulated.
+    mmap_using_noreserve = Param.Bool(False, "mmap the backing store " \
+                                          "without reserving swap")
+
     # The memory ranges are to be populated when creating the system
     # such that these can be passed from the I/O subsystem through an
     # I/O bridge or cache
index c311d65b92bd3e3c82bd2b05d8f5c0af30e5ebd9..9bd487b0360d5e8958cd029c6dac9eda3f0385e6 100644 (file)
@@ -88,7 +88,7 @@ System::System(Params *p)
       loadAddrMask(p->load_addr_mask),
       loadAddrOffset(p->load_offset),
       nextPID(0),
-      physmem(name() + ".physmem", p->memories),
+      physmem(name() + ".physmem", p->memories, p->mmap_using_noreserve),
       memoryMode(p->mem_mode),
       _cacheLineSize(p->cache_line_size),
       workItemsBegin(0),