arch-riscv,sim-se: Support RV32 register ABI call
1. Add RegABI32, SyscallABI32 2. Support parse function arguments to host and save result to registers 3. Add write to ThreadPointerReg in archClone 4. Support RV32 M5Op syscall Change-Id: Ie327b517f41b5d633d2741b6abb5be955281c838 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/65532 Tested-by: kokoro <noreply+kokoro@google.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Reviewed-by: Yu-hsin Wang <yuhsingw@google.com> Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
This commit is contained in:
@@ -38,8 +38,12 @@
|
||||
def format M5Op() {{
|
||||
iop = InstObjParams(name, Name, 'PseudoOp', '''
|
||||
uint64_t result;
|
||||
pseudo_inst::pseudoInst<RegABI64>(xc->tcBase(), M5FUNC, result);
|
||||
a0 = result''',
|
||||
if (machInst.rv_type == RV32) {
|
||||
pseudo_inst::pseudoInst<RegABI32>(xc->tcBase(), M5FUNC, result);
|
||||
} else {
|
||||
pseudo_inst::pseudoInst<RegABI64>(xc->tcBase(), M5FUNC, result);
|
||||
}
|
||||
a0 = rvSext(result)''',
|
||||
['IsNonSpeculative', 'IsSerializeAfter'])
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
|
||||
@@ -371,8 +371,10 @@ class RiscvLinux32 : public RiscvLinux, public OpenFlagTable<RiscvLinux32>
|
||||
uint64_t stack, uint64_t tls)
|
||||
{
|
||||
ctc->getIsaPtr()->copyRegsFrom(ptc);
|
||||
if (flags & TGT_CLONE_SETTLS)
|
||||
ctc->setReg(RiscvISA::ThreadPointerReg, sext<32>(tls));
|
||||
if (stack)
|
||||
ctc->setReg(RiscvISA::StackPointerReg, stack);
|
||||
ctc->setReg(RiscvISA::StackPointerReg, sext<32>(stack));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ unameFunc32(SyscallDesc *desc, ThreadContext *tc, VPtr<Linux::utsname> name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SyscallDescTable<SEWorkload::SyscallABI> EmuLinux::syscallDescs64 = {
|
||||
SyscallDescTable<SEWorkload::SyscallABI64> EmuLinux::syscallDescs64 = {
|
||||
{ 0, "io_setup" },
|
||||
{ 1, "io_destroy" },
|
||||
{ 2, "io_submit" },
|
||||
@@ -462,7 +462,7 @@ SyscallDescTable<SEWorkload::SyscallABI> EmuLinux::syscallDescs64 = {
|
||||
{ 2011, "getmainvars" }
|
||||
};
|
||||
|
||||
SyscallDescTable<SEWorkload::SyscallABI> EmuLinux::syscallDescs32 = {
|
||||
SyscallDescTable<SEWorkload::SyscallABI32> EmuLinux::syscallDescs32 = {
|
||||
{ 0, "io_setup" },
|
||||
{ 1, "io_destroy" },
|
||||
{ 2, "io_submit" },
|
||||
|
||||
@@ -47,10 +47,10 @@ class EmuLinux : public SEWorkload
|
||||
protected:
|
||||
|
||||
/// 64 bit syscall descriptors, indexed by call number.
|
||||
static SyscallDescTable<SEWorkload::SyscallABI> syscallDescs64;
|
||||
static SyscallDescTable<SEWorkload::SyscallABI64> syscallDescs64;
|
||||
|
||||
/// 32 bit syscall descriptors, indexed by call number.
|
||||
static SyscallDescTable<SEWorkload::SyscallABI> syscallDescs32;
|
||||
static SyscallDescTable<SEWorkload::SyscallABI32> syscallDescs32;
|
||||
|
||||
public:
|
||||
using Params = RiscvEmuLinuxParams;
|
||||
|
||||
@@ -39,5 +39,11 @@ const std::vector<RegId> RegABI64::ArgumentRegs = {
|
||||
int_reg::A4, int_reg::A5, int_reg::A6
|
||||
};
|
||||
|
||||
const std::vector<RegId> RegABI32::ArgumentRegs = {
|
||||
int_reg::A0, int_reg::A1, int_reg::A2, int_reg::A3,
|
||||
int_reg::A4, int_reg::A5, int_reg::A6
|
||||
};
|
||||
|
||||
|
||||
} // namespace RiscvISA
|
||||
} // namespace gem5
|
||||
|
||||
@@ -44,7 +44,36 @@ struct RegABI64 : public GenericSyscallABI64
|
||||
static const std::vector<RegId> ArgumentRegs;
|
||||
};
|
||||
|
||||
struct RegABI32 : public GenericSyscallABI32
|
||||
{
|
||||
static const std::vector<RegId> ArgumentRegs;
|
||||
};
|
||||
|
||||
} // namespace RiscvISA
|
||||
|
||||
namespace guest_abi
|
||||
{
|
||||
|
||||
// This method will be used if the size of argument type of function is
|
||||
// greater than 4 for Riscv 32.
|
||||
template <typename ABI, typename Arg>
|
||||
struct Argument<ABI, Arg,
|
||||
typename std::enable_if_t<
|
||||
std::is_base_of_v<RiscvISA::RegABI32, ABI> &&
|
||||
std::is_integral_v<Arg> &&
|
||||
ABI::template IsWideV<Arg>>>
|
||||
{
|
||||
static Arg
|
||||
get(ThreadContext *tc, typename ABI::State &state)
|
||||
{
|
||||
panic_if(state >= ABI::ArgumentRegs.size(),
|
||||
"Ran out of syscall argument registers.");
|
||||
return bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
#endif // __ARCH_RISCV_REG_ABI_HH__
|
||||
|
||||
@@ -60,8 +60,8 @@ class SEWorkload : public gem5::SEWorkload
|
||||
|
||||
loader::Arch getArch() const override { return loader::Riscv64; }
|
||||
|
||||
//FIXME RISCV needs to handle 64 bit arguments in its 32 bit ISA.
|
||||
using SyscallABI = RegABI64;
|
||||
using SyscallABI64 = RegABI64;
|
||||
using SyscallABI32 = RegABI32;
|
||||
};
|
||||
|
||||
} // namespace RiscvISA
|
||||
@@ -70,7 +70,7 @@ namespace guest_abi
|
||||
{
|
||||
|
||||
template <>
|
||||
struct Result<RiscvISA::SEWorkload::SyscallABI, SyscallReturn>
|
||||
struct Result<RiscvISA::SEWorkload::SyscallABI64, SyscallReturn>
|
||||
{
|
||||
static void
|
||||
store(ThreadContext *tc, const SyscallReturn &ret)
|
||||
@@ -85,6 +85,22 @@ struct Result<RiscvISA::SEWorkload::SyscallABI, SyscallReturn>
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Result<RiscvISA::SEWorkload::SyscallABI32, SyscallReturn>
|
||||
{
|
||||
static void
|
||||
store(ThreadContext *tc, const SyscallReturn &ret)
|
||||
{
|
||||
if (ret.successful()) {
|
||||
// no error
|
||||
tc->setReg(RiscvISA::ReturnValueReg, sext<32>(ret.returnValue()));
|
||||
} else {
|
||||
// got an error, return details
|
||||
tc->setReg(RiscvISA::ReturnValueReg, sext<32>(ret.encodedValue()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace guest_abi
|
||||
} // namespace gem5
|
||||
|
||||
|
||||
Reference in New Issue
Block a user