}
#endif
-static SyscallDescABI<DefaultSyscallABI> syscallDescs32[] = {
+static SyscallDescABI<ArmFreebsdProcess32::SyscallABI> syscallDescs32[] = {
/* 0 */ { "unused#000" },
/* 1 */ { "unused#001" },
/* 2 */ { "unused#002" },
/* 547 */ { "unused#547" },
};
-static SyscallDescABI<DefaultSyscallABI> syscallDescs64[] = {
+static SyscallDescABI<ArmFreebsdProcess64::SyscallABI> syscallDescs64[] = {
/* 0 */ { "unused#000" },
/* 1 */ { "exit", exitFunc },
/* 2 */ { "unused#002" },
};
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
{
static const Addr commPage;
SyscallDesc* getDesc(int callnum) override;
+
+ struct SyscallABI : public ArmProcess32::SyscallABI,
+ public ArmFreebsdProcessBits::SyscallABI
+ {};
};
/// A process with emulated Arm/Freebsd syscalls.
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__
return 0;
}
-static SyscallDescABI<DefaultSyscallABI> syscallDescs32[] = {
+static SyscallDescABI<ArmLinuxProcess32::SyscallABI> syscallDescs32[] = {
/* 0 */ { "syscall" },
/* 1 */ { "exit", exitFunc },
/* 2 */ { "fork" },
/* 365 */ { "sys_recvmmsg" },
};
-static SyscallDescABI<DefaultSyscallABI> syscallDescs64[] = {
+static SyscallDescABI<ArmLinuxProcess64::SyscallABI> syscallDescs64[] = {
/* 0 */ { "io_setup" },
/* 1 */ { "io_destroy" },
/* 2 */ { "io_submit" },
/* 1079 */ { "fork" }
};
-static SyscallDescABI<DefaultSyscallABI> privSyscallDescs32[] = {
+static SyscallDescABI<ArmLinuxProcess32::SyscallABI> privSyscallDescs32[] = {
/* 1 */ { "breakpoint" },
/* 2 */ { "cacheflush" },
/* 3 */ { "usr26" },
};
// Indices 1, 3 and 4 are unallocated.
-static SyscallDescABI<DefaultSyscallABI> privSyscallDescs64[] = {
+static SyscallDescABI<ArmLinuxProcess64::SyscallABI> privSyscallDescs64[] = {
/* 1 */ { "unallocated" },
/* 2 */ { "cacheflush" },
/* 3 */ { "unallocated" },
};
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
{
static const Addr commPage;
SyscallDesc* getDesc(int callnum) override;
+
+ struct SyscallABI : public ArmProcess32::SyscallABI,
+ public ArmLinuxProcessBits::SyscallABI
+ {};
};
/// A process with emulated Arm/Linux syscalls.
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__
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)
{
#include "base/loader/object_file.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
+#include "sim/syscall_abi.hh"
class ObjectFile;
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:
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__