From a04fac976f02377237bb827d46854b669ebc2397 Mon Sep 17 00:00:00 2001 From: Brandon Potter Date: Thu, 17 Mar 2016 10:24:17 -0700 Subject: 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. --- src/arch/alpha/linux/linux.cc | 30 ++++++- src/arch/alpha/linux/linux.hh | 21 ++++- src/arch/alpha/tru64/tru64.cc | 22 +++++ src/arch/alpha/tru64/tru64.hh | 24 +++++- src/arch/arm/freebsd/freebsd.hh | 4 + src/arch/arm/linux/linux.cc | 55 +++++++++++- src/arch/arm/linux/linux.hh | 42 ++++++++- src/arch/mips/linux/linux.cc | 31 ++++++- src/arch/mips/linux/linux.hh | 21 ++++- src/arch/power/linux/linux.cc | 30 ++++++- src/arch/power/linux/linux.hh | 21 ++++- src/arch/sparc/linux/linux.cc | 34 +++++++- src/arch/sparc/linux/linux.hh | 23 ++++- src/arch/sparc/solaris/solaris.cc | 29 ++++++- src/arch/sparc/solaris/solaris.hh | 23 ++++- src/arch/x86/linux/linux.cc | 60 ++++++++++++- src/arch/x86/linux/linux.hh | 47 +++++++++-- src/sim/syscall_emul.cc | 4 +- src/sim/syscall_emul.hh | 173 ++++++++++++++++++++++++-------------- 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 - #include "arch/alpha/linux/linux.hh" +#include +#include + // 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 - #include "arch/arm/linux/linux.hh" +#include +#include + // 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 - #include "arch/mips/linux/linux.hh" +#include +#include + // 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 - #include "arch/power/linux/linux.hh" +#include +#include + // 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 - #include "arch/sparc/linux/linux.hh" +#include +#include + // 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 - #include "arch/sparc/solaris/solaris.hh" +#include +#include + // 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 - #include "arch/x86/linux/linux.hh" +#include +#include + // 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 // for O_BINARY #endif +#include #include #include #include @@ -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 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; } -- cgit v1.2.3