sim: Make SyscallReturn handle extra/"pseudo" return registers.
authorGabe Black <gabeblack@google.com>
Sun, 8 Dec 2019 01:45:44 +0000 (17:45 -0800)
committerGabe Black <gabeblack@google.com>
Thu, 12 Mar 2020 01:35:34 +0000 (01:35 +0000)
Avoid special casing them in the system calls themselves.

Change-Id: I735f8e6fdff164c66e3f1386aed3fc9b107ea45f
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23440
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Gabe Black <gabeblack@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/arm/process.cc
src/arch/mips/process.cc
src/arch/sparc/process.cc
src/sim/syscall_emul.cc
src/sim/syscall_return.hh

index 290e93bbedb90b3cfa7e7326d6efd0c2486c127f..bce354e704a9b18640a9fb9d89428846d0966bf2 100644 (file)
@@ -524,6 +524,8 @@ ArmProcess32::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
     }
 
     tc->setIntReg(ReturnValueReg, sysret.encodedValue());
+    if (sysret.count() > 1)
+        tc->setIntReg(SyscallPseudoReturnReg, sysret.value2());
 }
 
 void
@@ -541,4 +543,6 @@ ArmProcess64::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
     }
 
     tc->setIntReg(ReturnValueReg, sysret.encodedValue());
+    if (sysret.count() > 1)
+        tc->setIntReg(SyscallPseudoReturnReg, sysret.value2());
 }
index fb6c110b6faa1c678807326d8c44cba4e4f9d30e..b9385337b448ad6d28d1fb56589e0caaabc8005b 100644 (file)
@@ -208,4 +208,6 @@ MipsProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
         tc->setIntReg(SyscallSuccessReg, (uint32_t)(-1));
         tc->setIntReg(ReturnValueReg, sysret.errnoValue());
     }
+    if (sysret.count() > 1)
+        tc->setIntReg(SyscallPseudoReturnReg, sysret.value2());
 }
index bd3ca0064c616a9ed8fcae7c8476ed7281aed93c..884deb44f5d76e20a576457d4151e5517c95c967 100644 (file)
@@ -533,4 +533,6 @@ SparcProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
             val = bits(val, 31, 0);
         tc->setIntReg(ReturnValueReg, val);
     }
+    if (sysret.count() > 1)
+        tc->setIntReg(SyscallPseudoReturnReg, sysret.value2());
 }
index 4084009bab6ec953407d7c02b831001ae3464a3a..913a26591ac12ec3b830d72ea187d3d2952bd9c2 100644 (file)
@@ -977,8 +977,7 @@ getpidPseudoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
     // not getting a unique value.
 
     auto process = tc->getProcessPtr();
-    tc->setIntReg(SyscallPseudoReturnReg, process->ppid());
-    return process->pid();
+    return SyscallReturn(process->pid(), process->ppid());
 }
 
 
@@ -988,20 +987,17 @@ getuidPseudoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
     // Make up a UID and EUID... it shouldn't matter, and we want the
     // simulation to be deterministic.
 
-    // EUID goes in r20.
     auto process = tc->getProcessPtr();
-    tc->setIntReg(SyscallPseudoReturnReg, process->euid()); // EUID
-    return process->uid(); // UID
+    return SyscallReturn(process->uid(), process->euid());
 }
 
 
 SyscallReturn
 getgidPseudoFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
 {
-    // Get current group ID.  EGID goes in r20.
+    // Get current group ID.
     auto process = tc->getProcessPtr();
-    tc->setIntReg(SyscallPseudoReturnReg, process->egid()); // EGID
-    return process->gid();
+    return SyscallReturn(process->gid(), process->egid());
 }
 
 
index 4c7db82263eb7537f705324ab8b1d06876f342b3..7c6a0c68aa0dac3170afd85312361aed925093d6 100644 (file)
@@ -61,10 +61,16 @@ class SyscallReturn
     /// 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(int64_t v) : _value(v), _count(1) {}
 
     /// A SyscallReturn constructed with no value means don't return anything.
-    SyscallReturn() : suppressedFlag(true) {}
+    SyscallReturn() : _count(0) {}
+
+    /// A SyscallReturn constructed with two values means put the second value
+    /// in additional return registers as defined by the ABI, if they exist.
+    SyscallReturn(int64_t v1, int64_t v2) :
+        _value(v1), _value2(v2), _count(2)
+    {}
 
     /// Pseudo-constructor to create an instance with the retry flag set.
     static SyscallReturn
@@ -81,21 +87,24 @@ class SyscallReturn
     bool
     successful() const
     {
-        return (value >= 0 || value <= -4096);
+        return (_value >= 0 || _value <= -4096);
     }
 
     /// Does the syscall need to be retried?
     bool needsRetry() const { return retryFlag; }
 
     /// Should returning this value be suppressed?
-    bool suppressed() const { return suppressedFlag; }
+    bool suppressed() const { return _count == 0; }
+
+    /// How many values did the syscall attempt to return?
+    int count() const { return _count; }
 
     /// The return value
     int64_t
     returnValue() const
     {
         assert(successful());
-        return value;
+        return _value;
     }
 
     /// The errno value
@@ -103,17 +112,18 @@ class SyscallReturn
     errnoValue() const
     {
         assert(!successful());
-        return -value;
+        return -_value;
     }
 
     /// The encoded value (as described above)
-    int64_t encodedValue() const { return value; }
+    int64_t encodedValue() const { return _value; }
+    int64_t value2() const { return _value2; }
 
   private:
-    int64_t value;
+    int64_t _value, _value2;
+    int _count;
 
     bool retryFlag = false;
-    bool suppressedFlag =  false;
 };
 
 #endif