syscall emulation: clean up & comment SyscallReturn
authorSteve Reinhardt <steve.reinhardt@amd.com>
Mon, 12 May 2014 21:23:31 +0000 (14:23 -0700)
committerSteve Reinhardt <steve.reinhardt@amd.com>
Mon, 12 May 2014 21:23:31 +0000 (14:23 -0700)
src/arch/alpha/process.cc
src/arch/arm/process.cc
src/arch/mips/process.cc
src/arch/power/process.cc
src/arch/sparc/process.cc
src/arch/x86/process.cc
src/sim/syscall_emul.cc
src/sim/syscallreturn.hh

index 07208fb29e51b531fbef57fc9c3a20ce072e25a9..8cc83b0fd488bec8ead31c2f12d4e4c1a5f79aaa 100644 (file)
@@ -220,19 +220,18 @@ AlphaLiveProcess::setSyscallArg(ThreadContext *tc,
 }
 
 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());
     }
 }
index dd23a5e214ed88a7e5fef3476e221a5c0b2205ae..175382b43257158f4229d5ece8ef0aefac91647d 100644 (file)
@@ -454,15 +454,13 @@ ArmLiveProcess64::setSyscallArg(ThreadContext *tc,
 }
 
 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());
 }
index 4ed9a7b39ecd82cd1908004a4eb4bef587f851ee..f84c5cc4a5f6295b98f037f54f4da1282969fcb9 100644 (file)
@@ -197,16 +197,15 @@ MipsLiveProcess::setSyscallArg(ThreadContext *tc,
 }
 
 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());
     }
 }
index 3c5d1e8b42dce0faec58e08c8f279c773271c49c..175a84f6b316c4854ac9bc6fdb34e6317366c094 100644 (file)
@@ -277,15 +277,14 @@ PowerLiveProcess::setSyscallArg(ThreadContext *tc,
 }
 
 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());
 }
index 456b8b94aeed2e8c02b9c29ceaacf600e97c279f..06b0d18b382486836b7b8f71bbd0e14fbd767dce 100644 (file)
@@ -532,26 +532,25 @@ Sparc64LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val)
 }
 
 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);
index bf7669cdfa5d4eff12cf9280f3da5fb6816d8202..95a7f9998d02db0d8bbbe9f23691c52a62a7f54d 100644 (file)
@@ -678,9 +678,9 @@ I386LiveProcess::argsInit(int intSize, int pageSize)
 }
 
 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
index 935193e7f9a0a1b8337892bf3496492eaf353090..61ba3295531b8d5e4cc81937ef38486cbf7989bc 100644 (file)
@@ -69,7 +69,7 @@ SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc)
     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);
@@ -366,7 +366,7 @@ readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc,
     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);
@@ -390,7 +390,7 @@ unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
 
     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);
@@ -407,7 +407,7 @@ mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
 
     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);
@@ -864,7 +864,7 @@ accessFunc(SyscallDesc *desc, int callnum, LiveProcess *p, ThreadContext *tc,
 {
     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);
index 385ff55db1426780fc202bf300a045a6d28ed626..547d7661076cd5cb219cc4501d503b5648fb050a 100644 (file)
 
 #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 <class T>
-    SyscallReturn(T v, bool s)
+
+    /// 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() {}
+
+    /// Was the system call successful?
+    bool successful() const
     {
-        retval = (uint64_t)v;
-        success = s;
+        return (value >= 0 || value <= -4096);
     }
 
-    template <class T>
-    SyscallReturn(T v)
+    /// The return value
+    int64_t returnValue() const
     {
-        success = (v >= 0);
-        retval = (uint64_t)v;
+        assert(successful());
+        return value;
     }
 
-    ~SyscallReturn() {}
+    /// The errno value
+    int errnoValue() const
+    {
+        assert(!successful());
+        return -value;
+    }
 
-    SyscallReturn& operator=(const SyscallReturn& s)
+    /// The encoded value (as described above)
+    int64_t encodedValue() const
     {
-        retval = s.retval;
-        success = s.success;
-        return *this;
+        return value;
     }
 
-    bool successful() { return success; }
-    uint64_t value() { return retval; }
+  private:
 
-    private:
-    uint64_t retval;
-    bool success;
+    int64_t value;
 };
 
 #endif