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>
}
tc->setIntReg(ReturnValueReg, sysret.encodedValue());
+ if (sysret.count() > 1)
+ tc->setIntReg(SyscallPseudoReturnReg, sysret.value2());
}
void
}
tc->setIntReg(ReturnValueReg, sysret.encodedValue());
+ if (sysret.count() > 1)
+ tc->setIntReg(SyscallPseudoReturnReg, sysret.value2());
}
tc->setIntReg(SyscallSuccessReg, (uint32_t)(-1));
tc->setIntReg(ReturnValueReg, sysret.errnoValue());
}
+ if (sysret.count() > 1)
+ tc->setIntReg(SyscallPseudoReturnReg, sysret.value2());
}
val = bits(val, 31, 0);
tc->setIntReg(ReturnValueReg, val);
}
+ if (sysret.count() > 1)
+ tc->setIntReg(SyscallPseudoReturnReg, sysret.value2());
}
// not getting a unique value.
auto process = tc->getProcessPtr();
- tc->setIntReg(SyscallPseudoReturnReg, process->ppid());
- return process->pid();
+ return SyscallReturn(process->pid(), process->ppid());
}
// 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());
}
/// 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
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
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