#ifndef __SIM_SYSCALL_EMUL_HH__
#define __SIM_SYSCALL_EMUL_HH__
+#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \
+ defined(__FreeBSD__))
+
///
/// @file syscall_emul.hh
///
#include <errno.h>
#include <string>
+#ifdef __CYGWIN32__
+#include <sys/fcntl.h> // for O_BINARY
+#endif
+#include <sys/uio.h>
#include "base/intmath.hh" // for RoundUp
-#include "mem/functional_mem/functional_memory.hh"
-#include "targetarch/isa_traits.hh" // for Addr
+#include "mem/functional/functional.hh"
+#include "arch/isa_traits.hh" // for Addr
#include "base/trace.hh"
#include "cpu/exec_context.hh"
/// Handler for unimplemented syscalls that we haven't thought about.
-SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Handler for unimplemented syscalls that we never intend to
/// implement (signal handling, etc.) and should not affect the correct
/// behavior of the program. Print a warning only if the appropriate
/// trace flag is enabled. Return success to the target program.
-SyscallReturn ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target exit() handler: terminate simulation.
-SyscallReturn exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn exitFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target getpagesize() handler.
-SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target obreak() handler: set brk address.
-SyscallReturn obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn obreakFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target close() handler.
-SyscallReturn closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn closeFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target read() handler.
-SyscallReturn readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn readFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target write() handler.
-SyscallReturn writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn writeFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target lseek() handler.
-SyscallReturn lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn lseekFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target munmap() handler.
-SyscallReturn munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn munmapFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target gethostname() handler.
-SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target unlink() handler.
-SyscallReturn unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
/// Target rename() handler.
-SyscallReturn renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn renameFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+/// Target truncate() handler.
+SyscallReturn truncateFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+/// Target ftruncate() handler.
+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.
void
getElapsedTime(T1 &sec, T2 &usec)
{
- int cycles_per_usec = ticksPerSecond / one_million;
-
- int elapsed_usecs = curTick / cycles_per_usec;
+ int elapsed_usecs = curTick / Clock::Int::us;
sec = elapsed_usecs / one_million;
usec = elapsed_usecs % one_million;
}
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
return -ENOTTY;
default:
- fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n", fd, req, xc->readPC());
+ fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
+ fd, req, xc->readPC());
}
}
if (path == "/dev/sysdev0") {
// This is a memory-mapped high-resolution timer device on Alpha.
// We don't support it, so just punt.
- DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << std::endl;
+ warn("Ignoring open(%s, ...)\n", path);
return -ENOENT;
}
// any target flags left?
if (tgtFlags != 0)
- std::cerr << "Syscall: open: cannot decode flags: " << tgtFlags << std::endl;
+ warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
#ifdef __CYGWIN32__
hostFlags |= O_BINARY;
#endif
+ DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
+
// 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;
}
}
+/// 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
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
{
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;
return -errno;
OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+ return 0;
+}
+
+
+/// Target statfs() handler.
+template <class OS>
+SyscallReturn
+statfsFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ std::string path;
+
+ if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+ return -EFAULT;
+
+ struct statfs hostBuf;
+ int result = statfs(path.c_str(), &hostBuf);
+
+ if (result < 0)
+ return errno;
+
+ OS::copyOutStatfsBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+
+/// Target fstatfs() handler.
+template <class OS>
+SyscallReturn
+fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fd = process->sim_fd(xc->getSyscallArg(0));
+
+ if (fd < 0)
+ return -EBADF;
+
+ struct statfs hostBuf;
+ int result = fstatfs(fd, &hostBuf);
+
+ if (result < 0)
+ return errno;
+
+ OS::copyOutStatfsBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+
+/// 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;
}
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);
+ }
}
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;
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);
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);
}
+/// 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
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;