syscall emul: fix Power Linux mmap constant, plus other cleanup
authorSteve Reinhardt <steve.reinhardt@amd.com>
Mon, 23 May 2011 21:29:23 +0000 (14:29 -0700)
committerSteve Reinhardt <steve.reinhardt@amd.com>
Mon, 23 May 2011 21:29:23 +0000 (14:29 -0700)
We were getting a spurious warning in the regressions that turned
out to be due to having the wrong value for TGT_MAP_ANONYMOUS for
Power Linux, but in the process of tracking it down I ended up
doing some cleanup of the mmap handling in general.

src/arch/power/linux/linux.hh
src/sim/process.cc
src/sim/syscall_emul.hh

index c681c8baf6ed5762d12db82b51f898abc29ede76..1bfc9cbd8be1bc3c251df1c900e9a6957d9b83b5 100644 (file)
@@ -126,7 +126,7 @@ class PowerLinux : public Linux
     //@}
 
     /// For mmap().
-    static const unsigned TGT_MAP_ANONYMOUS = 0x800;
+    static const unsigned TGT_MAP_ANONYMOUS = 0x20;
 
     //@{
     /// ioctl() command codes.
index 9a9527664ac7eab323ef345728d17359731e1ece..28142d7317a107d9e13885793cb146703f7f6c65 100644 (file)
@@ -313,7 +313,7 @@ Process::free_fd(int tgt_fd)
 int
 Process::sim_fd(int tgt_fd)
 {
-    if (tgt_fd > MAX_FD)
+    if (tgt_fd < 0 || tgt_fd > MAX_FD)
         return -1;
 
     return fd_map[tgt_fd].fd;
@@ -322,8 +322,8 @@ Process::sim_fd(int tgt_fd)
 Process::FdMap *
 Process::sim_fd_obj(int tgt_fd)
 {
-    if (tgt_fd > MAX_FD)
-        panic("sim_fd_obj called in fd out of range.");
+    if (tgt_fd < 0 || tgt_fd > MAX_FD)
+        return NULL;
 
     return &fd_map[tgt_fd];
 }
index e685a0f30d23351213ba8ac3e6f5b90c17f626db..d119adc247e1522a7249012ebdc65fa5c6f2356f 100644 (file)
@@ -989,13 +989,8 @@ writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 /// 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).  Always print a warning,
-/// since this could be seriously broken if we're not mapping
-/// /dev/zero.
-//
-/// Someday we should explicitly check for /dev/zero in open, flag the
-/// file descriptor, and fail (or implement!) a non-anonymous mmap to
-/// anything else.
+/// doesn't really check addresses anyway).
+///
 template <class OS>
 SyscallReturn
 mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
@@ -1005,9 +1000,24 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
     uint64_t length = p->getSyscallArg(tc, index);
     index++; // int prot = p->getSyscallArg(tc, index);
     int flags = p->getSyscallArg(tc, index);
-    int fd = p->sim_fd(p->getSyscallArg(tc, index));
+    int tgt_fd = p->getSyscallArg(tc, index);
     // int offset = p->getSyscallArg(tc, index);
 
+    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
+        Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd);
+        if (!fd_map || fd_map->fd < 0) {
+            warn("mmap failing: target fd %d is not valid\n", tgt_fd);
+            return -EBADF;
+        }
+
+        if (fd_map->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", fd_map->filename);
+        }
+    }
 
     if ((start  % TheISA::VMPageSize) != 0 ||
         (length % TheISA::VMPageSize) != 0) {
@@ -1032,11 +1042,6 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
     }
     p->pTable->allocate(start, length);
 
-    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
-        warn("allowing mmap of file @ fd %d. "
-             "This will break if not /dev/zero.", fd);
-    }
-
     return start;
 }