syscall_emul: extend mmap system call to support file backed mmaps
authorBrandon Potter <brandon.potter@amd.com>
Thu, 17 Mar 2016 17:24:17 +0000 (10:24 -0700)
committerBrandon Potter <brandon.potter@amd.com>
Thu, 17 Mar 2016 17:24:17 +0000 (10:24 -0700)
For O3, which has a stat that counts reg reads, there is an additional
reg read per mmap() call since there's an arg we no longer ignore.
Otherwise, stats should not be affected.

19 files changed:
src/arch/alpha/linux/linux.cc
src/arch/alpha/linux/linux.hh
src/arch/alpha/tru64/tru64.cc
src/arch/alpha/tru64/tru64.hh
src/arch/arm/freebsd/freebsd.hh
src/arch/arm/linux/linux.cc
src/arch/arm/linux/linux.hh
src/arch/mips/linux/linux.cc
src/arch/mips/linux/linux.hh
src/arch/power/linux/linux.cc
src/arch/power/linux/linux.hh
src/arch/sparc/linux/linux.cc
src/arch/sparc/linux/linux.hh
src/arch/sparc/solaris/solaris.cc
src/arch/sparc/solaris/solaris.hh
src/arch/x86/linux/linux.cc
src/arch/x86/linux/linux.hh
src/sim/syscall_emul.cc
src/sim/syscall_emul.hh

index b86b92c2ee6c6a11fa3a25abd35cc9f97d3e34ee..7b747f127b7cd7b708f4e121622e921a771d4344 100644 (file)
  * Authors: Korey Sewell
  */
 
-#include <fcntl.h>
-
 #include "arch/alpha/linux/linux.hh"
 
+#include <fcntl.h>
+#include <sys/mman.h>
+
 // open(2) flags translation table
 SyscallFlagTransTable AlphaLinux::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -99,3 +100,28 @@ SyscallFlagTransTable AlphaLinux::openFlagTable[] = {
 
 const int AlphaLinux::NUM_OPEN_FLAGS =
     (sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0]));
+
+// mmap(2) flags translation table
+SyscallFlagTransTable AlphaLinux::mmapFlagTable[] = {
+  { AlphaLinux::TGT_MAP_SHARED,     MAP_SHARED },
+  { AlphaLinux::TGT_MAP_PRIVATE,    MAP_PRIVATE },
+  { AlphaLinux::TGT_MAP_ANON,       MAP_ANON },
+  { AlphaLinux::TGT_MAP_DENYWRITE,  MAP_DENYWRITE },
+  { AlphaLinux::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { AlphaLinux::TGT_MAP_FILE,       MAP_FILE },
+  { AlphaLinux::TGT_MAP_GROWSDOWN,  MAP_GROWSDOWN },
+  { AlphaLinux::TGT_MAP_HUGETLB,    MAP_HUGETLB },
+  { AlphaLinux::TGT_MAP_LOCKED,     MAP_LOCKED },
+  { AlphaLinux::TGT_MAP_NONBLOCK,   MAP_NONBLOCK },
+  { AlphaLinux::TGT_MAP_NORESERVE,  MAP_NORESERVE },
+  { AlphaLinux::TGT_MAP_POPULATE,   MAP_POPULATE },
+#ifdef MAP_STACK
+  { AlphaLinux::TGT_MAP_STACK,      MAP_STACK },
+#endif
+  { AlphaLinux::TGT_MAP_ANONYMOUS,  MAP_ANONYMOUS },
+  { AlphaLinux::TGT_MAP_FIXED,      MAP_FIXED },
+};
+
+const unsigned AlphaLinux::NUM_MMAP_FLAGS =
+        sizeof(AlphaLinux::mmapFlagTable) /
+        sizeof(AlphaLinux::mmapFlagTable[0]);
index 7864c64144203bf02ed97e352630ed180b2109df..409ad4dd1c3c9070667e56ceab503653ea59bcb9 100644 (file)
@@ -104,8 +104,25 @@ class AlphaLinux : public Linux
     //@}
 
     /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-    static const unsigned TGT_MAP_FIXED     = 0x100;
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x000001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x000002;
+    static const unsigned TGT_MAP_ANON          = 0x000010;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x002000;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x004000;
+    static const unsigned TGT_MAP_FILE          = 0x000000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x001000;
+    static const unsigned TGT_MAP_HUGETLB       = 0x100000;
+    static const unsigned TGT_MAP_LOCKED        = 0x008000;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x040000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x010000;
+    static const unsigned TGT_MAP_POPULATE      = 0x020000;
+    static const unsigned TGT_MAP_STACK         = 0x080000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x000010;
+    static const unsigned TGT_MAP_FIXED         = 0x000100;
+
+    static const unsigned NUM_MMAP_FLAGS;
 
     //@{
     /// For getsysinfo().
index 1854a02f17f5cb00e3ed621208594ea563a7d252..1fd589f667c1f77e7e86b48b8d8c8789f587c7a3 100644 (file)
@@ -68,5 +68,27 @@ SyscallFlagTransTable AlphaTru64::openFlagTable[] = {
 const int AlphaTru64::NUM_OPEN_FLAGS =
         (sizeof(AlphaTru64::openFlagTable)/sizeof(AlphaTru64::openFlagTable[0]));
 
+// mmap(2) flags translation table
+SyscallFlagTransTable AlphaTru64::mmapFlagTable[] = {
+  { TGT_MAP_SHARED, MAP_SHARED },
+  { TGT_MAP_PRIVATE, MAP_PRIVATE },
+  { TGT_MAP_32BIT, MAP_32BIT},
+  { TGT_MAP_ANON, MAP_ANON },
+  { TGT_MAP_DENYWRITE, MAP_DENYWRITE },
+  { TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { TGT_MAP_FILE, MAP_FILE },
+  { TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
+  { TGT_MAP_HUGETLB, MAP_HUGETLB },
+  { TGT_MAP_LOCKED, MAP_LOCKED },
+  { TGT_MAP_NONBLOCK, MAP_NONBLOCK },
+  { TGT_MAP_NORESERVE, MAP_NORESERVE },
+  { TGT_MAP_POPULATE, MAP_POPULATE },
+  { TGT_MAP_STACK, MAP_STACK },
+  { TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
+  { TGT_MAP_FIXED, MAP_FIXED },
+};
 
+const unsigned AlphaTru64::NUM_MMAP_FLAGS =
+        sizeof(AlphaTru64::mmapFlagTable) /
+        sizeof(AlphaTru64::mmapFlagTable[0]);
 
index 92d6db84259a5e8d6ebcd00f8999dd34b0a34fbd..e8ac3c7e83b574cb45fca3284f23c52b3823aa01 100644 (file)
@@ -63,8 +63,28 @@ class AlphaTru64 : public Tru64
     //@}
 
     /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-    static const unsigned TGT_MAP_FIXED     = 0x100;
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_32BIT         = 0x00040;
+    static const unsigned TGT_MAP_ANON          = 0x00020;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x00800;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x01000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x00100;
+    static const unsigned TGT_MAP_HUGETLB       = 0x40000;
+    static const unsigned TGT_MAP_LOCKED        = 0x02000;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x10000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x04000;
+    static const unsigned TGT_MAP_POPULATE      = 0x08000;
+    static const unsigned TGT_MAP_STACK         = 0x20000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00020;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+
+    static const unsigned NUM_MMAP_FLAGS;
+
+    //@{
 
     //@{
     /// For getsysinfo().
index 7e85659ecb87ded9ff3cdd2263786bf6cc6a1baf..e2c5e493c323c6579a2b956d89a62773b3a9b796 100644 (file)
@@ -74,6 +74,8 @@ class ArmFreebsd32 : public FreeBSD
     //@}
 
     /// For mmap().
+    static const unsigned TGT_MAP_SHARED    = 0x0001;
+    static const unsigned TGT_MAP_PRIVATE   = 0x0002;
     static const unsigned TGT_MAP_ANONYMOUS = 0x1000;
     static const unsigned TGT_MAP_FIXED     = 0x0010;
 
@@ -229,6 +231,8 @@ class ArmFreebsd64 : public FreeBSD
     //@}
 
     /// For mmap().
+    static const unsigned TGT_MAP_SHARED    = 0x0001;
+    static const unsigned TGT_MAP_PRIVATE   = 0x0002;
     static const unsigned TGT_MAP_ANONYMOUS = 0x1000;
     static const unsigned TGT_MAP_FIXED     = 0x0010;
 
index ac114048ae3c4b2e741e4638d521fa8a4f66d548..3dde8c2175b5d3a9f38e2d4ca28d4fcc932445c3 100644 (file)
  * Authors: Stephen Hines
  */
 
-#include <fcntl.h>
-
 #include "arch/arm/linux/linux.hh"
 
+#include <fcntl.h>
+#include <sys/mman.h>
+
 // open(2) flags translation table
 SyscallFlagTransTable ArmLinux32::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -121,6 +122,31 @@ SyscallFlagTransTable ArmLinux32::openFlagTable[] = {
 const int ArmLinux32::NUM_OPEN_FLAGS = sizeof(ArmLinux32::openFlagTable) /
                                        sizeof(ArmLinux32::openFlagTable[0]);
 
+// mmap(2) flags translation table
+SyscallFlagTransTable ArmLinux32::mmapFlagTable[] = {
+  { ArmLinux32::TGT_MAP_SHARED,     MAP_SHARED },
+  { ArmLinux32::TGT_MAP_PRIVATE,    MAP_PRIVATE },
+  { ArmLinux32::TGT_MAP_ANON,       MAP_ANON },
+  { ArmLinux32::TGT_MAP_DENYWRITE,  MAP_DENYWRITE },
+  { ArmLinux32::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { ArmLinux32::TGT_MAP_FILE,       MAP_FILE },
+  { ArmLinux32::TGT_MAP_GROWSDOWN,  MAP_GROWSDOWN },
+  { ArmLinux32::TGT_MAP_HUGETLB,    MAP_HUGETLB },
+  { ArmLinux32::TGT_MAP_LOCKED,     MAP_LOCKED },
+  { ArmLinux32::TGT_MAP_NONBLOCK,   MAP_NONBLOCK },
+  { ArmLinux32::TGT_MAP_NORESERVE,  MAP_NORESERVE },
+  { ArmLinux32::TGT_MAP_POPULATE,   MAP_POPULATE },
+#ifdef MAP_STACK
+  { ArmLinux32::TGT_MAP_STACK,      MAP_STACK },
+#endif
+  { ArmLinux32::TGT_MAP_ANONYMOUS,  MAP_ANONYMOUS },
+  { ArmLinux32::TGT_MAP_FIXED,      MAP_FIXED },
+};
+
+const unsigned ArmLinux32::NUM_MMAP_FLAGS =
+        sizeof(ArmLinux32::mmapFlagTable) /
+        sizeof(ArmLinux32::mmapFlagTable[0]);
+
 // open(2) flags translation table
 SyscallFlagTransTable ArmLinux64::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -197,3 +223,28 @@ SyscallFlagTransTable ArmLinux64::openFlagTable[] = {
 const int ArmLinux64::NUM_OPEN_FLAGS = sizeof(ArmLinux64::openFlagTable) /
                                        sizeof(ArmLinux64::openFlagTable[0]);
 
+// mmap(2) flags translation table
+SyscallFlagTransTable ArmLinux64::mmapFlagTable[] = {
+  { ArmLinux64::TGT_MAP_SHARED,     MAP_SHARED },
+  { ArmLinux64::TGT_MAP_PRIVATE,    MAP_PRIVATE },
+  { ArmLinux64::TGT_MAP_ANON,       MAP_ANON },
+  { ArmLinux64::TGT_MAP_DENYWRITE,  MAP_DENYWRITE },
+  { ArmLinux64::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { ArmLinux64::TGT_MAP_FILE,       MAP_FILE },
+  { ArmLinux64::TGT_MAP_GROWSDOWN,  MAP_GROWSDOWN },
+  { ArmLinux64::TGT_MAP_HUGETLB,    MAP_HUGETLB },
+  { ArmLinux64::TGT_MAP_LOCKED,     MAP_LOCKED },
+  { ArmLinux64::TGT_MAP_NONBLOCK,   MAP_NONBLOCK },
+  { ArmLinux64::TGT_MAP_NORESERVE,  MAP_NORESERVE },
+  { ArmLinux64::TGT_MAP_POPULATE,   MAP_POPULATE },
+#ifdef MAP_STACK
+  { ArmLinux64::TGT_MAP_STACK,      MAP_STACK },
+#endif
+  { ArmLinux64::TGT_MAP_ANONYMOUS,  MAP_ANONYMOUS },
+  { ArmLinux64::TGT_MAP_FIXED,      MAP_FIXED },
+};
+
+const unsigned ArmLinux64::NUM_MMAP_FLAGS =
+        sizeof(ArmLinux64::mmapFlagTable) /
+        sizeof(ArmLinux64::mmapFlagTable[0]);
+
index a2eaea52c71018c03814014ab5053563cb2bab0a..5c814cde14c8ff3d378e8fd5cbb70d3b57ee57eb 100644 (file)
@@ -125,8 +125,25 @@ class ArmLinux32 : public Linux
     //@}
 
     /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x20;
-    static const unsigned TGT_MAP_FIXED     = 0x10;
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_ANON          = 0x00020;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x00800;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x01000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x00100;
+    static const unsigned TGT_MAP_HUGETLB       = 0x40000;
+    static const unsigned TGT_MAP_LOCKED        = 0x02000;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x10000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x04000;
+    static const unsigned TGT_MAP_POPULATE      = 0x08000;
+    static const unsigned TGT_MAP_STACK         = 0x20000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00020;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+
+    static const unsigned NUM_MMAP_FLAGS;
 
     /// For table().
     static const int TBL_SYSINFO = 12;
@@ -320,8 +337,25 @@ class ArmLinux64 : public Linux
     //@}
 
     /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x20;
-    static const unsigned TGT_MAP_FIXED     = 0x10;
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_ANON          = 0x00020;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x00800;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x01000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x00100;
+    static const unsigned TGT_MAP_HUGETLB       = 0x40000;
+    static const unsigned TGT_MAP_LOCKED        = 0x02000;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x10000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x04000;
+    static const unsigned TGT_MAP_POPULATE      = 0x08000;
+    static const unsigned TGT_MAP_STACK         = 0x20000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00020;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+
+    static const unsigned NUM_MMAP_FLAGS;
 
     //@{
     /// For getrusage().
index 4861f7cb99269f8cbf1f4ac12b612c8c030cd7db..2f0ca609012103d03597aaa0f1d53207dbb426e7 100644 (file)
  * Authors: Korey Sewell
  */
 
-#include <fcntl.h>
-
 #include "arch/mips/linux/linux.hh"
 
+#include <fcntl.h>
+#include <sys/mman.h>
+
 // open(2) flags translation table
 SyscallFlagTransTable MipsLinux::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -97,3 +98,29 @@ SyscallFlagTransTable MipsLinux::openFlagTable[] = {
 
 const int MipsLinux::NUM_OPEN_FLAGS =
         (sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));
+
+// mmap(2) flags translation table
+SyscallFlagTransTable MipsLinux::mmapFlagTable[] = {
+  { MipsLinux::TGT_MAP_SHARED,     MAP_SHARED },
+  { MipsLinux::TGT_MAP_PRIVATE,    MAP_PRIVATE },
+  { MipsLinux::TGT_MAP_ANON,       MAP_ANON },
+  { MipsLinux::TGT_MAP_DENYWRITE,  MAP_DENYWRITE },
+  { MipsLinux::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { MipsLinux::TGT_MAP_FILE,       MAP_FILE },
+  { MipsLinux::TGT_MAP_GROWSDOWN,  MAP_GROWSDOWN },
+  { MipsLinux::TGT_MAP_HUGETLB,    MAP_HUGETLB },
+  { MipsLinux::TGT_MAP_LOCKED,     MAP_LOCKED },
+  { MipsLinux::TGT_MAP_NONBLOCK,   MAP_NONBLOCK },
+  { MipsLinux::TGT_MAP_NORESERVE,  MAP_NORESERVE },
+  { MipsLinux::TGT_MAP_POPULATE,   MAP_POPULATE },
+#ifdef MAP_STACK
+  { MipsLinux::TGT_MAP_STACK,      MAP_STACK },
+#endif
+  { MipsLinux::TGT_MAP_ANONYMOUS,  MAP_ANONYMOUS },
+  { MipsLinux::TGT_MAP_FIXED,      MAP_FIXED },
+};
+
+const unsigned MipsLinux::NUM_MMAP_FLAGS =
+        sizeof(MipsLinux::mmapFlagTable) /
+        sizeof(MipsLinux::mmapFlagTable[0]);
+
index 6e4b6a82d02f5b107fcc4ef65a64cce715f2ac48..f4b18397e93544dde693eee55c9f2c7c4bc66c25 100644 (file)
@@ -102,8 +102,25 @@ class MipsLinux : public Linux
     //@}
 
     /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x800;
-    static const unsigned TGT_MAP_FIXED     = 0x10;
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_ANON          = 0x00800;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x02000;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x04000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x01000;
+    static const unsigned TGT_MAP_HUGETLB       = 0x80000;
+    static const unsigned TGT_MAP_LOCKED        = 0x08000;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x20000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x00400;
+    static const unsigned TGT_MAP_POPULATE      = 0x10000;
+    static const unsigned TGT_MAP_STACK         = 0x40000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00800;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+
+    static const unsigned NUM_MMAP_FLAGS;
 
     //@{
     /// For getsysinfo().
index f73dd063ba0c10d793c937a3f8a4d87b0063735c..6382ca72a8a1fd109a10a98ebf9b156c887e1210 100644 (file)
  * Authors: Timothy M. Jones
  */
 
-#include <fcntl.h>
-
 #include "arch/power/linux/linux.hh"
 
+#include <fcntl.h>
+#include <sys/mman.h>
+
 // open(2) flags translation table
 SyscallFlagTransTable PowerLinux::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -105,3 +106,28 @@ SyscallFlagTransTable PowerLinux::openFlagTable[] = {
 const int PowerLinux::NUM_OPEN_FLAGS =
         (sizeof(PowerLinux::openFlagTable)/sizeof(PowerLinux::openFlagTable[0]));
 
+// mmap(2) flags translation table
+SyscallFlagTransTable PowerLinux::mmapFlagTable[] = {
+  { PowerLinux::TGT_MAP_SHARED,     MAP_SHARED },
+  { PowerLinux::TGT_MAP_PRIVATE,    MAP_PRIVATE },
+  { PowerLinux::TGT_MAP_ANON,       MAP_ANON },
+  { PowerLinux::TGT_MAP_DENYWRITE,  MAP_DENYWRITE },
+  { PowerLinux::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { PowerLinux::TGT_MAP_FILE,       MAP_FILE },
+  { PowerLinux::TGT_MAP_GROWSDOWN,  MAP_GROWSDOWN },
+  { PowerLinux::TGT_MAP_HUGETLB,    MAP_HUGETLB },
+  { PowerLinux::TGT_MAP_LOCKED,     MAP_LOCKED },
+  { PowerLinux::TGT_MAP_NONBLOCK,   MAP_NONBLOCK },
+  { PowerLinux::TGT_MAP_NORESERVE,  MAP_NORESERVE },
+  { PowerLinux::TGT_MAP_POPULATE,   MAP_POPULATE },
+#ifdef MAP_STACK
+  { PowerLinux::TGT_MAP_STACK,      MAP_STACK },
+#endif
+  { PowerLinux::TGT_MAP_ANONYMOUS,  MAP_ANONYMOUS },
+  { PowerLinux::TGT_MAP_FIXED,      MAP_FIXED },
+};
+
+const unsigned PowerLinux::NUM_MMAP_FLAGS =
+        sizeof(PowerLinux::mmapFlagTable) /
+        sizeof(PowerLinux::mmapFlagTable[0]);
+
index 656f4402e882ddbccd531c2c4dfd948ed1fa17fa..55634800e687dc7199a01127965c4b4d636f2a1e 100644 (file)
@@ -164,8 +164,25 @@ class PowerLinux : public Linux
     //@}
 
     /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x20;
-    static const unsigned TGT_MAP_FIXED     = 0x10;
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_ANON          = 0x00020;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x00800;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x01000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x00100;
+    static const unsigned TGT_MAP_HUGETLB       = 0x40000;
+    static const unsigned TGT_MAP_LOCKED        = 0x00080;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x10000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x00040;
+    static const unsigned TGT_MAP_POPULATE      = 0x08000;
+    static const unsigned TGT_MAP_STACK         = 0x20000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00020;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+
+    static const unsigned NUM_MMAP_FLAGS;
 
     //@{
     /// ioctl() command codes.
index 2f91cf81d712411316a4ac84081c4ea936a1c2ef..dbc7e9691579cfc45673b910c87d95189748fab3 100644 (file)
  * Authors: Gabe Black
  */
 
-#include <fcntl.h>
-
 #include "arch/sparc/linux/linux.hh"
 
+#include <fcntl.h>
+#include <sys/mman.h>
+
 // open(2) flags translation table
 SyscallFlagTransTable SparcLinux::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -95,3 +96,32 @@ SyscallFlagTransTable SparcLinux::openFlagTable[] = {
 const int SparcLinux::NUM_OPEN_FLAGS =
         (sizeof(SparcLinux::openFlagTable)/sizeof(SparcLinux::openFlagTable[0]));
 
+// mmap(2) flags translation table
+SyscallFlagTransTable SparcLinux::mmapFlagTable[] = {
+  { SparcLinux::TGT_MAP_SHARED,     MAP_SHARED },
+  { SparcLinux::TGT_MAP_PRIVATE,    MAP_PRIVATE },
+  { SparcLinux::TGT_MAP_ANON,       MAP_ANON },
+  { SparcLinux::TGT_MAP_DENYWRITE,  MAP_DENYWRITE },
+  { SparcLinux::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { SparcLinux::TGT_MAP_FILE,       MAP_FILE },
+  { SparcLinux::TGT_MAP_GROWSDOWN,  MAP_GROWSDOWN },
+  { SparcLinux::TGT_MAP_HUGETLB,    MAP_HUGETLB },
+  { SparcLinux::TGT_MAP_LOCKED,     MAP_LOCKED },
+  { SparcLinux::TGT_MAP_NONBLOCK,   MAP_NONBLOCK },
+  { SparcLinux::TGT_MAP_NORESERVE,  MAP_NORESERVE },
+  { SparcLinux::TGT_MAP_POPULATE,   MAP_POPULATE },
+#ifdef MAP_STACK
+  { SparcLinux::TGT_MAP_STACK,      MAP_STACK },
+#endif
+  { SparcLinux::TGT_MAP_ANONYMOUS,  MAP_ANONYMOUS },
+  { SparcLinux::TGT_MAP_FIXED,      MAP_FIXED },
+#ifdef MAP_INHERIT
+  { SparcLinux::TGT_MAP_INHERIT,    MAP_INHERIT },
+#endif
+  { SparcLinux::TGT_MAP_POPULATE,   MAP_POPULATE },
+};
+
+const unsigned SparcLinux::NUM_MMAP_FLAGS =
+        sizeof(SparcLinux::mmapFlagTable) /
+        sizeof(SparcLinux::mmapFlagTable[0]);
+
index 138f178b74dcb8c4bcdca4c9f5b624cb7473e730..d0631f82b053c87921fd513f04f9a9df61d935dc 100644 (file)
@@ -118,8 +118,27 @@ class SparcLinux : public Linux
 
     static const int NUM_OPEN_FLAGS;
 
-    static const unsigned TGT_MAP_ANONYMOUS = 0x20;
-    static const unsigned TGT_MAP_FIXED     = 0x10;
+    /// For mmap().
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_ANON          = 0x00020;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x00800;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x01000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x00200;
+    static const unsigned TGT_MAP_HUGETLB       = 0x40000;
+    static const unsigned TGT_MAP_LOCKED        = 0x00100;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x10000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x00040;
+    static const unsigned TGT_MAP_POPULATE      = 0x08000;
+    static const unsigned TGT_MAP_STACK         = 0x20000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00020;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+    static const unsigned TGT_MAP_INHERIT       = 0x00080;
+
+    static const unsigned NUM_MMAP_FLAGS;
 
     typedef struct {
         int64_t  uptime;    /* Seconds since boot */
index e17de3af055d60fe2518a61796e8f66dcdb8224a..afedcfe88c03ac1f2b5b87e80e38193bcd0a2287 100644 (file)
  * Authors: Ali Saidi
  */
 
-#include <fcntl.h>
-
 #include "arch/sparc/solaris/solaris.hh"
 
+#include <fcntl.h>
+#include <sys/mman.h>
+
 // open(2) flags translation table
 SyscallFlagTransTable SparcSolaris::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -76,3 +77,27 @@ SyscallFlagTransTable SparcSolaris::openFlagTable[] = {
 const int SparcSolaris::NUM_OPEN_FLAGS =
         (sizeof(SparcSolaris::openFlagTable)/sizeof(SparcSolaris::openFlagTable[0]));
 
+// mmap(2) flags translation table
+SyscallFlagTransTable SparcSolaris::mmapFlagTable[] = {
+  { TGT_MAP_SHARED, MAP_SHARED },
+  { TGT_MAP_PRIVATE, MAP_PRIVATE },
+  { TGT_MAP_32BIT, MAP_32BIT},
+  { TGT_MAP_ANON, MAP_ANON },
+  { TGT_MAP_DENYWRITE, MAP_DENYWRITE },
+  { TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { TGT_MAP_FILE, MAP_FILE },
+  { TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
+  { TGT_MAP_HUGETLB, MAP_HUGETLB },
+  { TGT_MAP_LOCKED, MAP_LOCKED },
+  { TGT_MAP_NONBLOCK, MAP_NONBLOCK },
+  { TGT_MAP_NORESERVE, MAP_NORESERVE },
+  { TGT_MAP_POPULATE, MAP_POPULATE },
+  { TGT_MAP_STACK, MAP_STACK },
+  { TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
+  { TGT_MAP_FIXED, MAP_FIXED },
+};
+
+const unsigned SparcSolaris::NUM_MMAP_FLAGS =
+        sizeof(SparcSolaris::mmapFlagTable) /
+        sizeof(SparcSolaris::mmapFlagTable[0]);
+
index 9827b6b500dc8fb35ed16e7cc8f5a54f59c2c085..1e814bc53a9b9922016de49f8287fa045b2edfef 100644 (file)
@@ -58,8 +58,27 @@ class SparcSolaris : public Solaris
 
     static const int NUM_OPEN_FLAGS;
 
-    static const unsigned TGT_MAP_ANONYMOUS = 0x100;
-    static const unsigned TGT_MAP_FIXED     = 0x10;
+    /// For mmap().
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_32BIT         = 0x00040;
+    static const unsigned TGT_MAP_ANON          = 0x00020;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x00800;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x01000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x00100;
+    static const unsigned TGT_MAP_HUGETLB       = 0x40000;
+    static const unsigned TGT_MAP_LOCKED        = 0x02000;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x10000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x04000;
+    static const unsigned TGT_MAP_POPULATE      = 0x08000;
+    static const unsigned TGT_MAP_STACK         = 0x20000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00020;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+
+    static const unsigned NUM_MMAP_FLAGS;
 };
 
 #endif
index 2eab555ce0de0e477016552b2056527147f6737a..f51bb16e7a8b67ced8376434823975df287dbd80 100644 (file)
  * Authors: Gabe Black
  */
 
-#include <fcntl.h>
-
 #include "arch/x86/linux/linux.hh"
 
+#include <fcntl.h>
+#include <sys/mman.h>
+
 // open(2) flags translation table
 SyscallFlagTransTable X86Linux64::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -110,6 +111,34 @@ const int X86Linux64::NUM_OPEN_FLAGS =
         sizeof(X86Linux64::openFlagTable) /
         sizeof(X86Linux64::openFlagTable[0]);
 
+// mmap(2) flags translation table
+SyscallFlagTransTable X86Linux64::mmapFlagTable[] = {
+  { X86Linux64::TGT_MAP_SHARED,     MAP_SHARED },
+  { X86Linux64::TGT_MAP_PRIVATE,    MAP_PRIVATE },
+  { X86Linux64::TGT_MAP_32BIT,      MAP_32BIT},
+  { X86Linux64::TGT_MAP_ANON,       MAP_ANON },
+  { X86Linux64::TGT_MAP_DENYWRITE,  MAP_DENYWRITE },
+  { X86Linux64::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { X86Linux64::TGT_MAP_FILE,       MAP_FILE },
+  { X86Linux64::TGT_MAP_GROWSDOWN,  MAP_GROWSDOWN },
+#ifdef MAP_HUGETLB
+  { X86Linux64::TGT_MAP_HUGETLB,    MAP_HUGETLB },
+#endif
+  { X86Linux64::TGT_MAP_LOCKED,     MAP_LOCKED },
+  { X86Linux64::TGT_MAP_NONBLOCK,   MAP_NONBLOCK },
+  { X86Linux64::TGT_MAP_NORESERVE,  MAP_NORESERVE },
+  { X86Linux64::TGT_MAP_POPULATE,   MAP_POPULATE },
+#ifdef MAP_STACK
+  { X86Linux64::TGT_MAP_STACK,      MAP_STACK },
+#endif
+  { X86Linux64::TGT_MAP_ANONYMOUS,  MAP_ANONYMOUS },
+  { X86Linux64::TGT_MAP_FIXED,      MAP_FIXED },
+};
+
+const unsigned X86Linux64::NUM_MMAP_FLAGS =
+        sizeof(X86Linux64::mmapFlagTable) /
+        sizeof(X86Linux64::mmapFlagTable[0]);
+
 // open(2) flags translation table
 SyscallFlagTransTable X86Linux32::openFlagTable[] = {
 #ifdef _MSC_VER
@@ -179,3 +208,30 @@ const int X86Linux32::NUM_OPEN_FLAGS =
         sizeof(X86Linux32::openFlagTable) /
         sizeof(X86Linux32::openFlagTable[0]);
 
+// mmap(2) flags translation table
+SyscallFlagTransTable X86Linux32::mmapFlagTable[] = {
+  { X86Linux32::TGT_MAP_SHARED,     MAP_SHARED },
+  { X86Linux32::TGT_MAP_PRIVATE,    MAP_PRIVATE },
+  { X86Linux32::TGT_MAP_32BIT,      MAP_32BIT},
+  { X86Linux32::TGT_MAP_ANON,       MAP_ANON },
+  { X86Linux32::TGT_MAP_DENYWRITE,  MAP_DENYWRITE },
+  { X86Linux32::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
+  { X86Linux32::TGT_MAP_FILE,       MAP_FILE },
+  { X86Linux32::TGT_MAP_GROWSDOWN,  MAP_GROWSDOWN },
+#ifdef MAP_HUGETLB
+  { X86Linux32::TGT_MAP_HUGETLB,    MAP_HUGETLB },
+#endif
+  { X86Linux32::TGT_MAP_LOCKED,     MAP_LOCKED },
+  { X86Linux32::TGT_MAP_NONBLOCK,   MAP_NONBLOCK },
+  { X86Linux32::TGT_MAP_NORESERVE,  MAP_NORESERVE },
+  { X86Linux32::TGT_MAP_POPULATE,   MAP_POPULATE },
+#ifdef MAP_STACK
+  { X86Linux32::TGT_MAP_STACK,      MAP_STACK },
+#endif
+  { X86Linux32::TGT_MAP_ANONYMOUS,  MAP_ANONYMOUS },
+  { X86Linux32::TGT_MAP_FIXED,      MAP_FIXED },
+};
+
+const unsigned X86Linux32::NUM_MMAP_FLAGS =
+        sizeof(X86Linux32::mmapFlagTable) /
+        sizeof(X86Linux32::mmapFlagTable[0]);
index 854ab00a0d905c678d4ff9c5e1a50de2a0da458c..ce395f17df5e81ff4fcf64c9912e1c54f22bb3e1 100644 (file)
@@ -126,8 +126,27 @@ class X86Linux64 : public Linux
 
     static const int NUM_OPEN_FLAGS;
 
-    static const unsigned TGT_MAP_ANONYMOUS = 0x20;
-    static const unsigned TGT_MAP_FIXED     = 0x10;
+    /// For mmap().
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_32BIT         = 0x00040;
+    static const unsigned TGT_MAP_ANON          = 0x00020;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x00800;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x01000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x00100;
+    static const unsigned TGT_MAP_HUGETLB       = 0x40000;
+    static const unsigned TGT_MAP_LOCKED        = 0x02000;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x10000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x04000;
+    static const unsigned TGT_MAP_POPULATE      = 0x08000;
+    static const unsigned TGT_MAP_STACK         = 0x20000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00020;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+
+    static const unsigned NUM_MMAP_FLAGS;
 
     typedef struct {
         uint64_t iov_base; // void *
@@ -147,7 +166,7 @@ class X86Linux64 : public Linux
         uint64_t totalhigh; /* Total high memory size */
         uint64_t freehigh;  /* Available high memory size */
         uint64_t mem_unit;  /* Memory unit size in bytes */
-   } tgt_sysinfo;
+    } tgt_sysinfo;
 
 };
 
@@ -236,8 +255,26 @@ class X86Linux32 : public Linux
 
     static const int NUM_OPEN_FLAGS;
 
-    static const unsigned TGT_MAP_ANONYMOUS = 0x20;
-    static const unsigned TGT_MAP_FIXED     = 0x10;
+    static SyscallFlagTransTable mmapFlagTable[];
+
+    static const unsigned TGT_MAP_SHARED        = 0x00001;
+    static const unsigned TGT_MAP_PRIVATE       = 0x00002;
+    static const unsigned TGT_MAP_32BIT         = 0x00040;
+    static const unsigned TGT_MAP_ANON          = 0x00020;
+    static const unsigned TGT_MAP_DENYWRITE     = 0x00800;
+    static const unsigned TGT_MAP_EXECUTABLE    = 0x01000;
+    static const unsigned TGT_MAP_FILE          = 0x00000;
+    static const unsigned TGT_MAP_GROWSDOWN     = 0x00100;
+    static const unsigned TGT_MAP_HUGETLB       = 0x40000;
+    static const unsigned TGT_MAP_LOCKED        = 0x02000;
+    static const unsigned TGT_MAP_NONBLOCK      = 0x10000;
+    static const unsigned TGT_MAP_NORESERVE     = 0x04000;
+    static const unsigned TGT_MAP_POPULATE      = 0x08000;
+    static const unsigned TGT_MAP_STACK         = 0x20000;
+    static const unsigned TGT_MAP_ANONYMOUS     = 0x00020;
+    static const unsigned TGT_MAP_FIXED         = 0x00010;
+
+    static const unsigned NUM_MMAP_FLAGS;
 
     typedef struct {
        int32_t  uptime;    /* Seconds since boot */
index 517580d79922aa6f526d3ba89c354b2739706934..392658c5a0ec87bc919edd397678194ba58b405d 100644 (file)
@@ -324,7 +324,9 @@ _llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
 SyscallReturn
 munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
 {
-    // given that we don't really implement mmap, munmap is really easy
+    // With mmap more fully implemented, it might be worthwhile to bite
+    // the bullet and implement munmap. Should allow us to reuse simulated
+    // memory.
     return 0;
 }
 
index 080dcb011d5cf617613b9e609ebf1e954bafcf80..34fbc6618dfe3e463c2c8ee4e33f64b602266f52 100644 (file)
@@ -58,6 +58,7 @@
 #ifdef __CYGWIN32__
 #include <sys/fcntl.h>  // for O_BINARY
 #endif
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/uio.h>
@@ -1224,12 +1225,6 @@ writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 
 
 /// Target mmap() handler.
-///
-/// We don't really handle mmap().  If the target is mmaping an
-/// anonymous region or /dev/zero, we can get away with doing basically
-/// nothing (since memory is initialized to zero and the simulator
-/// doesn't really check addresses anyway).
-///
 template <class OS>
 SyscallReturn
 mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
@@ -1237,78 +1232,134 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
     int index = 0;
     Addr start = p->getSyscallArg(tc, index);
     uint64_t length = p->getSyscallArg(tc, index);
-    index++; // int prot = p->getSyscallArg(tc, index);
-    int flags = p->getSyscallArg(tc, index);
+    int prot = p->getSyscallArg(tc, index);
+    int tgt_flags = p->getSyscallArg(tc, index);
     int tgt_fd = p->getSyscallArg(tc, index);
     int offset = p->getSyscallArg(tc, index);
 
-    if (length > 0x100000000ULL)
-        warn("mmap length argument %#x is unreasonably large.\n", length);
-
-    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
-        FDEntry *fde = p->getFDEntry(tgt_fd);
-        if (!fde || fde->fd < 0) {
-            warn("mmap failing: target fd %d is not valid\n", tgt_fd);
-            return -EBADF;
-        }
+    DPRINTF_SYSCALL(Verbose, "mmap(0x%x, len %d, prot %d, flags %d, fd %d, "
+                    "offs %d)\n", start, length, prot, tgt_flags, tgt_fd,
+                    offset);
+
+    if (start & (TheISA::PageBytes - 1) ||
+        offset & (TheISA::PageBytes - 1) ||
+        (tgt_flags & OS::TGT_MAP_PRIVATE &&
+         tgt_flags & OS::TGT_MAP_SHARED) ||
+        (!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
+         !(tgt_flags & OS::TGT_MAP_SHARED)) ||
+        !length) {
+        return -EINVAL;
+    }
 
-        if (fde->filename != "/dev/zero") {
-            // This is very likely broken, but leave a warning here
-            // (rather than panic) in case /dev/zero is known by
-            // another name on some platform
-            warn("allowing mmap of file %s; mmap not supported on files"
-                 " other than /dev/zero\n", fde->filename);
-        }
+    if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
+        // With shared mmaps, there are two cases to consider:
+        // 1) anonymous: writes should modify the mapping and this should be
+        // visible to observers who share the mapping. Currently, it's
+        // difficult to update the shared mapping because there's no
+        // structure which maintains information about the which virtual
+        // memory areas are shared. If that structure existed, it would be
+        // possible to make the translations point to the same frames.
+        // 2) file-backed: writes should modify the mapping and the file
+        // which is backed by the mapping. The shared mapping problem is the
+        // same as what was mentioned about the anonymous mappings. For
+        // file-backed mappings, the writes to the file are difficult
+        // because it requires syncing what the mapping holds with the file
+        // that resides on the host system. So, any write on a real system
+        // would cause the change to be propagated to the file mapping at
+        // some point in the future (the inode is tracked along with the
+        // mapping). This isn't guaranteed to always happen, but it usually
+        // works well enough. The guarantee is provided by the msync system
+        // call. We could force the change through with shared mappings with
+        // a call to msync, but that again would require more information
+        // than we currently maintain.
+        warn("mmap: writing to shared mmap region is currently "
+             "unsupported. The write succeeds on the target, but it "
+             "will not be propagated to the host or shared mappings");
     }
 
     length = roundUp(length, TheISA::PageBytes);
 
-    if ((start  % TheISA::PageBytes) != 0 ||
-        (offset % TheISA::PageBytes) != 0) {
-        warn("mmap failing: arguments not page-aligned: "
-             "start 0x%x offset 0x%x",
-             start, offset);
-        return -EINVAL;
-    }
+    int sim_fd = -1;
+    uint8_t *pmap = nullptr;
+    if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
+        sim_fd = p->getSimFD(tgt_fd);
+        if (sim_fd < 0)
+            return -EBADF;
 
-    // are we ok with clobbering existing mappings?  only set this to
-    // true if the user has been warned.
-    bool clobber = false;
-
-    // try to use the caller-provided address if there is one
-    bool use_provided_address = (start != 0);
-
-    if (use_provided_address) {
-        // check to see if the desired address is already in use
-        if (!p->pTable->isUnmapped(start, length)) {
-            // there are existing mappings in the desired range
-            // whether we clobber them or not depends on whether the caller
-            // specified MAP_FIXED
-            if (flags & OS::TGT_MAP_FIXED) {
-                // MAP_FIXED specified: map attempt fails
-                return -EINVAL;
-            } else {
-                // MAP_FIXED not specified: ignore suggested start address
-                warn("mmap: ignoring suggested map address 0x%x\n", start);
-                use_provided_address = false;
-            }
+        pmap = (decltype(pmap))mmap(NULL, length, PROT_READ, MAP_PRIVATE,
+                                    sim_fd, offset);
+
+        if (pmap == (decltype(pmap))-1) {
+            warn("mmap: failed to map file into host address space");
+            return -errno;
         }
     }
 
-    if (!use_provided_address) {
-        // no address provided, or provided address unusable:
-        // pick next address from our "mmap region"
-        if (OS::mmapGrowsDown()) {
-            start = p->mmap_end - length;
-            p->mmap_end = start;
-        } else {
-            start = p->mmap_end;
-            p->mmap_end += length;
+    // Extend global mmap region if necessary. Note that we ignore the
+    // start address unless MAP_FIXED is specified.
+    if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
+        start = (OS::mmapGrowsDown()) ? p->mmap_end - length : p->mmap_end;
+        p->mmap_end = (OS::mmapGrowsDown()) ? start : p->mmap_end + length;
+    }
+
+    DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
+                    start, start + length - 1);
+
+    // We only allow mappings to overwrite existing mappings if
+    // TGT_MAP_FIXED is set. Otherwise it shouldn't be a problem
+    // because we ignore the start hint if TGT_MAP_FIXED is not set.
+    int clobber = tgt_flags & OS::TGT_MAP_FIXED;
+    if (clobber) {
+        for (auto tc : p->system->threadContexts) {
+            // If we might be overwriting old mappings, we need to
+            // invalidate potentially stale mappings out of the TLBs.
+            tc->getDTBPtr()->flushAll();
+            tc->getITBPtr()->flushAll();
         }
     }
 
+    // Allocate physical memory and map it in. If the page table is already
+    // mapped and clobber is not set, the simulator will issue throw a
+    // fatal and bail out of the simulation.
     p->allocateMem(start, length, clobber);
 
+    // Transfer content into target address space.
+    SETranslatingPortProxy &tp = tc->getMemProxy();
+    if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
+        // In general, we should zero the mapped area for anonymous mappings,
+        // with something like:
+        //     tp.memsetBlob(start, 0, length);
+        // However, given that we don't support sparse mappings, and
+        // some applications can map a couple of gigabytes of space
+        // (intending sparse usage), that can get painfully expensive.
+        // Fortunately, since we don't properly implement munmap either,
+        // there's no danger of remapping used memory, so for now all
+        // newly mapped memory should already be zeroed so we can skip it.
+    } else {
+        // It is possible to mmap an area larger than a file, however
+        // accessing unmapped portions the system triggers a "Bus error"
+        // on the host. We must know when to stop copying the file from
+        // the host into the target address space.
+        struct stat file_stat;
+        if (fstat(sim_fd, &file_stat) > 0)
+            fatal("mmap: cannot stat file");
+
+        // Copy the portion of the file that is resident. This requires
+        // checking both the mmap size and the filesize that we are
+        // trying to mmap into this space; the mmap size also depends
+        // on the specified offset into the file.
+        uint64_t size = std::min((uint64_t)file_stat.st_size - offset,
+                                 length);
+        tp.writeBlob(start, pmap, size);
+
+        // Cleanup the mmap region before exiting this function.
+        munmap(pmap, length);
+
+        // Note that we do not zero out the remainder of the mapping. This
+        // is done by a real system, but it probably will not affect
+        // execution (hopefully).
+    }
+
     return start;
 }