Merge zizzer:/bk/m5
[gem5.git] / sim / syscall_emul.hh
index d061f868e0fa36a24a7be0543cfc981b164fe5da..d8029ddb0b30c40378a4515035bd3c440a1faa33 100644 (file)
@@ -29,6 +29,9 @@
 #ifndef __SIM_SYSCALL_EMUL_HH__
 #define __SIM_SYSCALL_EMUL_HH__
 
+#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \
+                  defined(__FreeBSD__))
+
 ///
 /// @file syscall_emul.hh
 ///
 #ifdef __CYGWIN32__
 #include <sys/fcntl.h> // for O_BINARY
 #endif
+#include <sys/uio.h>
 
 #include "base/intmath.hh"     // for RoundUp
 #include "mem/functional/functional.hh"
-#include "targetarch/isa_traits.hh"    // for Addr
+#include "arch/isa_traits.hh"  // for Addr
 
 #include "base/trace.hh"
 #include "cpu/exec_context.hh"
@@ -226,6 +230,15 @@ SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
                             Process *p, ExecContext *xc);
 
 
+/// Target chown() handler.
+SyscallReturn chownFunc(SyscallDesc *desc, int num,
+                        Process *p, ExecContext *xc);
+
+
+/// Target fchown() handler.
+SyscallReturn fchownFunc(SyscallDesc *desc, int num,
+                         Process *p, ExecContext *xc);
+
 /// This struct is used to build an target-OS-dependent table that
 /// maps the target's open() flags to the host open() flags.
 struct OpenFlagTransTable {
@@ -272,7 +285,7 @@ ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
     int fd = xc->getSyscallArg(0);
     unsigned req = xc->getSyscallArg(1);
 
-    // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
+    DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
 
     if (fd < 0 || process->sim_fd(fd) < 0) {
         // doesn't map to any simulator fd: not a valid target fd
@@ -339,7 +352,60 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
     // open the file
     int fd = open(path.c_str(), hostFlags, mode);
 
-    return (fd == -1) ? -errno : process->open_fd(fd);
+    return (fd == -1) ? -errno : process->alloc_fd(fd);
+}
+
+
+/// Target chmod() handler.
+template <class OS>
+SyscallReturn
+chmodFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    std::string path;
+
+    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+        return -EFAULT;
+
+    uint32_t mode = xc->getSyscallArg(1);
+    mode_t hostMode = 0;
+
+    // XXX translate mode flags via OS::something???
+    hostMode = mode;
+
+    // do the chmod
+    int result = chmod(path.c_str(), hostMode);
+    if (result < 0)
+        return errno;
+
+    return 0;
+}
+
+
+/// Target fchmod() handler.
+template <class OS>
+SyscallReturn
+fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
+           ExecContext *xc)
+{
+    int fd = xc->getSyscallArg(0);
+    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 = xc->getSyscallArg(1);
+    mode_t hostMode = 0;
+
+    // XXX translate mode flags via OS::someting???
+    hostMode = mode;
+
+    // do the fchmod
+    int result = fchmod(process->sim_fd(fd), hostMode);
+    if (result < 0)
+        return errno;
+
+    return 0;
 }
 
 
@@ -366,6 +432,35 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
 }
 
 
+/// Target fstat64() handler.
+template <class OS>
+SyscallReturn
+fstat64Func(SyscallDesc *desc, int callnum, Process *process,
+            ExecContext *xc)
+{
+    int fd = xc->getSyscallArg(0);
+    if (fd < 0 || process->sim_fd(fd) < 0) {
+        // doesn't map to any simulator fd: not a valid target fd
+        return -EBADF;
+    }
+
+#if BSD_HOST
+    struct stat  hostBuf;
+    int result = fstat(process->sim_fd(fd), &hostBuf);
+#else
+    struct stat64  hostBuf;
+    int result = fstat64(process->sim_fd(fd), &hostBuf);
+#endif
+
+    if (result < 0)
+        return errno;
+
+    OS::copyOutStat64Buf(xc->mem, fd, xc->getSyscallArg(1), &hostBuf);
+
+    return 0;
+}
+
+
 /// Target lstat() handler.
 template <class OS>
 SyscallReturn
@@ -388,6 +483,33 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
     return 0;
 }
 
+/// Target lstat64() handler.
+template <class OS>
+SyscallReturn
+lstat64Func(SyscallDesc *desc, int callnum, Process *process,
+            ExecContext *xc)
+{
+    std::string path;
+
+    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+        return -EFAULT;
+
+#if BSD_HOST
+    struct stat hostBuf;
+    int result = lstat(path.c_str(), &hostBuf);
+#else
+    struct stat64 hostBuf;
+    int result = lstat64(path.c_str(), &hostBuf);
+#endif
+
+    if (result < 0)
+        return -errno;
+
+    OS::copyOutStat64Buf(xc->mem, -1, xc->getSyscallArg(1), &hostBuf);
+
+    return 0;
+}
+
 /// Target fstat() handler.
 template <class OS>
 SyscallReturn
@@ -396,7 +518,7 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
 {
     int fd = process->sim_fd(xc->getSyscallArg(0));
 
-    // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd);
+    DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
 
     if (fd < 0)
         return -EBADF;
@@ -408,7 +530,6 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
         return -errno;
 
     OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
-
     return 0;
 }
 
@@ -459,6 +580,46 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
 }
 
 
+/// Target writev() handler.
+template <class OS>
+SyscallReturn
+writevFunc(SyscallDesc *desc, int callnum, Process *process,
+           ExecContext *xc)
+{
+    int fd = xc->getSyscallArg(0);
+    if (fd < 0 || process->sim_fd(fd) < 0) {
+        // doesn't map to any simulator fd: not a valid target fd
+        return -EBADF;
+    }
+
+    uint64_t tiov_base = xc->getSyscallArg(1);
+    size_t count = xc->getSyscallArg(2);
+    struct iovec hiov[count];
+    for (int i = 0; i < count; ++i)
+    {
+        typename OS::tgt_iovec tiov;
+        xc->mem->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec),
+                        &tiov, sizeof(typename OS::tgt_iovec));
+        hiov[i].iov_len = gtoh(tiov.iov_len);
+        hiov[i].iov_base = new char [hiov[i].iov_len];
+        xc->mem->access(Read, gtoh(tiov.iov_base),
+                        hiov[i].iov_base, hiov[i].iov_len);
+    }
+
+    int result = writev(process->sim_fd(fd), hiov, count);
+
+    for (int i = 0; i < count; ++i)
+    {
+        delete [] (char *)hiov[i].iov_base;
+    }
+
+    if (result < 0)
+        return errno;
+
+    return 0;
+}
+
+
 /// Target mmap() handler.
 ///
 /// We don't really handle mmap().  If the target is mmaping an
@@ -485,7 +646,7 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
     if (start == 0) {
         // user didn't give an address... pick one from our "mmap region"
         start = p->mmap_end;
-        p->mmap_end += RoundUp<Addr>(length, VMPageSize);
+        p->mmap_end += roundUp(length, VMPageSize);
         if (p->nxm_start != 0) {
             //If we have an nxm space, make sure we haven't colided
             assert(p->mmap_end < p->nxm_start);
@@ -493,8 +654,8 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
     }
 
     if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
-        DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d.  "
-                "This will break if not /dev/zero.", xc->getSyscallArg(4));
+        warn("allowing mmap of file @ fd %d. "
+             "This will break if not /dev/zero.", xc->getSyscallArg(4));
     }
 
     return start;
@@ -504,22 +665,24 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
 template <class OS>
 SyscallReturn
 getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
+        ExecContext *xc)
 {
     unsigned resource = xc->getSyscallArg(0);
     TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
 
     switch (resource) {
-      case OS::RLIMIT_STACK:
-        // max stack size in bytes: make up a number (2MB for now)
-        rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
-        break;
-
-      default:
-        std::cerr << "getrlimitFunc: unimplemented resource " << resource
-                  << std::endl;
-        abort();
-        break;
+        case OS::TGT_RLIMIT_STACK:
+            // max stack size in bytes: make up a number (2MB 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);
+            break;
+
+        default:
+            std::cerr << "getrlimitFunc: unimplemented resource " << resource
+                << std::endl;
+            abort();
+            break;
     }
 
     rlp.copyOut(xc->mem);
@@ -530,12 +693,14 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
 template <class OS>
 SyscallReturn
 gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
-                 ExecContext *xc)
+        ExecContext *xc)
 {
     TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
 
     getElapsedTime(tp->tv_sec, tp->tv_usec);
     tp->tv_sec += seconds_since_epoch;
+    tp->tv_sec = htog(tp->tv_sec);
+    tp->tv_usec = htog(tp->tv_usec);
 
     tp.copyOut(xc->mem);
 
@@ -543,6 +708,33 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
 }
 
 
+/// Target utimes() handler.
+template <class OS>
+SyscallReturn
+utimesFunc(SyscallDesc *desc, int callnum, Process *process,
+           ExecContext *xc)
+{
+    std::string path;
+
+    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+        return -EFAULT;
+
+    TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
+    tp.copyIn(xc->mem);
+
+    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);
+    }
+    int result = utimes(path.c_str(), hostTimeval);
+
+    if (result < 0)
+        return -errno;
+
+    return 0;
+}
 /// Target getrusage() function.
 template <class OS>
 SyscallReturn
@@ -552,15 +744,17 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
     int who = xc->getSyscallArg(0);    // THREAD, SELF, or CHILDREN
     TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
 
-    if (who != OS::RUSAGE_SELF) {
+    if (who != OS::TGT_RUSAGE_SELF) {
         // don't really handle THREAD or CHILDREN, but just warn and
         // plow ahead
-        DCOUT(SyscallWarnings)
-            << "Warning: getrusage() only supports RUSAGE_SELF."
-            << "  Parameter " << who << " ignored." << std::endl;
+        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
+             who);
     }
 
     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_stime.tv_sec = 0;
     rup->ru_stime.tv_usec = 0;
     rup->ru_maxrss = 0;