# Node ID 05bae81fc38921795df6c0de5fd1756f3d09746c # Parent e40b35147270fbbbb8035650bd28efe037d92465 diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -220,19 +220,18 @@ } void -AlphaLiveProcess::setSyscallReturn(ThreadContext *tc, - SyscallReturn return_value) +AlphaLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) { // check for error condition. Alpha syscall convention is to // indicate success/failure in reg a3 (r19) and put the // return value itself in the standard return value reg (v0). - if (return_value.successful()) { + if (sysret.successful()) { // no error tc->setIntReg(SyscallSuccessReg, 0); - tc->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(ReturnValueReg, sysret.returnValue()); } else { // got an error, return details tc->setIntReg(SyscallSuccessReg, (IntReg)-1); - tc->setIntReg(ReturnValueReg, -return_value.value()); + tc->setIntReg(ReturnValueReg, sysret.errnoValue()); } } diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -454,15 +454,13 @@ } void -ArmLiveProcess32::setSyscallReturn(ThreadContext *tc, - SyscallReturn return_value) +ArmLiveProcess32::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) { - tc->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(ReturnValueReg, sysret.encodedValue()); } void -ArmLiveProcess64::setSyscallReturn(ThreadContext *tc, - SyscallReturn return_value) +ArmLiveProcess64::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) { - tc->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(ReturnValueReg, sysret.encodedValue()); } diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -197,16 +197,15 @@ } void -MipsLiveProcess::setSyscallReturn(ThreadContext *tc, - SyscallReturn return_value) +MipsLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) { - if (return_value.successful()) { + if (sysret.successful()) { // no error tc->setIntReg(SyscallSuccessReg, 0); - tc->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(ReturnValueReg, sysret.returnValue()); } else { // got an error, return details tc->setIntReg(SyscallSuccessReg, (IntReg) -1); - tc->setIntReg(ReturnValueReg, -return_value.value()); + tc->setIntReg(ReturnValueReg, sysret.errnoValue()); } } diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -277,15 +277,14 @@ } void -PowerLiveProcess::setSyscallReturn(ThreadContext *tc, - SyscallReturn return_value) +PowerLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) { Cr cr = tc->readIntReg(INTREG_CR); - if (return_value.successful()) { + if (sysret.successful()) { cr.cr0.so = 0; } else { cr.cr0.so = 1; } tc->setIntReg(INTREG_CR, cr); - tc->setIntReg(ReturnValueReg, return_value.value()); + tc->setIntReg(ReturnValueReg, sysret.encodedValue()); } diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -532,26 +532,25 @@ } void -SparcLiveProcess::setSyscallReturn(ThreadContext *tc, - SyscallReturn return_value) +SparcLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret) { // check for error condition. SPARC syscall convention is to // indicate success/failure in reg the carry bit of the ccr // and put the return value itself in the standard return value reg (). PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); - if (return_value.successful()) { + if (sysret.successful()) { // no error, clear XCC.C tc->setIntReg(NumIntArchRegs + 2, - tc->readIntReg(NumIntArchRegs + 2) & 0xEE); - IntReg val = return_value.value(); + tc->readIntReg(NumIntArchRegs + 2) & 0xEE); + IntReg val = sysret.returnValue(); if (pstate.am) val = bits(val, 31, 0); tc->setIntReg(ReturnValueReg, val); } else { // got an error, set XCC.C tc->setIntReg(NumIntArchRegs + 2, - tc->readIntReg(NumIntArchRegs + 2) | 0x11); - IntReg val = -return_value.value(); + tc->readIntReg(NumIntArchRegs + 2) | 0x11); + IntReg val = sysret.errnoValue(); if (pstate.am) val = bits(val, 31, 0); tc->setIntReg(ReturnValueReg, val); diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -678,9 +678,9 @@ } void -X86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn return_value) +X86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn retval) { - tc->setIntReg(INTREG_RAX, return_value.value()); + tc->setIntReg(INTREG_RAX, retval.encodedValue()); } X86ISA::IntReg diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -69,7 +69,7 @@ SyscallReturn retval = (*funcPtr)(this, callnum, process, tc); DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n", - curTick(),tc->getCpuPtr()->name(), name, retval.value()); + curTick(), tc->getCpuPtr()->name(), name, retval.encodedValue()); if (!(flags & SyscallDesc::SuppressReturnValue)) process->setSyscallReturn(tc, retval); @@ -359,7 +359,7 @@ int index = 0; if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) - return (TheISA::IntReg)-EFAULT; + return -EFAULT; // Adjust path for current working directory path = p->fullPath(path); @@ -383,7 +383,7 @@ int index = 0; if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) - return (TheISA::IntReg)-EFAULT; + return -EFAULT; // Adjust path for current working directory path = p->fullPath(path); @@ -400,7 +400,7 @@ int index = 0; if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) - return (TheISA::IntReg)-EFAULT; + return -EFAULT; // Adjust path for current working directory path = p->fullPath(path); @@ -858,7 +858,7 @@ string path; if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) - return (TheISA::IntReg)-EFAULT; + return -EFAULT; // Adjust path for current working directory path = p->fullPath(path); diff --git a/src/sim/syscallreturn.hh b/src/sim/syscallreturn.hh --- a/src/sim/syscallreturn.hh +++ b/src/sim/syscallreturn.hh @@ -33,38 +33,71 @@ #include "base/types.hh" +/** + * This class represents the return value from an emulated system call, + * including any errno setting. + * + * On some platforms, the return value and errno are encoded in a + * single signed integer. A value less than zero but greater than + * -4096 indicates an error, and the value is the negation of the + * errno value. Otherwise, the call was successful and the integer is + * the return value. (Large negative numbers are considered + * successful to allow syscalls to return pointers to high memory, + * e.g., stack addresses.) See, for example, Appendix A of the AMD64 + * ABI spec at http://www.x86-64.org/documentation/abi.pdf. + * + * Other platforms use a more complex interface, returning a value and + * an error code in separate registers. + * + * This class is designed to support both types of interfaces. + */ class SyscallReturn { public: - template - SyscallReturn(T v, bool s) - { - retval = (uint64_t)v; - success = s; - } - template - SyscallReturn(T v) - { - success = (v >= 0); - retval = (uint64_t)v; - } + /// For simplicity, allow the object to be initialized with a + /// single signed integer using the same positive=success, + /// negative=-errno convention described above. + /// + /// Typically this constructor is used as a default type + /// conversion, so a bare integer is used where a SyscallReturn + /// value is expected, e.g., as the return value from a system + /// call emulation function ('return 0;' or 'return -EFAULT;'). + SyscallReturn(int64_t v) + : value(v) + {} ~SyscallReturn() {} - SyscallReturn& operator=(const SyscallReturn& s) + /// Was the system call successful? + bool successful() const { - retval = s.retval; - success = s.success; - return *this; + return (value >= 0 || value <= -4096); } - bool successful() { return success; } - uint64_t value() { return retval; } + /// The return value + int64_t returnValue() const + { + assert(successful()); + return value; + } - private: - uint64_t retval; - bool success; + /// The errno value + int errnoValue() const + { + assert(!successful()); + return -value; + } + + /// The encoded value (as described above) + int64_t encodedValue() const + { + return value; + } + + private: + + int64_t value; }; #endif