From: Gabe Black Date: Sat, 7 Dec 2019 11:07:43 +0000 (-0800) Subject: sparc: Use a SPARC specific GuestABI for system calls. X-Git-Tag: v20.0.0.0~380 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=37d2204c5a4fc60ca9d34ba5e74b1a162426eb56;p=gem5.git sparc: Use a SPARC specific GuestABI for system calls. Change-Id: I41996cada5ccde7b265e5315829ac6690da8902f Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23447 Reviewed-by: Bobby R. Bruce Maintainer: Gabe Black Tested-by: kokoro --- diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh index 3b79b39fd..3543773aa 100644 --- a/src/arch/sparc/linux/process.hh +++ b/src/arch/sparc/linux/process.hh @@ -43,11 +43,11 @@ class SparcLinuxProcess { public: /// Array of syscall descriptors, indexed by call number. - static SyscallDescABI syscallDescs[]; + static SyscallDescABI syscallDescs[]; /// Array of 32 bit compatibility syscall descriptors, /// indexed by call number. - static SyscallDescABI syscall32Descs[]; + static SyscallDescABI 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 2c4992ccf..bb36d1e70 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -81,7 +81,8 @@ getresuidFunc(SyscallDesc *desc, int num, ThreadContext *tc, return 0; } -SyscallDescABI SparcLinuxProcess::syscall32Descs[] = { +SyscallDescABI + SparcLinuxProcess::syscall32Descs[] = { /* 0 */ { "restart_syscall" }, /* 1 */ { "exit", exitFunc }, // 32 bit /* 2 */ { "fork" }, @@ -387,7 +388,8 @@ SyscallDescABI SparcLinuxProcess::syscall32Descs[] = { const int SparcLinuxProcess::Num_Syscall32_Descs = sizeof(SparcLinuxProcess::syscall32Descs) / sizeof(SyscallDesc); -SyscallDescABI SparcLinuxProcess::syscallDescs[] = { +SyscallDescABI + 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 ce201d0b4..0104b1a58 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -48,8 +48,9 @@ using namespace std; using namespace SparcISA; -static const int FirstArgumentReg = 8; - +const std::vector SparcProcess::SyscallABI::ArgumentRegs = { + INTREG_O0, INTREG_O1, INTREG_O2, INTREG_O3, INTREG_O4, INTREG_O5 +}; SparcProcess::SparcProcess(ProcessParams *params, ObjectFile *objFile, Addr _StackBias) @@ -490,6 +491,8 @@ Sparc64Process::flushWindows(ThreadContext *tc) 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 f8660bddf..4bd99a834 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -34,10 +34,12 @@ #include #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 { @@ -67,8 +69,52 @@ class SparcProcess : public Process virtual void flushWindows(ThreadContext *tc) = 0; void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value) override; + + struct SyscallABI + { + static const std::vector ArgumentRegs; + }; }; +namespace GuestABI +{ + +template +struct Result::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: @@ -109,8 +155,35 @@ class Sparc32Process : public SparcProcess RegVal getSyscallArg(ThreadContext *tc, int &i) override; /// Explicitly import the otherwise hidden getSyscallArg using Process::getSyscallArg; + + struct SyscallABI : public GenericSyscallABI32, + public SparcProcess::SyscallABI + {}; }; +namespace GuestABI +{ + +template +struct Argument::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: @@ -150,6 +223,10 @@ class Sparc64Process : public SparcProcess RegVal getSyscallArg(ThreadContext *tc, int &i) override; /// 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 20fb3cf8f..bf34f58a5 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -87,7 +87,8 @@ unameFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, Addr utsname) } -SyscallDescABI SparcSolarisProcess::syscallDescs[] = { +SyscallDescABI + 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 9dac37868..0f658ba24 100644 --- a/src/arch/sparc/solaris/process.hh +++ b/src/arch/sparc/solaris/process.hh @@ -51,7 +51,7 @@ class SparcSolarisProcess : public Sparc64Process void syscall(ThreadContext *tc, Fault *fault) override; /// Array of syscall descriptors, indexed by call number. - static SyscallDescABI syscallDescs[]; + static SyscallDescABI syscallDescs[]; const int Num_Syscall_Descs; };