diff options
Diffstat (limited to 'src/sim/syscall_emul.cc')
-rw-r--r-- | src/sim/syscall_emul.cc | 188 |
1 files changed, 111 insertions, 77 deletions
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index ed0da628e..e72890612 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -24,6 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Steve Reinhardt + * Ali Saidi */ #include <fcntl.h> @@ -35,37 +38,37 @@ #include "sim/syscall_emul.hh" #include "base/chunk_generator.hh" #include "base/trace.hh" -#include "cpu/exec_context.hh" +#include "cpu/thread_context.hh" #include "cpu/base.hh" #include "mem/page_table.hh" #include "sim/process.hh" -#include "sim/sim_events.hh" +#include "sim/sim_exit.hh" using namespace std; using namespace TheISA; void -SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc) +SyscallDesc::doSyscall(int callnum, Process *process, ThreadContext *tc) { DPRINTFR(SyscallVerbose, "%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n", - curTick,xc->getCpuPtr()->name(), name, - xc->getSyscallArg(0),xc->getSyscallArg(1), - xc->getSyscallArg(2),xc->getSyscallArg(3)); + curTick,tc->getCpuPtr()->name(), name, + tc->getSyscallArg(0),tc->getSyscallArg(1), + tc->getSyscallArg(2),tc->getSyscallArg(3)); - SyscallReturn retval = (*funcPtr)(this, callnum, process, xc); + SyscallReturn retval = (*funcPtr)(this, callnum, process, tc); DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n", - curTick,xc->getCpuPtr()->name(), name, retval.value()); + curTick,tc->getCpuPtr()->name(), name, retval.value()); if (!(flags & SyscallDesc::SuppressReturnValue)) - xc->setSyscallReturn(retval); + tc->setSyscallReturn(retval); } SyscallReturn unimplementedFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { fatal("syscall %s (#%d) unimplemented.", desc->name, callnum); @@ -75,10 +78,10 @@ unimplementedFunc(SyscallDesc *desc, int callnum, Process *process, SyscallReturn ignoreFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { warn("ignoring syscall %s(%d, %d, ...)", desc->name, - xc->getSyscallArg(0), xc->getSyscallArg(1)); + tc->getSyscallArg(0), tc->getSyscallArg(1)); return 0; } @@ -86,28 +89,30 @@ ignoreFunc(SyscallDesc *desc, int callnum, Process *process, SyscallReturn exitFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { - new SimExitEvent("target called exit()", xc->getSyscallArg(0) & 0xff); + if (tc->exit()) { + exitSimLoop("target called exit()", tc->getSyscallArg(0) & 0xff); + } return 1; } SyscallReturn -getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { return (int)VMPageSize; } SyscallReturn -obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +obreakFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { Addr junk; // change brk addr to first arg - Addr new_brk = xc->getSyscallArg(0); + Addr new_brk = tc->getSyscallArg(0); if (new_brk != 0) { for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point, VMPageSize); !gen.done(); gen.next()) { @@ -123,9 +128,9 @@ obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) SyscallReturn -closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +closeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { - int target_fd = xc->getSyscallArg(0); + int target_fd = tc->getSyscallArg(0); int status = close(p->sim_fd(target_fd)); if (status >= 0) p->free_fd(target_fd); @@ -134,28 +139,28 @@ closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) SyscallReturn -readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +readFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { - int fd = p->sim_fd(xc->getSyscallArg(0)); - int nbytes = xc->getSyscallArg(2); - BufferArg bufArg(xc->getSyscallArg(1), nbytes); + int fd = p->sim_fd(tc->getSyscallArg(0)); + int nbytes = tc->getSyscallArg(2); + BufferArg bufArg(tc->getSyscallArg(1), nbytes); int bytes_read = read(fd, bufArg.bufferPtr(), nbytes); if (bytes_read != -1) - bufArg.copyOut(xc->getMemPort()); + bufArg.copyOut(tc->getMemPort()); return bytes_read; } SyscallReturn -writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +writeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { - int fd = p->sim_fd(xc->getSyscallArg(0)); - int nbytes = xc->getSyscallArg(2); - BufferArg bufArg(xc->getSyscallArg(1), nbytes); + int fd = p->sim_fd(tc->getSyscallArg(0)); + int nbytes = tc->getSyscallArg(2); + BufferArg bufArg(tc->getSyscallArg(1), nbytes); - bufArg.copyIn(xc->getMemPort()); + bufArg.copyIn(tc->getMemPort()); int bytes_written = write(fd, bufArg.bufferPtr(), nbytes); @@ -166,11 +171,11 @@ writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) SyscallReturn -lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +lseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { - int fd = p->sim_fd(xc->getSyscallArg(0)); - uint64_t offs = xc->getSyscallArg(1); - int whence = xc->getSyscallArg(2); + int fd = p->sim_fd(tc->getSyscallArg(0)); + uint64_t offs = tc->getSyscallArg(1); + int whence = tc->getSyscallArg(2); off_t result = lseek(fd, offs, whence); @@ -179,7 +184,7 @@ lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) SyscallReturn -munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +munmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { // given that we don't really implement mmap, munmap is really easy return 0; @@ -189,24 +194,24 @@ munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) const char *hostname = "m5.eecs.umich.edu"; SyscallReturn -gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +gethostnameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { - int name_len = xc->getSyscallArg(1); - BufferArg name(xc->getSyscallArg(0), name_len); + int name_len = tc->getSyscallArg(1); + BufferArg name(tc->getSyscallArg(0), name_len); strncpy((char *)name.bufferPtr(), hostname, name_len); - name.copyOut(xc->getMemPort()); + name.copyOut(tc->getMemPort()); return 0; } SyscallReturn -unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +unlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { string path; - if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) return (TheISA::IntReg)-EFAULT; int result = unlink(path.c_str()); @@ -214,16 +219,16 @@ unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) } SyscallReturn -renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +renameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { string old_name; - if (!xc->getMemPort()->tryReadString(old_name, xc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(old_name, tc->getSyscallArg(0))) return -EFAULT; string new_name; - if (!xc->getMemPort()->tryReadString(new_name, xc->getSyscallArg(1))) + if (!tc->getMemPort()->tryReadString(new_name, tc->getSyscallArg(1))) return -EFAULT; int64_t result = rename(old_name.c_str(), new_name.c_str()); @@ -231,45 +236,45 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) } SyscallReturn -truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +truncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { string path; - if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) return -EFAULT; - off_t length = xc->getSyscallArg(1); + off_t length = tc->getSyscallArg(1); int result = truncate(path.c_str(), length); return (result == -1) ? -errno : result; } SyscallReturn -ftruncateFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc) +ftruncateFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc) { - int fd = process->sim_fd(xc->getSyscallArg(0)); + int fd = process->sim_fd(tc->getSyscallArg(0)); if (fd < 0) return -EBADF; - off_t length = xc->getSyscallArg(1); + off_t length = tc->getSyscallArg(1); int result = ftruncate(fd, length); return (result == -1) ? -errno : result; } SyscallReturn -chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +chownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) { string path; - if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0))) + if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0))) return -EFAULT; /* XXX endianess */ - uint32_t owner = xc->getSyscallArg(1); + uint32_t owner = tc->getSyscallArg(1); uid_t hostOwner = owner; - uint32_t group = xc->getSyscallArg(2); + uint32_t group = tc->getSyscallArg(2); gid_t hostGroup = group; int result = chown(path.c_str(), hostOwner, hostGroup); @@ -277,17 +282,17 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) } SyscallReturn -fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc) +fchownFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc) { - int fd = process->sim_fd(xc->getSyscallArg(0)); + int fd = process->sim_fd(tc->getSyscallArg(0)); if (fd < 0) return -EBADF; /* XXX endianess */ - uint32_t owner = xc->getSyscallArg(1); + uint32_t owner = tc->getSyscallArg(1); uid_t hostOwner = owner; - uint32_t group = xc->getSyscallArg(2); + uint32_t group = tc->getSyscallArg(2); gid_t hostGroup = group; int result = fchown(fd, hostOwner, hostGroup); @@ -297,14 +302,14 @@ fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc) SyscallReturn fcntlFunc(SyscallDesc *desc, int num, Process *process, - ExecContext *xc) + ThreadContext *tc) { - int fd = xc->getSyscallArg(0); + int fd = tc->getSyscallArg(0); if (fd < 0 || process->sim_fd(fd) < 0) return -EBADF; - int cmd = xc->getSyscallArg(1); + int cmd = tc->getSyscallArg(1); switch (cmd) { case 0: // F_DUPFD // if we really wanted to support this, we'd need to do it @@ -338,8 +343,37 @@ fcntlFunc(SyscallDesc *desc, int num, Process *process, } SyscallReturn +fcntl64Func(SyscallDesc *desc, int num, Process *process, + ThreadContext *tc) +{ + int fd = tc->getSyscallArg(0); + + if (fd < 0 || process->sim_fd(fd) < 0) + return -EBADF; + + int cmd = tc->getSyscallArg(1); + switch (cmd) { + case 33: //F_GETLK64 + warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd); + return -EMFILE; + + case 34: // F_SETLK64 + case 35: // F_SETLKW64 + warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n", fd); + return -EMFILE; + + default: + // not sure if this is totally valid, but we'll pass it through + // to the underlying OS + warn("fcntl64(%d, %d) passed through to host\n", fd, cmd); + return fcntl(process->sim_fd(fd), cmd); + // return 0; + } +} + +SyscallReturn pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { int fds[2], sim_fds[2]; int pipe_retval = pipe(fds); @@ -354,99 +388,99 @@ pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process, // Alpha Linux convention for pipe() is that fd[0] is returned as // the return value of the function, and fd[1] is returned in r20. - xc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]); + tc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]); return sim_fds[0]; } SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { // Make up a PID. There's no interprocess communication in // fake_syscall mode, so there's no way for a process to know it's // not getting a unique value. - xc->setIntReg(SyscallPseudoReturnReg, 99); + tc->setIntReg(SyscallPseudoReturnReg, 99); return 100; } SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { // Make up a UID and EUID... it shouldn't matter, and we want the // simulation to be deterministic. // EUID goes in r20. - xc->setIntReg(SyscallPseudoReturnReg, 100); //EUID + tc->setIntReg(SyscallPseudoReturnReg, 100); //EUID return 100; // UID } SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { // Get current group ID. EGID goes in r20. - xc->setIntReg(SyscallPseudoReturnReg, 100); //EGID + tc->setIntReg(SyscallPseudoReturnReg, 100); //EGID return 100; } SyscallReturn setuidFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { // can't fathom why a benchmark would call this. - warn("Ignoring call to setuid(%d)\n", xc->getSyscallArg(0)); + warn("Ignoring call to setuid(%d)\n", tc->getSyscallArg(0)); return 0; } SyscallReturn getpidFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { // Make up a PID. There's no interprocess communication in // fake_syscall mode, so there's no way for a process to know it's // not getting a unique value. - xc->setIntReg(SyscallPseudoReturnReg, 99); //PID + tc->setIntReg(SyscallPseudoReturnReg, 99); //PID return 100; } SyscallReturn getppidFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { return 99; } SyscallReturn getuidFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { return 100; // UID } SyscallReturn geteuidFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { return 100; // UID } SyscallReturn getgidFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { return 100; } SyscallReturn getegidFunc(SyscallDesc *desc, int callnum, Process *process, - ExecContext *xc) + ThreadContext *tc) { return 100; } |