diff options
author | Brandon Potter <brandon.potter@amd.com> | 2016-03-17 10:24:17 -0700 |
---|---|---|
committer | Brandon Potter <brandon.potter@amd.com> | 2016-03-17 10:24:17 -0700 |
commit | a04fac976f02377237bb827d46854b669ebc2397 (patch) | |
tree | 2f2a5e55e16b2c05e4d94e302081bb977e864a36 /src | |
parent | 3fa311e5acd58ce720014dd964728c2fa414ca6a (diff) | |
download | gem5-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/alpha/linux/linux.cc | 30 | ||||
-rw-r--r-- | src/arch/alpha/linux/linux.hh | 21 | ||||
-rw-r--r-- | src/arch/alpha/tru64/tru64.cc | 22 | ||||
-rw-r--r-- | src/arch/alpha/tru64/tru64.hh | 24 | ||||
-rw-r--r-- | src/arch/arm/freebsd/freebsd.hh | 4 | ||||
-rw-r--r-- | src/arch/arm/linux/linux.cc | 55 | ||||
-rw-r--r-- | src/arch/arm/linux/linux.hh | 42 | ||||
-rw-r--r-- | src/arch/mips/linux/linux.cc | 31 | ||||
-rw-r--r-- | src/arch/mips/linux/linux.hh | 21 | ||||
-rw-r--r-- | src/arch/power/linux/linux.cc | 30 | ||||
-rw-r--r-- | src/arch/power/linux/linux.hh | 21 | ||||
-rw-r--r-- | src/arch/sparc/linux/linux.cc | 34 | ||||
-rw-r--r-- | src/arch/sparc/linux/linux.hh | 23 | ||||
-rw-r--r-- | src/arch/sparc/solaris/solaris.cc | 29 | ||||
-rw-r--r-- | src/arch/sparc/solaris/solaris.hh | 23 | ||||
-rw-r--r-- | src/arch/x86/linux/linux.cc | 60 | ||||
-rw-r--r-- | src/arch/x86/linux/linux.hh | 47 | ||||
-rw-r--r-- | src/sim/syscall_emul.cc | 4 | ||||
-rw-r--r-- | 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 <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; } |