cpu: Fix retry bug in MinorCPU LSQ
[gem5.git] / src / sim / syscall_emul.hh
index 21f8201c8d5f0231aeaa0f3d500fe5012079803e..cc430b9492b1c881219f613077887e5bed856594 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012-2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2003-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -33,7 +45,8 @@
 #define __SIM_SYSCALL_EMUL_HH__
 
 #define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \
-                   defined(__FreeBSD__) || defined(__CYGWIN__))
+  defined(__FreeBSD__) || defined(__CYGWIN__) || \
+  defined(__NetBSD__))
 
 ///
 /// @file syscall_emul.hh
 /// This file defines objects used to emulate syscalls from the target
 /// application on the host machine.
 
-#include <errno.h>
-#include <string>
 #ifdef __CYGWIN32__
 #include <sys/fcntl.h>  // for O_BINARY
 #endif
 #include <sys/stat.h>
-#include <fcntl.h>
+#include <sys/time.h>
 #include <sys/uio.h>
+#include <fcntl.h>
+
+#include <cerrno>
+#include <string>
 
 #include "base/chunk_generator.hh"
 #include "base/intmath.hh"      // for RoundUp
 #include "config/the_isa.hh"
 #include "cpu/base.hh"
 #include "cpu/thread_context.hh"
-#include "mem/translating_port.hh"
+#include "debug/SyscallVerbose.hh"
 #include "mem/page_table.hh"
-#include "sim/system.hh"
+#include "sim/byteswap.hh"
+#include "sim/emul_driver.hh"
 #include "sim/process.hh"
+#include "sim/syscall_emul_buf.hh"
+#include "sim/syscallreturn.hh"
+#include "sim/system.hh"
 
 ///
 /// System call descriptor.
@@ -98,73 +117,6 @@ class SyscallDesc {
 };
 
 
-class BaseBufferArg {
-
-  public:
-
-    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
-    {
-        bufPtr = new uint8_t[size];
-        // clear out buffer: in case we only partially populate this,
-        // and then do a copyOut(), we want to make sure we don't
-        // introduce any random junk into the simulated address space
-        memset(bufPtr, 0, size);
-    }
-
-    virtual ~BaseBufferArg() { delete [] bufPtr; }
-
-    //
-    // copy data into simulator space (read from target memory)
-    //
-    virtual bool copyIn(TranslatingPort *memport)
-    {
-        memport->readBlob(addr, bufPtr, size);
-        return true;    // no EFAULT detection for now
-    }
-
-    //
-    // copy data out of simulator space (write to target memory)
-    //
-    virtual bool copyOut(TranslatingPort *memport)
-    {
-        memport->writeBlob(addr, bufPtr, size);
-        return true;    // no EFAULT detection for now
-    }
-
-  protected:
-    Addr addr;
-    int size;
-    uint8_t *bufPtr;
-};
-
-
-class BufferArg : public BaseBufferArg
-{
-  public:
-    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
-    void *bufferPtr()   { return bufPtr; }
-};
-
-template <class T>
-class TypedBufferArg : public BaseBufferArg
-{
-  public:
-    // user can optionally specify a specific number of bytes to
-    // allocate to deal with those structs that have variable-size
-    // arrays at the end
-    TypedBufferArg(Addr _addr, int _size = sizeof(T))
-        : BaseBufferArg(_addr, _size)
-    { }
-
-    // type case
-    operator T*() { return (T *)bufPtr; }
-
-    // dereference operators
-    T &operator*()       { return *((T *)bufPtr); }
-    T* operator->()      { return (T *)bufPtr; }
-    T &operator[](int i) { return ((T *)bufPtr)[i]; }
-};
-
 //////////////////////////////////////////////////////////////////////
 //
 // The following emulation functions are generic enough that they
@@ -184,6 +136,8 @@ SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
 /// trace flag is enabled.  Return success to the target program.
 SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
                          LiveProcess *p, ThreadContext *tc);
+SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num,
+                         LiveProcess *p, ThreadContext *tc);
 
 /// Target exit() handler: terminate current context.
 SyscallReturn exitFunc(SyscallDesc *desc, int num,
@@ -233,11 +187,17 @@ SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
 SyscallReturn getcwdFunc(SyscallDesc *desc, int num,
                          LiveProcess *p, ThreadContext *tc);
 
-/// Target unlink() handler.
+/// Target readlink() handler.
+SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
+                           LiveProcess *p, ThreadContext *tc,
+                           int index = 0);
 SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
                            LiveProcess *p, ThreadContext *tc);
 
 /// Target unlink() handler.
+SyscallReturn unlinkHelper(SyscallDesc *desc, int num,
+                           LiveProcess *p, ThreadContext *tc,
+                           int index);
 SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
                          LiveProcess *p, ThreadContext *tc);
 
@@ -260,6 +220,10 @@ SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
                             LiveProcess *p, ThreadContext *tc);
 
 
+/// Target truncate64() handler.
+SyscallReturn truncate64Func(SyscallDesc *desc, int num,
+                             LiveProcess *p, ThreadContext *tc);
+
 /// Target ftruncate64() handler.
 SyscallReturn ftruncate64Func(SyscallDesc *desc, int num,
                               LiveProcess *p, ThreadContext *tc);
@@ -323,6 +287,95 @@ SyscallReturn getegidFunc(SyscallDesc *desc, int num,
 SyscallReturn cloneFunc(SyscallDesc *desc, int num,
                                LiveProcess *p, ThreadContext *tc);
 
+/// Target access() handler
+SyscallReturn accessFunc(SyscallDesc *desc, int num,
+                               LiveProcess *p, ThreadContext *tc);
+SyscallReturn accessFunc(SyscallDesc *desc, int num,
+                               LiveProcess *p, ThreadContext *tc,
+                               int index);
+
+/// Futex system call
+///  Implemented by Daniel Sanchez
+///  Used by printf's in multi-threaded apps
+template <class OS>
+SyscallReturn
+futexFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+          ThreadContext *tc)
+{
+    int index_uaddr = 0;
+    int index_op = 1;
+    int index_val = 2;
+    int index_timeout = 3;
+
+    uint64_t uaddr = process->getSyscallArg(tc, index_uaddr);
+    int op = process->getSyscallArg(tc, index_op);
+    int val = process->getSyscallArg(tc, index_val);
+    uint64_t timeout = process->getSyscallArg(tc, index_timeout);
+
+    std::map<uint64_t, std::list<ThreadContext *> * >
+        &futex_map = tc->getSystemPtr()->futexMap;
+
+    DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n",
+            uaddr, op, val);
+
+    op &= ~OS::TGT_FUTEX_PRIVATE_FLAG;
+
+    if (op == OS::TGT_FUTEX_WAIT) {
+        if (timeout != 0) {
+            warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;"
+                 "we'll wait indefinitely");
+        }
+
+        uint8_t *buf = new uint8_t[sizeof(int)];
+        tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int));
+        int mem_val = *((int *)buf);
+        delete buf;
+
+        if(val != mem_val) {
+            DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, "
+                                    "expected: %d\n", mem_val, val);
+            return -OS::TGT_EWOULDBLOCK;
+        }
+
+        // Queue the thread context
+        std::list<ThreadContext *> * tcWaitList;
+        if (futex_map.count(uaddr)) {
+            tcWaitList = futex_map.find(uaddr)->second;
+        } else {
+            tcWaitList = new std::list<ThreadContext *>();
+            futex_map.insert(std::pair< uint64_t,
+                            std::list<ThreadContext *> * >(uaddr, tcWaitList));
+        }
+        tcWaitList->push_back(tc);
+        DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling "
+                                "thread context\n");
+        tc->suspend();
+        return 0;
+    } else if (op == OS::TGT_FUTEX_WAKE){
+        int wokenUp = 0;
+        std::list<ThreadContext *> * tcWaitList;
+        if (futex_map.count(uaddr)) {
+            tcWaitList = futex_map.find(uaddr)->second;
+            while (tcWaitList->size() > 0 && wokenUp < val) {
+                tcWaitList->front()->activate();
+                tcWaitList->pop_front();
+                wokenUp++;
+            }
+            if(tcWaitList->empty()) {
+                futex_map.erase(uaddr);
+                delete tcWaitList;
+            }
+        }
+        DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting "
+                                "thread contexts\n", wokenUp);
+        return wokenUp;
+    } else {
+        warn("sys_futex: op %d is not implemented, just returning...", op);
+        return 0;
+    }
+
+}
+
 
 /// Pseudo Funcs  - These functions use a different return convension,
 /// returning a second value in a register other than the normal return register
@@ -356,7 +409,7 @@ template <class T1, class T2>
 void
 getElapsedTime(T1 &sec, T2 &usec)
 {
-    int elapsed_usecs = curTick / Clock::Int::us;
+    int elapsed_usecs = curTick() / SimClock::Int::us;
     sec = elapsed_usecs / one_million;
     usec = elapsed_usecs % one_million;
 }
@@ -390,41 +443,41 @@ convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
         tgt->st_dev = 0xA;
     else
         tgt->st_dev = host->st_dev;
-    tgt->st_dev = htog(tgt->st_dev);
+    tgt->st_dev = TheISA::htog(tgt->st_dev);
     tgt->st_ino = host->st_ino;
-    tgt->st_ino = htog(tgt->st_ino);
+    tgt->st_ino = TheISA::htog(tgt->st_ino);
     tgt->st_mode = host->st_mode;
     if (fakeTTY) {
         // Claim to be a character device
         tgt->st_mode &= ~S_IFMT;    // Clear S_IFMT
         tgt->st_mode |= S_IFCHR;    // Set S_IFCHR
     }
-    tgt->st_mode = htog(tgt->st_mode);
+    tgt->st_mode = TheISA::htog(tgt->st_mode);
     tgt->st_nlink = host->st_nlink;
-    tgt->st_nlink = htog(tgt->st_nlink);
+    tgt->st_nlink = TheISA::htog(tgt->st_nlink);
     tgt->st_uid = host->st_uid;
-    tgt->st_uid = htog(tgt->st_uid);
+    tgt->st_uid = TheISA::htog(tgt->st_uid);
     tgt->st_gid = host->st_gid;
-    tgt->st_gid = htog(tgt->st_gid);
+    tgt->st_gid = TheISA::htog(tgt->st_gid);
     if (fakeTTY)
         tgt->st_rdev = 0x880d;
     else
         tgt->st_rdev = host->st_rdev;
-    tgt->st_rdev = htog(tgt->st_rdev);
+    tgt->st_rdev = TheISA::htog(tgt->st_rdev);
     tgt->st_size = host->st_size;
-    tgt->st_size = htog(tgt->st_size);
+    tgt->st_size = TheISA::htog(tgt->st_size);
     tgt->st_atimeX = host->st_atime;
-    tgt->st_atimeX = htog(tgt->st_atimeX);
+    tgt->st_atimeX = TheISA::htog(tgt->st_atimeX);
     tgt->st_mtimeX = host->st_mtime;
-    tgt->st_mtimeX = htog(tgt->st_mtimeX);
+    tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX);
     tgt->st_ctimeX = host->st_ctime;
-    tgt->st_ctimeX = htog(tgt->st_ctimeX);
+    tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX);
     // Force the block size to be 8k. This helps to ensure buffered io works
     // consistently across different hosts.
     tgt->st_blksize = 0x2000;
-    tgt->st_blksize = htog(tgt->st_blksize);
+    tgt->st_blksize = TheISA::htog(tgt->st_blksize);
     tgt->st_blocks = host->st_blocks;
-    tgt->st_blocks = htog(tgt->st_blocks);
+    tgt->st_blocks = TheISA::htog(tgt->st_blocks);
 }
 
 // Same for stat64
@@ -438,11 +491,11 @@ convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
     convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
 #if defined(STAT_HAVE_NSEC)
     tgt->st_atime_nsec = host->st_atime_nsec;
-    tgt->st_atime_nsec = htog(tgt->st_atime_nsec);
+    tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec);
     tgt->st_mtime_nsec = host->st_mtime_nsec;
-    tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec);
+    tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec);
     tgt->st_ctime_nsec = host->st_ctime_nsec;
-    tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec);
+    tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec);
 #else
     tgt->st_atime_nsec = 0;
     tgt->st_mtime_nsec = 0;
@@ -453,7 +506,7 @@ convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
 //Here are a couple convenience functions
 template<class OS>
 static void
-copyOutStatBuf(TranslatingPort * mem, Addr addr,
+copyOutStatBuf(SETranslatingPortProxy &mem, Addr addr,
         hst_stat *host, bool fakeTTY = false)
 {
     typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
@@ -464,7 +517,7 @@ copyOutStatBuf(TranslatingPort * mem, Addr addr,
 
 template<class OS>
 static void
-copyOutStat64Buf(TranslatingPort * mem, Addr addr,
+copyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr,
         hst_stat64 *host, bool fakeTTY = false)
 {
     typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
@@ -475,59 +528,52 @@ copyOutStat64Buf(TranslatingPort * mem, Addr addr,
 
 /// Target ioctl() handler.  For the most part, programs call ioctl()
 /// only to find out if their stdout is a tty, to determine whether to
-/// do line or block buffering.
+/// do line or block buffering.  We always claim that output fds are
+/// not TTYs to provide repeatable results.
 template <class OS>
 SyscallReturn
 ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
           ThreadContext *tc)
 {
-    int fd = process->getSyscallArg(tc, 0);
-    unsigned req = process->getSyscallArg(tc, 1);
+    int index = 0;
+    int fd = process->getSyscallArg(tc, index);
+    unsigned req = process->getSyscallArg(tc, index);
 
     DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
 
-    if (fd < 0 || process->sim_fd(fd) < 0) {
+    Process::FdMap *fdObj = process->sim_fd_obj(fd);
+
+    if (fdObj == NULL) {
         // doesn't map to any simulator fd: not a valid target fd
         return -EBADF;
     }
 
-    switch (req) {
-      case OS::TIOCISATTY_:
-      case OS::TIOCGETP_:
-      case OS::TIOCSETP_:
-      case OS::TIOCSETN_:
-      case OS::TIOCSETC_:
-      case OS::TIOCGETC_:
-      case OS::TIOCGETS_:
-      case OS::TIOCGETA_:
-        return -ENOTTY;
+    if (fdObj->driver != NULL) {
+        return fdObj->driver->ioctl(process, tc, req);
+    }
 
-      default:
-        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
-              fd, req, tc->readPC());
+    if (OS::isTtyReq(req)) {
+        return -ENOTTY;
     }
+
+    warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
+         fd, req, tc->pcState());
+    return -ENOTTY;
 }
 
-/// Target open() handler.
 template <class OS>
-SyscallReturn
+static SyscallReturn
 openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
-         ThreadContext *tc)
+         ThreadContext *tc, int index)
 {
     std::string path;
 
-    if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index)))
         return -EFAULT;
 
-    if (path == "/dev/sysdev0") {
-        // This is a memory-mapped high-resolution timer device on Alpha.
-        // We don't support it, so just punt.
-        warn("Ignoring open(%s, ...)\n", path);
-        return -ENOENT;
-    }
-
-    int tgtFlags = process->getSyscallArg(tc, 1);
-    int mode = process->getSyscallArg(tc, 2);
+    int tgtFlags = process->getSyscallArg(tc, index);
+    int mode = process->getSyscallArg(tc, index);
     int hostFlags = 0;
 
     // translate open flags
@@ -551,18 +597,105 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 
     DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
 
+    if (startswith(path, "/dev/")) {
+        std::string filename = path.substr(strlen("/dev/"));
+        if (filename == "sysdev0") {
+            // This is a memory-mapped high-resolution timer device on Alpha.
+            // We don't support it, so just punt.
+            warn("Ignoring open(%s, ...)\n", path);
+            return -ENOENT;
+        }
+
+        EmulatedDriver *drv = process->findDriver(filename);
+        if (drv != NULL) {
+            // the driver's open method will allocate a fd from the
+            // process if necessary.
+            return drv->open(process, tc, mode, hostFlags);
+        }
+
+        // fall through here for pass through to host devices, such as
+        // /dev/zero
+    }
+
     int fd;
-    if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") ||
-        !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) {
-        // It's a proc/sys entery and requires special handling
+    int local_errno;
+    if (startswith(path, "/proc/") || startswith(path, "/system/") ||
+        startswith(path, "/platform/") || startswith(path, "/sys/")) {
+        // It's a proc/sys entry and requires special handling
         fd = OS::openSpecialFile(path, process, tc);
-        return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
+        local_errno = ENOENT;
      } else {
         // open the file
         fd = open(path.c_str(), hostFlags, mode);
-        return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
+        local_errno = errno;
      }
 
+    if (fd == -1)
+        return -local_errno;
+
+    return process->alloc_fd(fd, path.c_str(), hostFlags, mode, false);
+}
+
+/// Target open() handler.
+template <class OS>
+SyscallReturn
+openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+         ThreadContext *tc)
+{
+    return openFunc<OS>(desc, callnum, process, tc, 0);
+}
+
+/// Target openat() handler.
+template <class OS>
+SyscallReturn
+openatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+         ThreadContext *tc)
+{
+    int index = 0;
+    int dirfd = process->getSyscallArg(tc, index);
+    if (dirfd != OS::TGT_AT_FDCWD)
+        warn("openat: first argument not AT_FDCWD; unlikely to work");
+    return openFunc<OS>(desc, callnum, process, tc, 1);
+}
+
+/// Target unlinkat() handler.
+template <class OS>
+SyscallReturn
+unlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+             ThreadContext *tc)
+{
+    int index = 0;
+    int dirfd = process->getSyscallArg(tc, index);
+    if (dirfd != OS::TGT_AT_FDCWD)
+        warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
+
+    return unlinkHelper(desc, callnum, process, tc, 1);
+}
+
+/// Target facessat() handler
+template <class OS>
+SyscallReturn
+faccessatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+        ThreadContext *tc)
+{
+    int index = 0;
+    int dirfd = process->getSyscallArg(tc, index);
+    if (dirfd != OS::TGT_AT_FDCWD)
+        warn("faccessat: first argument not AT_FDCWD; unlikely to work");
+    return accessFunc(desc, callnum, process, tc, 1);
+}
+
+/// Target readlinkat() handler
+template <class OS>
+SyscallReturn
+readlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+        ThreadContext *tc)
+{
+    int index = 0;
+    int dirfd = process->getSyscallArg(tc, index);
+    if (dirfd != OS::TGT_AT_FDCWD)
+        warn("openat: first argument not AT_FDCWD; unlikely to work");
+    return readlinkFunc(desc, callnum, process, tc, 1);
 }
 
 /// Target sysinfo() handler.
@@ -572,14 +705,16 @@ sysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
          ThreadContext *tc)
 {
 
-   TypedBufferArg<typename OS::tgt_sysinfo> sysinfo(process->getSyscallArg(tc, 0));   
+    int index = 0;
+    TypedBufferArg<typename OS::tgt_sysinfo>
+        sysinfo(process->getSyscallArg(tc, index));   
 
-   sysinfo->uptime=seconds_since_epoch;
-   sysinfo->totalram=process->system->memSize();
+    sysinfo->uptime=seconds_since_epoch;
+    sysinfo->totalram=process->system->memSize();
 
-   sysinfo.copyOut(tc->getMemPort());
+    sysinfo.copyOut(tc->getMemProxy());
 
-   return 0;
+    return 0;
 }
 
 /// Target chmod() handler.
@@ -590,10 +725,13 @@ chmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 {
     std::string path;
 
-    if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
+    int index = 0;
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index))) {
         return -EFAULT;
+    }
 
-    uint32_t mode = process->getSyscallArg(tc, 1);
+    uint32_t mode = process->getSyscallArg(tc, index);
     mode_t hostMode = 0;
 
     // XXX translate mode flags via OS::something???
@@ -617,13 +755,14 @@ SyscallReturn
 fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
            ThreadContext *tc)
 {
-    int fd = process->getSyscallArg(tc, 0);
+    int index = 0;
+    int fd = process->getSyscallArg(tc, index);
     if (fd < 0 || process->sim_fd(fd) < 0) {
         // doesn't map to any simulator fd: not a valid target fd
         return -EBADF;
     }
 
-    uint32_t mode = process->getSyscallArg(tc, 1);
+    uint32_t mode = process->getSyscallArg(tc, index);
     mode_t hostMode = 0;
 
     // XXX translate mode flags via OS::someting???
@@ -642,44 +781,64 @@ template <class OS>
 SyscallReturn
 mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
 {
-    Addr start = process->getSyscallArg(tc, 0);
-    uint64_t old_length = process->getSyscallArg(tc, 1);
-    uint64_t new_length = process->getSyscallArg(tc, 2);
-    uint64_t flags = process->getSyscallArg(tc, 3);
-
-    if ((start % TheISA::VMPageSize != 0) ||
-            (new_length % TheISA::VMPageSize != 0)) {
+    int index = 0;
+    Addr start = process->getSyscallArg(tc, index);
+    uint64_t old_length = process->getSyscallArg(tc, index);
+    uint64_t new_length = process->getSyscallArg(tc, index);
+    uint64_t flags = process->getSyscallArg(tc, index);
+    uint64_t provided_address = 0;
+    bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
+
+    if (use_provided_address)
+        provided_address = process->getSyscallArg(tc, index);
+
+    if ((start % TheISA::PageBytes != 0) ||
+        (provided_address % TheISA::PageBytes != 0)) {
         warn("mremap failing: arguments not page aligned");
         return -EINVAL;
     }
 
+    new_length = roundUp(new_length, TheISA::PageBytes);
+
     if (new_length > old_length) {
-        if ((start + old_length) == process->mmap_end) {
+        if ((start + old_length) == process->mmap_end &&
+            (!use_provided_address || provided_address == start)) {
             uint64_t diff = new_length - old_length;
-            process->pTable->allocate(process->mmap_end, diff);
+            process->allocateMem(process->mmap_end, diff);
             process->mmap_end += diff;
             return start;
         } else {
-            // sys/mman.h defined MREMAP_MAYMOVE
-            if (!(flags & 1)) {
+            if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
                 warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
                 return -ENOMEM;
             } else {
-                process->pTable->remap(start, old_length, process->mmap_end);
-                warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 
-                        process->mmap_end, process->mmap_end + new_length, new_length);
-                start = process->mmap_end;
+                uint64_t new_start = use_provided_address ?
+                    provided_address : process->mmap_end;
+                process->pTable->remap(start, old_length, new_start);
+                warn("mremapping to new vaddr %08p-%08p, adding %d\n",
+                     new_start, new_start + new_length,
+                     new_length - old_length);
                 // add on the remaining unallocated pages
-                process->pTable->allocate(start + old_length, new_length - old_length);
-                process->mmap_end += new_length;
-                warn("returning %08p as start\n", start);
-                return start;
+                process->allocateMem(new_start + old_length,
+                                     new_length - old_length,
+                                     use_provided_address /* clobber */);
+                if (!use_provided_address)
+                    process->mmap_end += new_length;
+                if (use_provided_address &&
+                    new_start + new_length > process->mmap_end) {
+                    // something fishy going on here, at least notify the user
+                    // @todo: increase mmap_end?
+                    warn("mmap region limit exceeded with MREMAP_FIXED\n");
+                }
+                warn("returning %08p as start\n", new_start);
+                return new_start;
             }
         }
     } else {
-        process->pTable->deallocate(start + new_length, old_length -
-                new_length);
-        return start;
+        if (use_provided_address && provided_address != start)
+            process->pTable->remap(start, new_length, provided_address);
+        process->pTable->unmap(start + new_length, old_length - new_length);
+        return use_provided_address ? provided_address : start;
     }
 }
 
@@ -691,8 +850,12 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 {
     std::string path;
 
-    if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
-    return -EFAULT;
+    int index = 0;
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     // Adjust path for current working directory
     path = process->fullPath(path);
@@ -703,8 +866,7 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
-            &hostBuf);
+    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -718,8 +880,48 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
 {
     std::string path;
 
-    if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
+    int index = 0;
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index)))
+        return -EFAULT;
+    Addr bufPtr = process->getSyscallArg(tc, index);
+
+    // Adjust path for current working directory
+    path = process->fullPath(path);
+
+#if NO_STAT64
+    struct stat  hostBuf;
+    int result = stat(path.c_str(), &hostBuf);
+#else
+    struct stat64 hostBuf;
+    int result = stat64(path.c_str(), &hostBuf);
+#endif
+
+    if (result < 0)
+        return -errno;
+
+    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
+
+    return 0;
+}
+
+
+/// Target fstatat64() handler.
+template <class OS>
+SyscallReturn
+fstatat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
+              ThreadContext *tc)
+{
+    int index = 0;
+    int dirfd = process->getSyscallArg(tc, index);
+    if (dirfd != OS::TGT_AT_FDCWD)
+        warn("openat: first argument not AT_FDCWD; unlikely to work");
+
+    std::string path;
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index)))
         return -EFAULT;
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     // Adjust path for current working directory
     path = process->fullPath(path);
@@ -735,8 +937,7 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
-            &hostBuf);
+    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -748,7 +949,9 @@ SyscallReturn
 fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
             ThreadContext *tc)
 {
-    int fd = process->getSyscallArg(tc, 0);
+    int index = 0;
+    int fd = process->getSyscallArg(tc, index);
+    Addr bufPtr = process->getSyscallArg(tc, index);
     if (fd < 0 || process->sim_fd(fd) < 0) {
         // doesn't map to any simulator fd: not a valid target fd
         return -EBADF;
@@ -765,8 +968,7 @@ fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
-        &hostBuf, (fd == 1));
+    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1));
 
     return 0;
 }
@@ -780,8 +982,12 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 {
     std::string path;
 
-    if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
-      return -EFAULT;
+    int index = 0;
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     // Adjust path for current working directory
     path = process->fullPath(path);
@@ -792,8 +998,7 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
-            &hostBuf);
+    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -806,8 +1011,12 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
 {
     std::string path;
 
-    if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
-      return -EFAULT;
+    int index = 0;
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     // Adjust path for current working directory
     path = process->fullPath(path);
@@ -823,8 +1032,7 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
-            &hostBuf);
+    copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -835,7 +1043,9 @@ SyscallReturn
 fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
           ThreadContext *tc)
 {
-    int fd = process->sim_fd(process->getSyscallArg(tc, 0));
+    int index = 0;
+    int fd = process->sim_fd(process->getSyscallArg(tc, index));
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
 
@@ -848,8 +1058,7 @@ fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
-        &hostBuf, (fd == 1));
+    copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1));
 
     return 0;
 }
@@ -863,8 +1072,12 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 {
     std::string path;
 
-    if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
-      return -EFAULT;
+    int index = 0;
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     // Adjust path for current working directory
     path = process->fullPath(path);
@@ -875,8 +1088,7 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStatfsBuf(tc->getMemPort(),
-            (Addr)(process->getSyscallArg(tc, 1)), &hostBuf);
+    OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -888,7 +1100,9 @@ SyscallReturn
 fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
             ThreadContext *tc)
 {
-    int fd = process->sim_fd(process->getSyscallArg(tc, 0));
+    int index = 0;
+    int fd = process->sim_fd(process->getSyscallArg(tc, index));
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     if (fd < 0)
         return -EBADF;
@@ -899,8 +1113,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStatfsBuf(tc->getMemPort(), process->getSyscallArg(tc, 1),
-        &hostBuf);
+    OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -912,25 +1125,26 @@ SyscallReturn
 writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
            ThreadContext *tc)
 {
-    int fd = process->getSyscallArg(tc, 0);
+    int index = 0;
+    int fd = process->getSyscallArg(tc, index);
     if (fd < 0 || process->sim_fd(fd) < 0) {
         // doesn't map to any simulator fd: not a valid target fd
         return -EBADF;
     }
 
-    TranslatingPort *p = tc->getMemPort();
-    uint64_t tiov_base = process->getSyscallArg(tc, 1);
-    size_t count = process->getSyscallArg(tc, 2);
+    SETranslatingPortProxy &p = tc->getMemProxy();
+    uint64_t tiov_base = process->getSyscallArg(tc, index);
+    size_t count = process->getSyscallArg(tc, index);
     struct iovec hiov[count];
     for (size_t i = 0; i < count; ++i) {
         typename OS::tgt_iovec tiov;
 
-        p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
-                    (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
-        hiov[i].iov_len = gtoh(tiov.iov_len);
+        p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
+                   (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec));
+        hiov[i].iov_len = TheISA::gtoh(tiov.iov_len);
         hiov[i].iov_base = new char [hiov[i].iov_len];
-        p->readBlob(gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
-                    hiov[i].iov_len);
+        p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base,
+                   hiov[i].iov_len);
     }
 
     int result = writev(process->sim_fd(fd), hiov, count);
@@ -941,7 +1155,7 @@ writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     if (result < 0)
         return -errno;
 
-    return 0;
+    return result;
 }
 
 
@@ -950,52 +1164,86 @@ 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)
 {
-    Addr start = p->getSyscallArg(tc, 0);
-    uint64_t length = p->getSyscallArg(tc, 1);
-    // int prot = p->getSyscallArg(tc, 2);
-    int flags = p->getSyscallArg(tc, 3);
-    // int fd = p->sim_fd(p->getSyscallArg(tc, 4));
-    // int offset = p->getSyscallArg(tc, 5);
+    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 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)) {
+        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);
+        }
+    }
 
+    length = roundUp(length, TheISA::PageBytes);
 
-    if ((start  % TheISA::VMPageSize) != 0 ||
-        (length % TheISA::VMPageSize) != 0) {
+    if ((start  % TheISA::PageBytes) != 0 ||
+        (offset % TheISA::PageBytes) != 0) {
         warn("mmap failing: arguments not page-aligned: "
-             "start 0x%x length 0x%x",
-             start, length);
+             "start 0x%x offset 0x%x",
+             start, offset);
         return -EINVAL;
     }
 
-    if (start != 0) {
-        warn("mmap: ignoring suggested map address 0x%x, using 0x%x",
-             start, p->mmap_end);
+    // 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;
+            }
+        }
     }
 
-    // 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;
+    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;
+        }
     }
-    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.", p->getSyscallArg(tc, 4));
-    }
+    p->allocateMem(start, length, clobber);
 
     return start;
 }
@@ -1006,22 +1254,23 @@ SyscallReturn
 getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
         ThreadContext *tc)
 {
-    unsigned resource = process->getSyscallArg(tc, 0);
-    TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, 1));
+    int index = 0;
+    unsigned resource = process->getSyscallArg(tc, index);
+    TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index));
 
     switch (resource) {
         case OS::TGT_RLIMIT_STACK:
             // max stack size in bytes: make up a number (8MB for now)
             rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
-            rlp->rlim_cur = htog(rlp->rlim_cur);
-            rlp->rlim_max = htog(rlp->rlim_max);
+            rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
+            rlp->rlim_max = TheISA::htog(rlp->rlim_max);
             break;
 
         case OS::TGT_RLIMIT_DATA:
             // max data segment size in bytes: make up a number
             rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
-            rlp->rlim_cur = htog(rlp->rlim_cur);
-            rlp->rlim_max = htog(rlp->rlim_max);
+            rlp->rlim_cur = TheISA::htog(rlp->rlim_cur);
+            rlp->rlim_max = TheISA::htog(rlp->rlim_max);
             break;
 
         default:
@@ -1031,7 +1280,7 @@ getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
             break;
     }
 
-    rlp.copyOut(tc->getMemPort());
+    rlp.copyOut(tc->getMemProxy());
     return 0;
 }
 
@@ -1041,14 +1290,15 @@ SyscallReturn
 gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
         ThreadContext *tc)
 {
-    TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, 0));
+    int index = 0;
+    TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index));
 
     getElapsedTime(tp->tv_sec, tp->tv_usec);
     tp->tv_sec += seconds_since_epoch;
     tp->tv_sec = TheISA::htog(tp->tv_sec);
     tp->tv_usec = TheISA::htog(tp->tv_usec);
 
-    tp.copyOut(tc->getMemPort());
+    tp.copyOut(tc->getMemProxy());
 
     return 0;
 }
@@ -1062,17 +1312,21 @@ utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
 {
     std::string path;
 
-    if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
-      return -EFAULT;
+    int index = 0;
+    if (!tc->getMemProxy().tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
 
-    TypedBufferArg<typename OS::timeval [2]> tp(process->getSyscallArg(tc, 1));
-    tp.copyIn(tc->getMemPort());
+    TypedBufferArg<typename OS::timeval [2]>
+        tp(process->getSyscallArg(tc, index));
+    tp.copyIn(tc->getMemProxy());
 
     struct timeval hostTimeval[2];
     for (int i = 0; i < 2; ++i)
     {
-        hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
-        hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
+        hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec);
+        hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec);
     }
 
     // Adjust path for current working directory
@@ -1091,8 +1345,9 @@ SyscallReturn
 getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
               ThreadContext *tc)
 {
-    int who = process->getSyscallArg(tc, 0);     // THREAD, SELF, or CHILDREN
-    TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, 1));
+    int index = 0;
+    int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN
+    TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index));
 
     rup->ru_utime.tv_sec = 0;
     rup->ru_utime.tv_usec = 0;
@@ -1116,8 +1371,8 @@ getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     switch (who) {
       case OS::TGT_RUSAGE_SELF:
         getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
-        rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
-        rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
+        rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec);
+        rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec);
         break;
 
       case OS::TGT_RUSAGE_CHILDREN:
@@ -1131,7 +1386,7 @@ getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
              who);
     }
 
-    rup.copyOut(tc->getMemPort());
+    rup.copyOut(tc->getMemProxy());
 
     return 0;
 }
@@ -1142,20 +1397,21 @@ SyscallReturn
 timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
            ThreadContext *tc)
 {
-    TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, 0));
+    int index = 0;
+    TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index));
 
     // Fill in the time structure (in clocks)
-    int64_t clocks = curTick * OS::_SC_CLK_TCK / Clock::Int::s;
+    int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s;
     bufp->tms_utime = clocks;
     bufp->tms_stime = 0;
     bufp->tms_cutime = 0;
     bufp->tms_cstime = 0;
 
     // Convert to host endianness
-    bufp->tms_utime = htog(bufp->tms_utime);
+    bufp->tms_utime = TheISA::htog(bufp->tms_utime);
 
     // Write back
-    bufp.copyOut(tc->getMemPort());
+    bufp.copyOut(tc->getMemProxy());
 
     // Return clock ticks since system boot
     return clocks;
@@ -1171,12 +1427,13 @@ timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
     getElapsedTime(sec, usec);
     sec += seconds_since_epoch;
 
-    Addr taddr = (Addr)process->getSyscallArg(tc, 0);
+    int index = 0;
+    Addr taddr = (Addr)process->getSyscallArg(tc, index);
     if(taddr != 0) {
         typename OS::time_t t = sec;
-        t = htog(t);
-        TranslatingPort *p = tc->getMemPort();
-        p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
+        t = TheISA::htog(t);
+        SETranslatingPortProxy &p = tc->getMemProxy();
+        p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
     }
     return sec;
 }