sim: enable pseudo instructions with varying pointer size

In this patch, Addr is subtituted by a struct wrapper (uint64_t) in the
pseudo instruction functions. This enables a correct argument handling
in systems where pointer size != 64 bit.

Change-Id: Ie84b43b4ab8e6c0d38c7b6b16e19fc043110681b
This commit is contained in:
Robert Hauser
2024-03-11 15:27:58 +00:00
parent 7ac9733199
commit de52f3614c
9 changed files with 128 additions and 32 deletions

View File

@@ -169,7 +169,8 @@ template <typename ABI, typename Arg>
static Arg
getArgument(ThreadContext *tc, typename ABI::State &state)
{
return Argument<ABI, Arg>::get(tc, state);
auto arg = Argument<ABI, Arg>::get(tc, state);
return *reinterpret_cast<Arg*>(&arg);
}
} // namespace guest_abi

View File

@@ -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");

View File

@@ -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
*

View File

@@ -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 <typename ABI, typename Arg>
struct Argument<ABI, Arg,
typename std::enable_if_t<
std::is_base_of_v<GenericSyscallABI64, ABI> &&
std::is_integral_v<Arg>>>
(std::is_integral_v<Arg> || std::is_same<Arg,GuestAddr>::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*>(&arg);
}
};