diff --git a/src/arch/arm/reg_abi.hh b/src/arch/arm/reg_abi.hh index e892166c5e..6bdc8b36c1 100644 --- a/src/arch/arm/reg_abi.hh +++ b/src/arch/arm/reg_abi.hh @@ -31,6 +31,7 @@ #include #include "base/logging.hh" +#include "sim/pseudo_inst.hh" #include "sim/syscall_abi.hh" namespace gem5 @@ -54,11 +55,13 @@ struct RegABI64 : public GenericSyscallABI64 namespace guest_abi { +using namespace pseudo_inst; + template struct Argument && - std::is_integral_v && + (std::is_integral_v || std::is_same::value) && ABI::template IsWideV>> { static Arg @@ -71,7 +74,8 @@ struct Argument(&merge); } }; diff --git a/src/arch/arm/semihosting.hh b/src/arch/arm/semihosting.hh index 557eb76636..221c0ce3cb 100644 --- a/src/arch/arm/semihosting.hh +++ b/src/arch/arm/semihosting.hh @@ -51,6 +51,7 @@ #include "mem/port_proxy.hh" #include "sim/core.hh" #include "sim/guest_abi.hh" +#include "sim/pseudo_inst.hh" #include "sim/sim_object.hh" namespace gem5 @@ -602,28 +603,37 @@ std::ostream &operator << ( namespace guest_abi { +using namespace pseudo_inst; + template struct Argument>> + typename std::enable_if_t< + (std::is_integral_v || std::is_same::value)>> { static Arg get(ThreadContext *tc, ArmSemihosting::Abi64::State &state) { - return state.get(tc); + auto arg = state.get(tc); + return *reinterpret_cast(&arg); } }; template struct Argument>> + typename std::enable_if_t< + (std::is_integral_v || std::is_same::value)>> { static Arg get(ThreadContext *tc, ArmSemihosting::Abi32::State &state) { - if (std::is_signed_v) - return sext<32>(state.get(tc)); - else - return state.get(tc); + if (std::is_signed_v) { + auto arg = sext<32>(state.get(tc)); + return *reinterpret_cast(&arg); + } + else { + auto arg = state.get(tc); + return *reinterpret_cast(&arg); + } } }; diff --git a/src/arch/riscv/reg_abi.hh b/src/arch/riscv/reg_abi.hh index 4c965321f7..6f1c8cbc6c 100644 --- a/src/arch/riscv/reg_abi.hh +++ b/src/arch/riscv/reg_abi.hh @@ -54,8 +54,10 @@ struct RegABI32 : public GenericSyscallABI32 namespace guest_abi { +using namespace pseudo_inst; + // This method will be used if the size of argument type of function is -// greater than 4 for Riscv 32. +// greater than 4 byte for Riscv 32. template struct Argument= ABI::ArgumentRegs.size(), "Ran out of syscall argument registers."); - return bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); + + auto low = ABI::ArgumentRegs[state++]; + auto high = ABI::ArgumentRegs[state++]; + return (Arg)ABI::mergeRegs(tc, low, high); + } +}; + +// This method will be used for Riscv 32 pointers. +template +struct Argument && + std::is_same::value && + ABI::template IsWideV>> +{ + static Arg + get(ThreadContext *tc, typename ABI::State &state) + { + panic_if(state >= ABI::ArgumentRegs.size(), + "Ran out of syscall argument registers."); + + auto arg = bits(tc->getReg(ABI::ArgumentRegs[state++]), 31, 0); + return *reinterpret_cast(&arg); } }; diff --git a/src/arch/sparc/pseudo_inst_abi.hh b/src/arch/sparc/pseudo_inst_abi.hh index 989f0e7dfc..58b64d805a 100644 --- a/src/arch/sparc/pseudo_inst_abi.hh +++ b/src/arch/sparc/pseudo_inst_abi.hh @@ -31,6 +31,7 @@ #include "arch/sparc/regs/int.hh" #include "cpu/thread_context.hh" #include "sim/guest_abi.hh" +#include "sim/pseudo_inst.hh" namespace gem5 { @@ -43,6 +44,8 @@ struct SparcPseudoInstABI namespace guest_abi { +using namespace pseudo_inst; + template struct Result { @@ -67,6 +70,18 @@ struct Argument } }; +template <> +struct Argument +{ + static GuestAddr + get(ThreadContext *tc, SparcPseudoInstABI::State &state) + { + panic_if(state >= 6, "Too many psuedo inst arguments."); + auto arg = tc->getReg(SparcISA::int_reg::o(state++)); + return *reinterpret_cast(&arg); + } +}; + } // namespace guest_abi } // namespace gem5 diff --git a/src/arch/x86/pseudo_inst_abi.hh b/src/arch/x86/pseudo_inst_abi.hh index e465c7abd5..0c098f16e2 100644 --- a/src/arch/x86/pseudo_inst_abi.hh +++ b/src/arch/x86/pseudo_inst_abi.hh @@ -37,6 +37,7 @@ #include "arch/x86/regs/int.hh" #include "sim/guest_abi.hh" +#include "sim/pseudo_inst.hh" namespace gem5 { @@ -49,6 +50,8 @@ struct X86PseudoInstABI namespace guest_abi { +using namespace pseudo_inst; + template struct Result { @@ -84,5 +87,28 @@ struct Argument } }; +template <> +struct Argument +{ + static GuestAddr + get(ThreadContext *tc, X86PseudoInstABI::State &state) + { + // The first 6 integer arguments are passed in registers, the rest + // are passed on the stack. + + panic_if(state >= 6, "Too many psuedo inst arguments."); + + using namespace X86ISA; + + constexpr RegId int_reg_map[] = { + int_reg::Rdi, int_reg::Rsi, int_reg::Rdx, + int_reg::Rcx, int_reg::R8, int_reg::R9 + }; + + auto arg = tc->getReg(int_reg_map[state++]); + return *reinterpret_cast(&arg); + } +}; + } // namespace guest_abi } // namespace gem5 diff --git a/src/sim/guest_abi/layout.hh b/src/sim/guest_abi/layout.hh index 4d469b177c..3ea01c168c 100644 --- a/src/sim/guest_abi/layout.hh +++ b/src/sim/guest_abi/layout.hh @@ -169,7 +169,8 @@ template static Arg getArgument(ThreadContext *tc, typename ABI::State &state) { - return Argument::get(tc, state); + auto arg = Argument::get(tc, state); + return *reinterpret_cast(&arg); } } // namespace guest_abi diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 29caba6661..084be5a419 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -256,27 +256,27 @@ loadsymbol(ThreadContext *tc) } void -addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) +addsymbol(ThreadContext *tc, GuestAddr addr, GuestAddr symbolAddr) { DPRINTF(PseudoInst, "pseudo_inst::addsymbol(0x%x, 0x%x)\n", - addr, symbolAddr); + addr.addr, symbolAddr.addr); std::string symbol; TranslatingPortProxy fs_proxy(tc); SETranslatingPortProxy se_proxy(tc); PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy; - virt_proxy.readString(symbol, symbolAddr); + virt_proxy.readString(symbol, symbolAddr.addr); - DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); + DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr.addr); tc->getSystemPtr()->workload->insertSymbol( { loader::Symbol::Binding::Global, - loader::Symbol::SymbolType::Function, symbol, addr } + loader::Symbol::SymbolType::Function, symbol, addr.addr } ); loader::debugSymbolTable.insert( { loader::Symbol::Binding::Global, - loader::Symbol::SymbolType::Function, symbol, addr } + loader::Symbol::SymbolType::Function, symbol, addr.addr } ); } @@ -368,10 +368,10 @@ m5checkpoint(ThreadContext *tc, Tick delay, Tick period) } uint64_t -readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) +readfile(ThreadContext *tc, GuestAddr vaddr, uint64_t len, uint64_t offset) { DPRINTF(PseudoInst, "pseudo_inst::readfile(0x%x, 0x%x, 0x%x)\n", - vaddr, len, offset); + vaddr.addr, len, offset); const std::string &file = tc->getSystemPtr()->params().readfile; if (file.empty()) { @@ -404,17 +404,17 @@ readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) SETranslatingPortProxy se_proxy(tc); PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy; - virt_proxy.writeBlob(vaddr, buf, result); + virt_proxy.writeBlob(vaddr.addr, buf, result); delete [] buf; return result; } uint64_t -writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset, - Addr filename_addr) +writefile(ThreadContext *tc, GuestAddr vaddr, uint64_t len, uint64_t offset, + GuestAddr filename_addr) { DPRINTF(PseudoInst, "pseudo_inst::writefile(0x%x, 0x%x, 0x%x, 0x%x)\n", - vaddr, len, offset, filename_addr); + vaddr.addr, len, offset, filename_addr.addr); // copy out target filename std::string filename; @@ -422,7 +422,7 @@ writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset, SETranslatingPortProxy se_proxy(tc); PortProxy &virt_proxy = FullSystem ? fs_proxy : se_proxy; - virt_proxy.readString(filename, filename_addr); + virt_proxy.readString(filename, filename_addr.addr); OutputStream *out; if (offset == 0) { @@ -448,7 +448,7 @@ writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset, // copy out data and write to file char *buf = new char[len]; - virt_proxy.readBlob(vaddr, buf, len); + virt_proxy.readBlob(vaddr.addr, buf, len); os->write(buf, len); if (os->fail() || os->bad()) panic("Error while doing writefile!\n"); diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index ba15370c55..57b5ae23e6 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -64,18 +64,29 @@ decodeAddrOffset(Addr offset, uint8_t &func) func = bits(offset, 15, 8); } +struct GuestAddr +{ + uint64_t addr; +}; + +inline std::ostream& +operator<<(std::ostream& os, const GuestAddr addr) +{ + return os << addr.addr; +} + void arm(ThreadContext *tc); void quiesce(ThreadContext *tc); void quiesceSkip(ThreadContext *tc); void quiesceNs(ThreadContext *tc, uint64_t ns); void quiesceCycles(ThreadContext *tc, uint64_t cycles); uint64_t quiesceTime(ThreadContext *tc); -uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, +uint64_t readfile(ThreadContext *tc, GuestAddr vaddr, uint64_t len, uint64_t offset); -uint64_t writefile(ThreadContext *tc, Addr vaddr, uint64_t len, - uint64_t offset, Addr filenameAddr); +uint64_t writefile(ThreadContext *tc, GuestAddr vaddr, uint64_t len, + uint64_t offset, GuestAddr filenameAddr); void loadsymbol(ThreadContext *xc); -void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr); +void addsymbol(ThreadContext *tc, GuestAddr addr, GuestAddr symbolAddr); uint64_t initParam(ThreadContext *xc, uint64_t key_str1, uint64_t key_str2); uint64_t rpns(ThreadContext *tc); void wakeCPU(ThreadContext *tc, uint64_t cpuid); @@ -95,6 +106,7 @@ void m5Syscall(ThreadContext *tc); void togglesync(ThreadContext *tc); void triggerWorkloadEvent(ThreadContext *tc); + /** * Execute a decoded M5 pseudo instruction * diff --git a/src/sim/syscall_abi.hh b/src/sim/syscall_abi.hh index 90dbd9747b..136555ea37 100644 --- a/src/sim/syscall_abi.hh +++ b/src/sim/syscall_abi.hh @@ -32,6 +32,7 @@ #include "base/types.hh" #include "cpu/thread_context.hh" #include "sim/guest_abi.hh" +#include "sim/pseudo_inst.hh" #include "sim/syscall_return.hh" namespace gem5 @@ -78,19 +79,22 @@ struct GenericSyscallABI32 : public GenericSyscallABI namespace guest_abi { +using namespace pseudo_inst; + // For 64 bit systems, return syscall args directly. template struct Argument && - std::is_integral_v>> + (std::is_integral_v || std::is_same::value)>> { static Arg get(ThreadContext *tc, typename ABI::State &state) { panic_if(state >= ABI::ArgumentRegs.size(), "Ran out of syscall argument registers."); - return tc->getReg(ABI::ArgumentRegs[state++]); + auto arg = tc->getReg(ABI::ArgumentRegs[state++]); + return *reinterpret_cast(&arg); } };