Gabe Black has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/23447 )
Change subject: sparc: Use a SPARC specific GuestABI for system calls.
......................................................................
sparc: Use a SPARC specific GuestABI for system calls.
Change-Id: I41996cada5ccde7b265e5315829ac6690da8902f
---
M src/arch/sparc/linux/process.hh
M src/arch/sparc/linux/syscalls.cc
M src/arch/sparc/process.cc
M src/arch/sparc/process.hh
M src/arch/sparc/solaris/process.cc
M src/arch/sparc/solaris/process.hh
6 files changed, 91 insertions(+), 8 deletions(-)
diff --git a/src/arch/sparc/linux/process.hh
b/src/arch/sparc/linux/process.hh
index b7a4117..f16cc19 100644
--- a/src/arch/sparc/linux/process.hh
+++ b/src/arch/sparc/linux/process.hh
@@ -45,11 +45,11 @@
{
public:
/// Array of syscall descriptors, indexed by call number.
- static SyscallDescABI<DefaultSyscallABI> syscallDescs[];
+ static SyscallDescABI<Sparc64Process::SyscallABI> syscallDescs[];
/// Array of 32 bit compatibility syscall descriptors,
/// indexed by call number.
- static SyscallDescABI<DefaultSyscallABI> syscall32Descs[];
+ static SyscallDescABI<Sparc32Process::SyscallABI> syscall32Descs[];
SyscallDesc* getDesc(int callnum);
SyscallDesc* getDesc32(int callnum);
diff --git a/src/arch/sparc/linux/syscalls.cc
b/src/arch/sparc/linux/syscalls.cc
index 6f8e646..1b8f400 100644
--- a/src/arch/sparc/linux/syscalls.cc
+++ b/src/arch/sparc/linux/syscalls.cc
@@ -83,7 +83,8 @@
return 0;
}
-SyscallDescABI<DefaultSyscallABI> SparcLinuxProcess::syscall32Descs[] = {
+SyscallDescABI<Sparc32Process::SyscallABI>
+ SparcLinuxProcess::syscall32Descs[] = {
/* 0 */ { "restart_syscall" },
/* 1 */ { "exit", exitFunc }, // 32 bit
/* 2 */ { "fork" },
@@ -389,7 +390,8 @@
const int SparcLinuxProcess::Num_Syscall32_Descs =
sizeof(SparcLinuxProcess::syscall32Descs) / sizeof(SyscallDesc);
-SyscallDescABI<DefaultSyscallABI> SparcLinuxProcess::syscallDescs[] = {
+SyscallDescABI<Sparc64Process::SyscallABI>
+ SparcLinuxProcess::syscallDescs[] = {
/* 0 */ { "restart_syscall" },
/* 1 */ { "exit", exitFunc },
/* 2 */ { "fork" },
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index d064de2..50167c7 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -51,8 +51,9 @@
using namespace std;
using namespace SparcISA;
-static const int FirstArgumentReg = 8;
-
+const std::vector<int> SparcProcess::SyscallABI::ArgumentRegs = {
+ INTREG_O0, INTREG_O1, INTREG_O2, INTREG_O3, INTREG_O4, INTREG_O5
+};
SparcProcess::SparcProcess(ProcessParams *params, ObjectFile *objFile,
Addr _StackBias)
@@ -493,6 +494,8 @@
tc->setMiscReg(MISCREG_CWP, origCWP);
}
+static const int FirstArgumentReg = 8;
+
RegVal
Sparc32Process::getSyscallArg(ThreadContext *tc, int &i)
{
diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh
index 2e5379b..d3d6866 100644
--- a/src/arch/sparc/process.hh
+++ b/src/arch/sparc/process.hh
@@ -37,10 +37,12 @@
#include <vector>
#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/miscregs.hh"
#include "base/loader/object_file.hh"
#include "mem/page_table.hh"
#include "sim/byteswap.hh"
#include "sim/process.hh"
+#include "sim/syscall_abi.hh"
class SparcProcess : public Process
{
@@ -69,8 +71,52 @@
virtual void flushWindows(ThreadContext *tc) = 0;
void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
+
+ struct SyscallABI
+ {
+ static const std::vector<int> ArgumentRegs;
+ };
};
+namespace GuestABI
+{
+
+template <typename ABI>
+struct Result<ABI, SyscallReturn,
+ typename std::enable_if<std::is_base_of<
+ SparcProcess::SyscallABI, ABI>::value>::type>
+{
+ static void
+ store(ThreadContext *tc, const SyscallReturn &ret)
+ {
+ if (ret.suppressed() || ret.needsRetry())
+ return;
+
+ // 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.
+ SparcISA::PSTATE pstate =
+ tc->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE);
+ SparcISA::CCR ccr = tc->readIntReg(SparcISA::INTREG_CCR);
+ RegVal val;
+ if (ret.successful()) {
+ ccr.xcc.c = ccr.icc.c = 0;
+ val = ret.returnValue();
+ } else {
+ ccr.xcc.c = ccr.icc.c = 1;
+ val = ret.errnoValue();
+ }
+ tc->setIntReg(SparcISA::INTREG_CCR, ccr);
+ if (pstate.am)
+ val = bits(val, 31, 0);
+ tc->setIntReg(SparcISA::ReturnValueReg, val);
+ if (ret.count() == 2)
+ tc->setIntReg(SparcISA::SyscallPseudoReturnReg, ret.value2());
+ }
+};
+
+} // namespace GuestABI
+
class Sparc32Process : public SparcProcess
{
protected:
@@ -111,8 +157,35 @@
RegVal getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using Process::getSyscallArg;
+
+ struct SyscallABI : public GenericSyscallABI32,
+ public SparcProcess::SyscallABI
+ {};
};
+namespace GuestABI
+{
+
+template <typename Arg>
+struct Argument<Sparc32Process::SyscallABI, Arg,
+ typename std::enable_if<
+ Sparc32Process::SyscallABI::IsWide<Arg>::value>::type>
+{
+ using ABI = Sparc32Process::SyscallABI;
+
+ static Arg
+ get(ThreadContext *tc, typename ABI::Position &position)
+ {
+ panic_if(position + 1 >= ABI::ArgumentRegs.size(),
+ "Ran out of syscall argument registers.");
+ auto high = ABI::ArgumentRegs[position++];
+ auto low = ABI::ArgumentRegs[position++];
+ return (Arg)ABI::mergeRegs(tc, low, high);
+ }
+};
+
+} // namespace GuestABI
+
class Sparc64Process : public SparcProcess
{
protected:
@@ -152,6 +225,10 @@
RegVal getSyscallArg(ThreadContext *tc, int &i);
/// Explicitly import the otherwise hidden getSyscallArg
using Process::getSyscallArg;
+
+ struct SyscallABI : public GenericSyscallABI64,
+ public SparcProcess::SyscallABI
+ {};
};
#endif // __SPARC_PROCESS_HH__
diff --git a/src/arch/sparc/solaris/process.cc
b/src/arch/sparc/solaris/process.cc
index 84c332e..3255eee 100644
--- a/src/arch/sparc/solaris/process.cc
+++ b/src/arch/sparc/solaris/process.cc
@@ -89,7 +89,8 @@
}
-SyscallDescABI<DefaultSyscallABI> SparcSolarisProcess::syscallDescs[] = {
+SyscallDescABI<Sparc64Process::SyscallABI>
+ SparcSolarisProcess::syscallDescs[] = {
/* 0 */ { "syscall" },
/* 1 */ { "exit", exitFunc },
/* 2 */ { "fork" },
diff --git a/src/arch/sparc/solaris/process.hh
b/src/arch/sparc/solaris/process.hh
index 424b0ec..d04fcc4 100644
--- a/src/arch/sparc/solaris/process.hh
+++ b/src/arch/sparc/solaris/process.hh
@@ -53,7 +53,7 @@
void syscall(ThreadContext *tc, Fault *fault) override;
/// Array of syscall descriptors, indexed by call number.
- static SyscallDescABI<DefaultSyscallABI> syscallDescs[];
+ static SyscallDescABI<Sparc64Process::SyscallABI> syscallDescs[];
const int Num_Syscall_Descs;
};
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/23447
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I41996cada5ccde7b265e5315829ac6690da8902f
Gerrit-Change-Number: 23447
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabebl...@google.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev