diff options
Diffstat (limited to 'src/sim')
-rw-r--r-- | src/sim/syscall_emul.cc | 91 | ||||
-rw-r--r-- | src/sim/syscall_emul.hh | 13 |
2 files changed, 101 insertions, 3 deletions
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index f0a693db0..d3161de26 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -106,6 +106,19 @@ exitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, SyscallReturn +exitGroupFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + // really should just halt all thread contexts belonging to this + // process in case there's another process running... + exitSimLoop("target called exit()", + process->getSyscallArg(tc, 0) & 0xff); + + return 1; +} + + +SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { return (int)VMPageSize; @@ -641,3 +654,81 @@ getegidFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } +SyscallReturn +cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + DPRINTF(SyscallVerbose, "In sys_clone:\n"); + DPRINTF(SyscallVerbose, " Flags=%llx\n", tc->getSyscallArg(0)); + DPRINTF(SyscallVerbose, " Child stack=%llx\n", tc->getSyscallArg(1)); + + + if (tc->getSyscallArg(0) != 0x10f00) { + warn("This sys_clone implementation assumes flags CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD (0x10f00), and may not work correctly with given flags 0x%llx\n", tc->getSyscallArg(0)); + } + + ThreadContext* ctc; //child thread context + if ( ( ctc = process->findFreeContext() ) != NULL ) { + DPRINTF(SyscallVerbose, " Found unallocated thread context\n"); + + ctc->clearArchRegs(); + + //Arch-specific cloning code + #if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA + //Cloning the misc. regs for these archs is enough + TheISA::copyMiscRegs(tc, ctc); + #elif THE_ISA == SPARC_ISA + TheISA::copyRegs(tc, ctc); + + //TODO: Explain what this code actually does :-) + ctc->setIntReg(NumIntArchRegs + 6, 0); + ctc->setIntReg(NumIntArchRegs + 4, 0); + ctc->setIntReg(NumIntArchRegs + 3, NWindows - 2); + ctc->setIntReg(NumIntArchRegs + 5, NWindows); + ctc->setMiscRegNoEffect(MISCREG_CWP, 0); + ctc->setIntReg(NumIntArchRegs + 7, 0); + ctc->setMiscRegNoEffect(MISCREG_TL, 0); + ctc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY); + + for (int y = 8; y < 32; y++) + ctc->setIntReg(y, tc->readIntReg(y)); + #else + fatal("sys_clone is not implemented for this ISA\n"); + #endif + + //Set up stack register + ctc->setIntReg(TheISA::StackPointerReg, tc->getSyscallArg(1)); + + //Set up syscall return values in parent and child + ctc->setIntReg(ReturnValueReg, 0); //return value, child + + //Alpha needs SyscallSuccessReg=0 in child + #if THE_ISA == ALPHA_ISA + ctc->setIntReg(SyscallSuccessReg, 0); + #endif + + //In SPARC/Linux, clone returns 0 on pseudo-return register if parent, non-zero if child + #if THE_ISA == SPARC_ISA + tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0); + ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1); + #endif + + ctc->setPC(tc->readNextPC()); + ctc->setNextPC(tc->readNextPC() + sizeof(TheISA::MachInst)); + + //In SPARC, need NNPC too... + #if THE_ISA == SPARC_ISA + ctc->setNextNPC(tc->readNextNPC() + sizeof(TheISA::MachInst)); + #endif + + ctc->activate(); + + // Should return nonzero child TID in parent's syscall return register, + // but for our pthread library any non-zero value will work + return 1; + } else { + fatal("Called sys_clone, but no unallocated thread contexts found!\n"); + return 0; + } +} + diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 0b0e73692..e995bd487 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -183,10 +183,14 @@ SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, SyscallReturn ignoreFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); -/// Target exit() handler: terminate simulation. +/// Target exit() handler: terminate current context. SyscallReturn exitFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); +/// Target exit_group() handler: terminate simulation. (exit all threads) +SyscallReturn exitGroupFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + /// Target getpagesize() handler. SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); @@ -308,6 +312,9 @@ SyscallReturn geteuidFunc(SyscallDesc *desc, int num, SyscallReturn getegidFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); +/// Target clone() handler. +SyscallReturn cloneFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); /// Pseudo Funcs - These functions use a different return convension, @@ -1013,8 +1020,8 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 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->tv_sec = TheISA::htog(tp->tv_sec); + tp->tv_usec = TheISA::htog(tp->tv_usec); tp.copyOut(tc->getMemPort()); |