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 <bbruce@ucdavis.edu> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -131,7 +131,7 @@ sysctlFunc(SyscallDesc *desc, int callnum, ThreadContext *tc,
|
||||
}
|
||||
#endif
|
||||
|
||||
static SyscallDescABI<DefaultSyscallABI> syscallDescs32[] = {
|
||||
static SyscallDescABI<ArmFreebsdProcess32::SyscallABI> syscallDescs32[] = {
|
||||
/* 0 */ { "unused#000" },
|
||||
/* 1 */ { "unused#001" },
|
||||
/* 2 */ { "unused#002" },
|
||||
@@ -682,7 +682,7 @@ static SyscallDescABI<DefaultSyscallABI> syscallDescs32[] = {
|
||||
/* 547 */ { "unused#547" },
|
||||
};
|
||||
|
||||
static SyscallDescABI<DefaultSyscallABI> syscallDescs64[] = {
|
||||
static SyscallDescABI<ArmFreebsdProcess64::SyscallABI> syscallDescs64[] = {
|
||||
/* 0 */ { "unused#000" },
|
||||
/* 1 */ { "exit", exitFunc },
|
||||
/* 2 */ { "unused#002" },
|
||||
|
||||
@@ -52,8 +52,40 @@ class ArmFreebsdProcessBits
|
||||
};
|
||||
|
||||
std::vector<SyscallTable> syscallTables;
|
||||
|
||||
struct SyscallABI {};
|
||||
};
|
||||
|
||||
namespace GuestABI
|
||||
{
|
||||
|
||||
template <typename ABI>
|
||||
struct Result<ABI, SyscallReturn,
|
||||
typename std::enable_if<std::is_base_of<
|
||||
ArmFreebsdProcessBits::SyscallABI, ABI>::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__
|
||||
|
||||
@@ -151,7 +151,7 @@ setTLSFunc64(SyscallDesc *desc, int callnum, ThreadContext *tc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SyscallDescABI<DefaultSyscallABI> syscallDescs32[] = {
|
||||
static SyscallDescABI<ArmLinuxProcess32::SyscallABI> syscallDescs32[] = {
|
||||
/* 0 */ { "syscall" },
|
||||
/* 1 */ { "exit", exitFunc },
|
||||
/* 2 */ { "fork" },
|
||||
@@ -528,7 +528,7 @@ static SyscallDescABI<DefaultSyscallABI> syscallDescs32[] = {
|
||||
/* 365 */ { "sys_recvmmsg" },
|
||||
};
|
||||
|
||||
static SyscallDescABI<DefaultSyscallABI> syscallDescs64[] = {
|
||||
static SyscallDescABI<ArmLinuxProcess64::SyscallABI> syscallDescs64[] = {
|
||||
/* 0 */ { "io_setup" },
|
||||
/* 1 */ { "io_destroy" },
|
||||
/* 2 */ { "io_submit" },
|
||||
@@ -1619,7 +1619,7 @@ static SyscallDescABI<DefaultSyscallABI> syscallDescs64[] = {
|
||||
/* 1079 */ { "fork" }
|
||||
};
|
||||
|
||||
static SyscallDescABI<DefaultSyscallABI> privSyscallDescs32[] = {
|
||||
static SyscallDescABI<ArmLinuxProcess32::SyscallABI> privSyscallDescs32[] = {
|
||||
/* 1 */ { "breakpoint" },
|
||||
/* 2 */ { "cacheflush" },
|
||||
/* 3 */ { "usr26" },
|
||||
@@ -1628,7 +1628,7 @@ static SyscallDescABI<DefaultSyscallABI> privSyscallDescs32[] = {
|
||||
};
|
||||
|
||||
// Indices 1, 3 and 4 are unallocated.
|
||||
static SyscallDescABI<DefaultSyscallABI> privSyscallDescs64[] = {
|
||||
static SyscallDescABI<ArmLinuxProcess64::SyscallABI> privSyscallDescs64[] = {
|
||||
/* 1 */ { "unallocated" },
|
||||
/* 2 */ { "cacheflush" },
|
||||
/* 3 */ { "unallocated" },
|
||||
|
||||
@@ -60,8 +60,32 @@ class ArmLinuxProcessBits
|
||||
};
|
||||
|
||||
std::vector<SyscallTable> syscallTables;
|
||||
|
||||
struct SyscallABI {};
|
||||
};
|
||||
|
||||
namespace GuestABI
|
||||
{
|
||||
|
||||
template <typename ABI>
|
||||
struct Result<ABI, SyscallReturn,
|
||||
typename std::enable_if<std::is_base_of<
|
||||
ArmLinuxProcessBits::SyscallABI, ABI>::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__
|
||||
|
||||
@@ -470,6 +470,14 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex)
|
||||
memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
|
||||
}
|
||||
|
||||
const std::vector<int> ArmProcess32::SyscallABI::ArgumentRegs = {
|
||||
0, 1, 2, 3, 4, 5, 6
|
||||
};
|
||||
|
||||
const std::vector<int> ArmProcess64::SyscallABI::ArgumentRegs = {
|
||||
0, 1, 2, 3, 4, 5, 6
|
||||
};
|
||||
|
||||
RegVal
|
||||
ArmProcess32::getSyscallArg(ThreadContext *tc, int &i)
|
||||
{
|
||||
|
||||
@@ -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<int> ArgumentRegs;
|
||||
};
|
||||
};
|
||||
|
||||
namespace GuestABI
|
||||
{
|
||||
|
||||
template <typename ABI, typename Arg>
|
||||
struct Argument<ABI, Arg,
|
||||
typename std::enable_if<
|
||||
std::is_base_of<ArmProcess32::SyscallABI, ABI>::value &&
|
||||
ABI::template IsWide<Arg>::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<int> ArgumentRegs;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // __ARM_PROCESS_HH__
|
||||
|
||||
Reference in New Issue
Block a user