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 <bbruce@ucdavis.edu> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user