From 01d41c76a48fcfeecdf01c559b4674ae5dcacb23 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 7 Dec 2019 07:28:14 -0800 Subject: [PATCH] arm: Use an ARM specific GuestABI for ARM system calls. Change-Id: I2d0d0a563355f43ed791ba2f2a1894e303cca994 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23448 Reviewed-by: Bobby R. Bruce Maintainer: Gabe Black Tested-by: kokoro --- src/arch/arm/freebsd/process.cc | 4 ++-- src/arch/arm/freebsd/process.hh | 40 +++++++++++++++++++++++++++++++++ src/arch/arm/linux/process.cc | 8 +++---- src/arch/arm/linux/process.hh | 32 ++++++++++++++++++++++++++ src/arch/arm/process.cc | 8 +++++++ src/arch/arm/process.hh | 36 +++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 6 deletions(-) diff --git a/src/arch/arm/freebsd/process.cc b/src/arch/arm/freebsd/process.cc index 58edefc47..e384e6aad 100644 --- a/src/arch/arm/freebsd/process.cc +++ b/src/arch/arm/freebsd/process.cc @@ -131,7 +131,7 @@ sysctlFunc(SyscallDesc *desc, int callnum, ThreadContext *tc, } #endif -static SyscallDescABI syscallDescs32[] = { +static SyscallDescABI syscallDescs32[] = { /* 0 */ { "unused#000" }, /* 1 */ { "unused#001" }, /* 2 */ { "unused#002" }, @@ -682,7 +682,7 @@ static SyscallDescABI syscallDescs32[] = { /* 547 */ { "unused#547" }, }; -static SyscallDescABI syscallDescs64[] = { +static SyscallDescABI syscallDescs64[] = { /* 0 */ { "unused#000" }, /* 1 */ { "exit", exitFunc }, /* 2 */ { "unused#002" }, diff --git a/src/arch/arm/freebsd/process.hh b/src/arch/arm/freebsd/process.hh index 7f3d6fbb5..835acc5b2 100644 --- a/src/arch/arm/freebsd/process.hh +++ b/src/arch/arm/freebsd/process.hh @@ -52,8 +52,40 @@ class ArmFreebsdProcessBits }; std::vector syscallTables; + + struct SyscallABI {}; +}; + +namespace GuestABI +{ + +template +struct Result::value>::type> +{ + static void + store(ThreadContext *tc, const SyscallReturn &ret) + { + if (ret.suppressed() || ret.needsRetry()) + return; + + RegVal val; + if (ret.successful()) { + tc->setCCReg(ArmISA::CCREG_C, 0); + val = ret.returnValue(); + } else { + tc->setCCReg(ArmISA::CCREG_C, 1); + val = ret.encodedValue(); + } + tc->setIntReg(ArmISA::ReturnValueReg, val); + if (ret.count() > 1) + tc->setIntReg(ArmISA::SyscallPseudoReturnReg, ret.value2()); + } }; +} // namespace GuestABI + /// A process with emulated Arm/Freebsd syscalls. class ArmFreebsdProcess32 : public ArmProcess32, public ArmFreebsdProcessBits { @@ -72,6 +104,10 @@ class ArmFreebsdProcess32 : public ArmProcess32, public ArmFreebsdProcessBits static const Addr commPage; SyscallDesc* getDesc(int callnum) override; + + struct SyscallABI : public ArmProcess32::SyscallABI, + public ArmFreebsdProcessBits::SyscallABI + {}; }; /// A process with emulated Arm/Freebsd syscalls. @@ -84,6 +120,10 @@ class ArmFreebsdProcess64 : public ArmProcess64, public ArmFreebsdProcessBits void initState() override; void syscall(ThreadContext *tc, Fault *fault) override; SyscallDesc* getDesc(int callnum) override; + + struct SyscallABI : public ArmProcess64::SyscallABI, + public ArmFreebsdProcessBits::SyscallABI + {}; }; #endif // __ARCH_ARM_FREEBSD_PROCESS_HH__ diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index 6ed37b048..03b85beec 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -151,7 +151,7 @@ setTLSFunc64(SyscallDesc *desc, int callnum, ThreadContext *tc, return 0; } -static SyscallDescABI syscallDescs32[] = { +static SyscallDescABI syscallDescs32[] = { /* 0 */ { "syscall" }, /* 1 */ { "exit", exitFunc }, /* 2 */ { "fork" }, @@ -528,7 +528,7 @@ static SyscallDescABI syscallDescs32[] = { /* 365 */ { "sys_recvmmsg" }, }; -static SyscallDescABI syscallDescs64[] = { +static SyscallDescABI syscallDescs64[] = { /* 0 */ { "io_setup" }, /* 1 */ { "io_destroy" }, /* 2 */ { "io_submit" }, @@ -1619,7 +1619,7 @@ static SyscallDescABI syscallDescs64[] = { /* 1079 */ { "fork" } }; -static SyscallDescABI privSyscallDescs32[] = { +static SyscallDescABI privSyscallDescs32[] = { /* 1 */ { "breakpoint" }, /* 2 */ { "cacheflush" }, /* 3 */ { "usr26" }, @@ -1628,7 +1628,7 @@ static SyscallDescABI privSyscallDescs32[] = { }; // Indices 1, 3 and 4 are unallocated. -static SyscallDescABI privSyscallDescs64[] = { +static SyscallDescABI privSyscallDescs64[] = { /* 1 */ { "unallocated" }, /* 2 */ { "cacheflush" }, /* 3 */ { "unallocated" }, diff --git a/src/arch/arm/linux/process.hh b/src/arch/arm/linux/process.hh index e37aed19e..8204f4300 100644 --- a/src/arch/arm/linux/process.hh +++ b/src/arch/arm/linux/process.hh @@ -60,8 +60,32 @@ class ArmLinuxProcessBits }; std::vector syscallTables; + + struct SyscallABI {}; }; +namespace GuestABI +{ + +template +struct Result::value>::type> +{ + static void + store(ThreadContext *tc, const SyscallReturn &ret) + { + if (ret.suppressed() || ret.needsRetry()) + return; + + tc->setIntReg(ArmISA::ReturnValueReg, ret.encodedValue()); + if (ret.count() > 1) + tc->setIntReg(ArmISA::SyscallPseudoReturnReg, ret.value2()); + } +}; + +} // namespace GuestABI + /// A process with emulated Arm/Linux syscalls. class ArmLinuxProcess32 : public ArmProcess32, public ArmLinuxProcessBits { @@ -80,6 +104,10 @@ class ArmLinuxProcess32 : public ArmProcess32, public ArmLinuxProcessBits static const Addr commPage; SyscallDesc* getDesc(int callnum) override; + + struct SyscallABI : public ArmProcess32::SyscallABI, + public ArmLinuxProcessBits::SyscallABI + {}; }; /// A process with emulated Arm/Linux syscalls. @@ -92,6 +120,10 @@ class ArmLinuxProcess64 : public ArmProcess64, public ArmLinuxProcessBits void initState() override; void syscall(ThreadContext *tc, Fault *fault) override; SyscallDesc* getDesc(int callnum) override; + + struct SyscallABI : public ArmProcess64::SyscallABI, + public ArmLinuxProcessBits::SyscallABI + {}; }; #endif // __ARM_LINUX_PROCESS_HH__ diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index bce354e70..7eb263dce 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -470,6 +470,14 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex) memState->setStackMin(roundDown(memState->getStackMin(), pageSize)); } +const std::vector ArmProcess32::SyscallABI::ArgumentRegs = { + 0, 1, 2, 3, 4, 5, 6 +}; + +const std::vector ArmProcess64::SyscallABI::ArgumentRegs = { + 0, 1, 2, 3, 4, 5, 6 +}; + RegVal ArmProcess32::getSyscallArg(ThreadContext *tc, int &i) { diff --git a/src/arch/arm/process.hh b/src/arch/arm/process.hh index cc9e39d65..1650ff680 100644 --- a/src/arch/arm/process.hh +++ b/src/arch/arm/process.hh @@ -48,6 +48,7 @@ #include "base/loader/object_file.hh" #include "mem/page_table.hh" #include "sim/process.hh" +#include "sim/syscall_abi.hh" class ObjectFile; @@ -89,8 +90,38 @@ class ArmProcess32 : public ArmProcess RegVal getSyscallArg(ThreadContext *tc, int &i) override; void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value) override; + + struct SyscallABI : public GenericSyscallABI32 + { + static const std::vector ArgumentRegs; + }; +}; + +namespace GuestABI +{ + +template +struct Argument::value && + ABI::template IsWide::value>::type> +{ + static Arg + get(ThreadContext *tc, typename ABI::Position &position) + { + // 64 bit arguments are passed starting in an even register. + if (position % 2) + position++; + panic_if(position + 1 >= ABI::ArgumentRegs.size(), + "Ran out of syscall argument registers."); + auto low = ABI::ArgumentRegs[position++]; + auto high = ABI::ArgumentRegs[position++]; + return (Arg)ABI::mergeRegs(tc, low, high); + } }; +} // namespace GuestABI + class ArmProcess64 : public ArmProcess { protected: @@ -108,6 +139,11 @@ class ArmProcess64 : public ArmProcess RegVal getSyscallArg(ThreadContext *tc, int &i) override; void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value) override; + + struct SyscallABI : public GenericSyscallABI64 + { + static const std::vector ArgumentRegs; + }; }; #endif // __ARM_PROCESS_HH__ -- 2.30.2