summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Potter <brandon.potter@amd.com>2016-03-17 10:24:17 -0700
committerBrandon Potter <brandon.potter@amd.com>2016-03-17 10:24:17 -0700
commita04fac976f02377237bb827d46854b669ebc2397 (patch)
tree2f2a5e55e16b2c05e4d94e302081bb977e864a36
parent3fa311e5acd58ce720014dd964728c2fa414ca6a (diff)
downloadgem5-a04fac976f02377237bb827d46854b669ebc2397.tar.xz
syscall_emul: extend mmap system call to support file backed mmaps
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.
-rw-r--r--src/arch/alpha/linux/linux.cc30
-rw-r--r--src/arch/alpha/linux/linux.hh21
-rw-r--r--src/arch/alpha/tru64/tru64.cc22
-rw-r--r--src/arch/alpha/tru64/tru64.hh24
-rw-r--r--src/arch/arm/freebsd/freebsd.hh4
-rw-r--r--src/arch/arm/linux/linux.cc55
-rw-r--r--src/arch/arm/linux/linux.hh42
-rw-r--r--src/arch/mips/linux/linux.cc31
-rw-r--r--src/arch/mips/linux/linux.hh21
-rw-r--r--src/arch/power/linux/linux.cc30
-rw-r--r--src/arch/power/linux/linux.hh21
-rw-r--r--src/arch/sparc/linux/linux.cc34
-rw-r--r--src/arch/sparc/linux/linux.hh23
-rw-r--r--src/arch/sparc/solaris/solaris.cc29
-rw-r--r--src/arch/sparc/solaris/solaris.hh23
-rw-r--r--src/arch/x86/linux/linux.cc60
-rw-r--r--src/arch/x86/linux/linux.hh47
-rw-r--r--src/sim/syscall_emul.cc4
-rw-r--r--src/sim/syscall_emul.hh173
19 files changed, 597 insertions, 97 deletions
diff --git a/src/arch/alpha/linux/linux.cc b/src/arch/alpha/linux/linux.cc
index b86b92c2e..7b747f127 100644
--- a/src/arch/alpha/linux/linux.cc
+++ b/src/arch/alpha/linux/linux.cc
@@ -28,10 +28,11 @@
* 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]);
diff --git a/src/arch/alpha/linux/linux.hh b/src/arch/alpha/linux/linux.hh
index 7864c6414..409ad4dd1 100644
--- a/src/arch/alpha/linux/linux.hh
+++ b/src/arch/alpha/linux/linux.hh
@@ -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().
diff --git a/src/arch/alpha/tru64/tru64.cc b/src/arch/alpha/tru64/tru64.cc
index 1854a02f1..1fd589f66 100644
--- a/src/arch/alpha/tru64/tru64.cc
+++ b/src/arch/alpha/tru64/tru64.cc
@@ -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]);
diff --git a/src/arch/alpha/tru64/tru64.hh b/src/arch/alpha/tru64/tru64.hh
index 92d6db842..e8ac3c7e8 100644
--- a/src/arch/alpha/tru64/tru64.hh
+++ b/src/arch/alpha/tru64/tru64.hh
@@ -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().
diff --git a/src/arch/arm/freebsd/freebsd.hh b/src/arch/arm/freebsd/freebsd.hh
index 7e85659ec..e2c5e493c 100644
--- a/src/arch/arm/freebsd/freebsd.hh
+++ b/src/arch/arm/freebsd/freebsd.hh
@@ -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;
diff --git a/src/arch/arm/linux/linux.cc b/src/arch/arm/linux/linux.cc
index ac114048a..3dde8c217 100644
--- a/src/arch/arm/linux/linux.cc
+++ b/src/arch/arm/linux/linux.cc
@@ -41,10 +41,11 @@
* 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]);
+
diff --git a/src/arch/arm/linux/linux.hh b/src/arch/arm/linux/linux.hh
index a2eaea52c..5c814cde1 100644
--- a/src/arch/arm/linux/linux.hh
+++ b/src/arch/arm/linux/linux.hh
@@ -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().
diff --git a/src/arch/mips/linux/linux.cc b/src/arch/mips/linux/linux.cc
index 4861f7cb9..2f0ca6090 100644
--- a/src/arch/mips/linux/linux.cc
+++ b/src/arch/mips/linux/linux.cc
@@ -28,10 +28,11 @@
* 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]);
+
diff --git a/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh
index 6e4b6a82d..f4b18397e 100644
--- a/src/arch/mips/linux/linux.hh
+++ b/src/arch/mips/linux/linux.hh
@@ -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().
diff --git a/src/arch/power/linux/linux.cc b/src/arch/power/linux/linux.cc
index f73dd063b..6382ca72a 100644
--- a/src/arch/power/linux/linux.cc
+++ b/src/arch/power/linux/linux.cc
@@ -29,10 +29,11 @@
* 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]);
+
diff --git a/src/arch/power/linux/linux.hh b/src/arch/power/linux/linux.hh
index 656f4402e..55634800e 100644
--- a/src/arch/power/linux/linux.hh
+++ b/src/arch/power/linux/linux.hh
@@ -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.
diff --git a/src/arch/sparc/linux/linux.cc b/src/arch/sparc/linux/linux.cc
index 2f91cf81d..dbc7e9691 100644
--- a/src/arch/sparc/linux/linux.cc
+++ b/src/arch/sparc/linux/linux.cc
@@ -28,10 +28,11 @@
* 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]);
+
diff --git a/src/arch/sparc/linux/linux.hh b/src/arch/sparc/linux/linux.hh
index 138f178b7..d0631f82b 100644
--- a/src/arch/sparc/linux/linux.hh
+++ b/src/arch/sparc/linux/linux.hh
@@ -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 */
diff --git a/src/arch/sparc/solaris/solaris.cc b/src/arch/sparc/solaris/solaris.cc
index e17de3af0..afedcfe88 100644
--- a/src/arch/sparc/solaris/solaris.cc
+++ b/src/arch/sparc/solaris/solaris.cc
@@ -28,10 +28,11 @@
* 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]);
+
diff --git a/src/arch/sparc/solaris/solaris.hh b/src/arch/sparc/solaris/solaris.hh
index 9827b6b50..1e814bc53 100644
--- a/src/arch/sparc/solaris/solaris.hh
+++ b/src/arch/sparc/solaris/solaris.hh
@@ -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
diff --git a/src/arch/x86/linux/linux.cc b/src/arch/x86/linux/linux.cc
index 2eab555ce..f51bb16e7 100644
--- a/src/arch/x86/linux/linux.cc
+++ b/src/arch/x86/linux/linux.cc
@@ -37,10 +37,11 @@
* 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]);
diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh
index 854ab00a0..ce395f17d 100644
--- a/src/arch/x86/linux/linux.hh
+++ b/src/arch/x86/linux/linux.hh
@@ -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 */
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index 517580d79..392658c5a 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -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;
}
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 080dcb011..34fbc6618 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -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;
}