From 9d606b80b628cfca1684bc79b4271615435f946c Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 7 Dec 2019 17:45:44 -0800 Subject: [PATCH] sim: Make SyscallReturn handle extra/"pseudo" return registers. 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 Maintainer: Gabe Black Tested-by: kokoro --- src/arch/arm/process.cc | 4 ++++ src/arch/mips/process.cc | 2 ++ src/arch/sparc/process.cc | 2 ++ src/sim/syscall_emul.cc | 12 ++++-------- src/sim/syscall_return.hh | 28 +++++++++++++++++++--------- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index 290e93bbe..bce354e70 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -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()); } diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index fb6c110b6..b9385337b 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -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()); } diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index bd3ca0064..884deb44f 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -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()); } diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 4084009ba..913a26591 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -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()); } diff --git a/src/sim/syscall_return.hh b/src/sim/syscall_return.hh index 4c7db8226..7c6a0c68a 100644 --- a/src/sim/syscall_return.hh +++ b/src/sim/syscall_return.hh @@ -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 -- 2.30.2