arch,cpu,mem,sim: Reimplement the SE translating proxy using the FS one.
The only functional difference between them was that the SE one might have optionally fixed up missing translations for demand paging. This lets us get rid of some code recreating the proxy ports in setProcessPtr since the SE translating port no longer keeps a copy of the process object pointer. Change-Id: Id97df1874f1de138ffd4f2dbb5846dda79d9e4ac Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/26550 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Matthew Poremba <matthew.poremba@amd.com> Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
@@ -410,8 +410,7 @@ ThreadContext::initMemProxies(::ThreadContext *tc)
|
||||
virtProxy.reset(new FSTranslatingPortProxy(tc));
|
||||
} else {
|
||||
assert(!virtProxy);
|
||||
virtProxy.reset(new SETranslatingPortProxy(
|
||||
_cpu->getSendFunctional(), getProcessPtr(),
|
||||
virtProxy.reset(new SETranslatingPortProxy(this,
|
||||
SETranslatingPortProxy::NextPage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,16 +404,16 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex)
|
||||
|
||||
//Write out the sentry void *
|
||||
IntType sentry_NULL = 0;
|
||||
initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
|
||||
initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
|
||||
|
||||
//Fix up the aux vectors which point to other data
|
||||
for (int i = auxv.size() - 1; i >= 0; i--) {
|
||||
if (auxv[i].type == M5_AT_PLATFORM) {
|
||||
auxv[i].val = platform_base;
|
||||
initVirtMem.writeString(platform_base, platform.c_str());
|
||||
initVirtMem->writeString(platform_base, platform.c_str());
|
||||
} else if (auxv[i].type == M5_AT_EXECFN) {
|
||||
auxv[i].val = aux_data_base;
|
||||
initVirtMem.writeString(aux_data_base, filename.c_str());
|
||||
initVirtMem->writeString(aux_data_base, filename.c_str());
|
||||
} else if (auxv[i].type == M5_AT_RANDOM) {
|
||||
auxv[i].val = aux_random_base;
|
||||
// Just leave the value 0, we don't want randomness
|
||||
@@ -423,20 +423,20 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex)
|
||||
//Copy the aux stuff
|
||||
Addr auxv_array_end = auxv_array_base;
|
||||
for (const auto &aux: auxv) {
|
||||
initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
|
||||
initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
|
||||
auxv_array_end += sizeof(aux);
|
||||
}
|
||||
//Write out the terminating zeroed auxillary vector
|
||||
const AuxVector<IntType> zero(0, 0);
|
||||
initVirtMem.write(auxv_array_end, zero);
|
||||
initVirtMem->write(auxv_array_end, zero);
|
||||
auxv_array_end += sizeof(zero);
|
||||
|
||||
copyStringArray(envp, envp_array_base, env_data_base,
|
||||
LittleEndianByteOrder, initVirtMem);
|
||||
LittleEndianByteOrder, *initVirtMem);
|
||||
copyStringArray(argv, argv_array_base, arg_data_base,
|
||||
LittleEndianByteOrder, initVirtMem);
|
||||
LittleEndianByteOrder, *initVirtMem);
|
||||
|
||||
initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
|
||||
initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
//Set the stack pointer register
|
||||
|
||||
@@ -159,24 +159,24 @@ MipsProcess::argsInit(int pageSize)
|
||||
|
||||
argc = htole((IntType)argc);
|
||||
|
||||
initVirtMem.writeBlob(memState->getStackMin(), &argc, intSize);
|
||||
initVirtMem->writeBlob(memState->getStackMin(), &argc, intSize);
|
||||
|
||||
copyStringArray(argv, argv_array_base, arg_data_base,
|
||||
LittleEndianByteOrder, initVirtMem);
|
||||
LittleEndianByteOrder, *initVirtMem);
|
||||
|
||||
copyStringArray(envp, envp_array_base, env_data_base,
|
||||
LittleEndianByteOrder, initVirtMem);
|
||||
LittleEndianByteOrder, *initVirtMem);
|
||||
|
||||
// Copy the aux vector
|
||||
Addr auxv_array_end = auxv_array_base;
|
||||
for (const auto &aux: auxv) {
|
||||
initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
|
||||
initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
|
||||
auxv_array_end += sizeof(aux);
|
||||
}
|
||||
|
||||
// Write out the terminating zeroed auxilliary vector
|
||||
const AuxVector<IntType> zero(0, 0);
|
||||
initVirtMem.write(auxv_array_end, zero);
|
||||
initVirtMem->write(auxv_array_end, zero);
|
||||
auxv_array_end += sizeof(zero);
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
|
||||
@@ -93,8 +93,8 @@ PowerProcess::argsInit(int intSize, int pageSize)
|
||||
uint64_t align = 16;
|
||||
|
||||
// load object file into target memory
|
||||
image.write(initVirtMem);
|
||||
interpImage.write(initVirtMem);
|
||||
image.write(*initVirtMem);
|
||||
interpImage.write(*initVirtMem);
|
||||
|
||||
//Setup the auxilliary vectors. These will already have endian conversion.
|
||||
//Auxilliary vectors are loaded only for elf formatted executables.
|
||||
@@ -227,36 +227,36 @@ PowerProcess::argsInit(int intSize, int pageSize)
|
||||
|
||||
//Write out the sentry void *
|
||||
uint32_t sentry_NULL = 0;
|
||||
initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
|
||||
initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
|
||||
|
||||
//Fix up the aux vectors which point to other data
|
||||
for (int i = auxv.size() - 1; i >= 0; i--) {
|
||||
if (auxv[i].type == M5_AT_PLATFORM) {
|
||||
auxv[i].val = platform_base;
|
||||
initVirtMem.writeString(platform_base, platform.c_str());
|
||||
initVirtMem->writeString(platform_base, platform.c_str());
|
||||
} else if (auxv[i].type == M5_AT_EXECFN) {
|
||||
auxv[i].val = aux_data_base;
|
||||
initVirtMem.writeString(aux_data_base, filename.c_str());
|
||||
initVirtMem->writeString(aux_data_base, filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//Copy the aux stuff
|
||||
Addr auxv_array_end = auxv_array_base;
|
||||
for (const auto &aux: auxv) {
|
||||
initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
|
||||
initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
|
||||
auxv_array_end += sizeof(aux);
|
||||
}
|
||||
//Write out the terminating zeroed auxilliary vector
|
||||
const AuxVector<uint64_t> zero(0, 0);
|
||||
initVirtMem.write(auxv_array_end, zero);
|
||||
initVirtMem->write(auxv_array_end, zero);
|
||||
auxv_array_end += sizeof(zero);
|
||||
|
||||
copyStringArray(envp, envp_array_base, env_data_base,
|
||||
BigEndianByteOrder, initVirtMem);
|
||||
BigEndianByteOrder, *initVirtMem);
|
||||
copyStringArray(argv, argv_array_base, arg_data_base,
|
||||
BigEndianByteOrder, initVirtMem);
|
||||
BigEndianByteOrder, *initVirtMem);
|
||||
|
||||
initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
|
||||
initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
|
||||
|
||||
@@ -155,17 +155,17 @@ RiscvProcess::argsInit(int pageSize)
|
||||
uint8_t at_random[RandomBytes];
|
||||
generate(begin(at_random), end(at_random),
|
||||
[&]{ return random_mt.random(0, 0xFF); });
|
||||
initVirtMem.writeBlob(memState->getStackMin(), at_random, RandomBytes);
|
||||
initVirtMem->writeBlob(memState->getStackMin(), at_random, RandomBytes);
|
||||
|
||||
// Copy argv to stack
|
||||
vector<Addr> argPointers;
|
||||
for (const string& arg: argv) {
|
||||
memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
|
||||
initVirtMem.writeString(memState->getStackMin(), arg.c_str());
|
||||
initVirtMem->writeString(memState->getStackMin(), arg.c_str());
|
||||
argPointers.push_back(memState->getStackMin());
|
||||
if (DTRACE(Stack)) {
|
||||
string wrote;
|
||||
initVirtMem.readString(wrote, argPointers.back());
|
||||
initVirtMem->readString(wrote, argPointers.back());
|
||||
DPRINTFN("Wrote arg \"%s\" to address %p\n",
|
||||
wrote, (void*)memState->getStackMin());
|
||||
}
|
||||
@@ -176,7 +176,7 @@ RiscvProcess::argsInit(int pageSize)
|
||||
vector<Addr> envPointers;
|
||||
for (const string& env: envp) {
|
||||
memState->setStackMin(memState->getStackMin() - (env.size() + 1));
|
||||
initVirtMem.writeString(memState->getStackMin(), env.c_str());
|
||||
initVirtMem->writeString(memState->getStackMin(), env.c_str());
|
||||
envPointers.push_back(memState->getStackMin());
|
||||
DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
|
||||
env, (void*)memState->getStackMin());
|
||||
@@ -195,7 +195,7 @@ RiscvProcess::argsInit(int pageSize)
|
||||
Addr sp = memState->getStackMin();
|
||||
const auto pushOntoStack =
|
||||
[this, &sp](IntType data) {
|
||||
initVirtMem.write(sp, data, GuestByteOrder);
|
||||
initVirtMem->write(sp, data, GuestByteOrder);
|
||||
sp += sizeof(data);
|
||||
};
|
||||
|
||||
|
||||
@@ -351,29 +351,29 @@ SparcProcess::argsInit(int pageSize)
|
||||
|
||||
// Write out the sentry void *
|
||||
uint64_t sentry_NULL = 0;
|
||||
initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
|
||||
initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
|
||||
|
||||
// Write the file name
|
||||
initVirtMem.writeString(file_name_base, filename.c_str());
|
||||
initVirtMem->writeString(file_name_base, filename.c_str());
|
||||
|
||||
// Copy the aux stuff
|
||||
Addr auxv_array_end = auxv_array_base;
|
||||
for (const auto &aux: auxv) {
|
||||
initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
|
||||
initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
|
||||
auxv_array_end += sizeof(aux);
|
||||
}
|
||||
|
||||
// Write out the terminating zeroed auxilliary vector
|
||||
const AuxVector<IntType> zero(0, 0);
|
||||
initVirtMem.write(auxv_array_end, zero);
|
||||
initVirtMem->write(auxv_array_end, zero);
|
||||
auxv_array_end += sizeof(zero);
|
||||
|
||||
copyStringArray(envp, envp_array_base, env_data_base,
|
||||
BigEndianByteOrder, initVirtMem);
|
||||
BigEndianByteOrder, *initVirtMem);
|
||||
copyStringArray(argv, argv_array_base, arg_data_base,
|
||||
BigEndianByteOrder, initVirtMem);
|
||||
BigEndianByteOrder, *initVirtMem);
|
||||
|
||||
initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
|
||||
initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
|
||||
|
||||
// Set up space for the trap handlers into the processes address space.
|
||||
// Since the stack grows down and there is reserved address space abov
|
||||
@@ -404,9 +404,9 @@ Sparc64Process::argsInit(int intSize, int pageSize)
|
||||
SparcProcess::argsInit<uint64_t>(pageSize);
|
||||
|
||||
// Stuff the trap handlers into the process address space
|
||||
initVirtMem.writeBlob(fillStart,
|
||||
initVirtMem->writeBlob(fillStart,
|
||||
fillHandler64, sizeof(MachInst) * numFillInsts);
|
||||
initVirtMem.writeBlob(spillStart,
|
||||
initVirtMem->writeBlob(spillStart,
|
||||
spillHandler64, sizeof(MachInst) * numSpillInsts);
|
||||
}
|
||||
|
||||
@@ -416,9 +416,9 @@ Sparc32Process::argsInit(int intSize, int pageSize)
|
||||
SparcProcess::argsInit<uint32_t>(pageSize);
|
||||
|
||||
// Stuff the trap handlers into the process address space
|
||||
initVirtMem.writeBlob(fillStart,
|
||||
initVirtMem->writeBlob(fillStart,
|
||||
fillHandler32, sizeof(MachInst) * numFillInsts);
|
||||
initVirtMem.writeBlob(spillStart,
|
||||
initVirtMem->writeBlob(spillStart,
|
||||
spillHandler32, sizeof(MachInst) * numSpillInsts);
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ X86_64Process::initState()
|
||||
0x0f,0x05, // syscall
|
||||
0xc3 // retq
|
||||
};
|
||||
initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vtimeOffset,
|
||||
initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vtimeOffset,
|
||||
vtimeBlob, sizeof(vtimeBlob));
|
||||
|
||||
uint8_t vgettimeofdayBlob[] = {
|
||||
@@ -203,7 +203,8 @@ X86_64Process::initState()
|
||||
0x0f,0x05, // syscall
|
||||
0xc3 // retq
|
||||
};
|
||||
initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vgettimeofdayOffset,
|
||||
initVirtMem->writeBlob(
|
||||
vsyscallPage.base + vsyscallPage.vgettimeofdayOffset,
|
||||
vgettimeofdayBlob, sizeof(vgettimeofdayBlob));
|
||||
|
||||
if (kvmInSE) {
|
||||
@@ -635,7 +636,7 @@ I386Process::initState()
|
||||
assert(_gdtSize % sizeof(zero) == 0);
|
||||
for (Addr gdtCurrent = _gdtStart;
|
||||
gdtCurrent < _gdtStart + _gdtSize; gdtCurrent += sizeof(zero)) {
|
||||
initVirtMem.write(gdtCurrent, zero);
|
||||
initVirtMem->write(gdtCurrent, zero);
|
||||
}
|
||||
|
||||
// Set up the vsyscall page for this process.
|
||||
@@ -647,7 +648,7 @@ I386Process::initState()
|
||||
0x89, 0xe5, // mov %esp, %ebp
|
||||
0x0f, 0x34 // sysenter
|
||||
};
|
||||
initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset,
|
||||
initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset,
|
||||
vsyscallBlob, sizeof(vsyscallBlob));
|
||||
|
||||
uint8_t vsysexitBlob[] = {
|
||||
@@ -656,7 +657,7 @@ I386Process::initState()
|
||||
0x59, // pop %ecx
|
||||
0xc3 // ret
|
||||
};
|
||||
initVirtMem.writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset,
|
||||
initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset,
|
||||
vsysexitBlob, sizeof(vsysexitBlob));
|
||||
|
||||
for (int i = 0; i < contextIds.size(); i++) {
|
||||
@@ -976,10 +977,10 @@ X86Process::argsInit(int pageSize,
|
||||
|
||||
// Write out the sentry void *
|
||||
IntType sentry_NULL = 0;
|
||||
initVirtMem.writeBlob(sentry_base, &sentry_NULL, sentry_size);
|
||||
initVirtMem->writeBlob(sentry_base, &sentry_NULL, sentry_size);
|
||||
|
||||
// Write the file name
|
||||
initVirtMem.writeString(file_name_base, filename.c_str());
|
||||
initVirtMem->writeString(file_name_base, filename.c_str());
|
||||
|
||||
// Fix up the aux vectors which point to data
|
||||
assert(auxv[auxv.size() - 3].type == M5_AT_RANDOM);
|
||||
@@ -993,22 +994,22 @@ X86Process::argsInit(int pageSize,
|
||||
// Copy the aux stuff
|
||||
Addr auxv_array_end = auxv_array_base;
|
||||
for (const auto &aux: auxv) {
|
||||
initVirtMem.write(auxv_array_end, aux, GuestByteOrder);
|
||||
initVirtMem->write(auxv_array_end, aux, GuestByteOrder);
|
||||
auxv_array_end += sizeof(aux);
|
||||
}
|
||||
// Write out the terminating zeroed auxiliary vector
|
||||
const AuxVector<uint64_t> zero(0, 0);
|
||||
initVirtMem.write(auxv_array_end, zero);
|
||||
initVirtMem->write(auxv_array_end, zero);
|
||||
auxv_array_end += sizeof(zero);
|
||||
|
||||
initVirtMem.writeString(aux_data_base, platform.c_str());
|
||||
initVirtMem->writeString(aux_data_base, platform.c_str());
|
||||
|
||||
copyStringArray(envp, envp_array_base, env_data_base,
|
||||
LittleEndianByteOrder, initVirtMem);
|
||||
LittleEndianByteOrder, *initVirtMem);
|
||||
copyStringArray(argv, argv_array_base, arg_data_base,
|
||||
LittleEndianByteOrder, initVirtMem);
|
||||
LittleEndianByteOrder, *initVirtMem);
|
||||
|
||||
initVirtMem.writeBlob(argc_base, &guestArgc, intSize);
|
||||
initVirtMem->writeBlob(argc_base, &guestArgc, intSize);
|
||||
|
||||
ThreadContext *tc = system->getThreadContext(contextIds[0]);
|
||||
// Set the stack pointer register
|
||||
|
||||
@@ -115,9 +115,8 @@ ThreadState::initMemProxies(ThreadContext *tc)
|
||||
virtProxy = new FSTranslatingPortProxy(tc);
|
||||
} else {
|
||||
assert(virtProxy == NULL);
|
||||
virtProxy = new SETranslatingPortProxy(baseCpu->getSendFunctional(),
|
||||
process,
|
||||
SETranslatingPortProxy::NextPage);
|
||||
virtProxy = new SETranslatingPortProxy(
|
||||
tc, SETranslatingPortProxy::NextPage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,20 +105,7 @@ struct ThreadState : public Serializable {
|
||||
|
||||
Process *getProcessPtr() { return process; }
|
||||
|
||||
void setProcessPtr(Process *p)
|
||||
{
|
||||
process = p;
|
||||
/**
|
||||
* When the process pointer changes while operating in SE Mode,
|
||||
* the se translating port proxy needs to be reinitialized since it
|
||||
* holds a pointer to the process class.
|
||||
*/
|
||||
if (virtProxy) {
|
||||
delete virtProxy;
|
||||
virtProxy = NULL;
|
||||
initMemProxies(NULL);
|
||||
}
|
||||
}
|
||||
void setProcessPtr(Process *p) { process = p; }
|
||||
|
||||
/** Reads the number of instructions functionally executed and
|
||||
* committed.
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
|
||||
#include "mem/fs_translating_port_proxy.hh"
|
||||
|
||||
#include "arch/generic/tlb.hh"
|
||||
#include "base/chunk_generator.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
@@ -58,21 +57,35 @@ FSTranslatingPortProxy::FSTranslatingPortProxy(ThreadContext *tc) :
|
||||
{}
|
||||
|
||||
bool
|
||||
FSTranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const
|
||||
FSTranslatingPortProxy::tryTLBsOnce(RequestPtr req, BaseTLB::Mode mode) const
|
||||
{
|
||||
BaseTLB *dtb = _tc->getDTBPtr();
|
||||
BaseTLB *itb = _tc->getDTBPtr();
|
||||
return dtb->translateFunctional(req, _tc, mode) == NoFault ||
|
||||
itb->translateFunctional(req, _tc, BaseTLB::Read) == NoFault;
|
||||
}
|
||||
|
||||
bool
|
||||
FSTranslatingPortProxy::tryTLBs(RequestPtr req, BaseTLB::Mode mode) const
|
||||
{
|
||||
// If at first this doesn't succeed, try to fixup and translate again. If
|
||||
// it still fails, report failure.
|
||||
return tryTLBsOnce(req, mode) ||
|
||||
(fixupAddr(req->getVaddr(), mode) && tryTLBsOnce(req, mode));
|
||||
}
|
||||
|
||||
bool
|
||||
FSTranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const
|
||||
{
|
||||
for (ChunkGenerator gen(addr, size, pageBytes); !gen.done();
|
||||
gen.next())
|
||||
{
|
||||
auto req = std::make_shared<Request>(
|
||||
gen.addr(), gen.size(), 0, Request::funcMasterId, 0,
|
||||
_tc->contextId());
|
||||
if (dtb->translateFunctional(req, _tc, BaseTLB::Read) != NoFault &&
|
||||
itb->translateFunctional(req, _tc, BaseTLB::Read) != NoFault) {
|
||||
|
||||
if (!tryTLBs(req, BaseTLB::Read))
|
||||
return false;
|
||||
}
|
||||
|
||||
PortProxy::readBlobPhys(
|
||||
req->getPaddr(), req->getFlags(), p, gen.size());
|
||||
@@ -86,19 +99,15 @@ bool
|
||||
FSTranslatingPortProxy::tryWriteBlob(
|
||||
Addr addr, const void *p, int size) const
|
||||
{
|
||||
BaseTLB *dtb = _tc->getDTBPtr();
|
||||
BaseTLB *itb = _tc->getDTBPtr();
|
||||
|
||||
for (ChunkGenerator gen(addr, size, pageBytes); !gen.done();
|
||||
gen.next())
|
||||
{
|
||||
auto req = std::make_shared<Request>(
|
||||
gen.addr(), gen.size(), 0, Request::funcMasterId, 0,
|
||||
_tc->contextId());
|
||||
if (dtb->translateFunctional(req, _tc, BaseTLB::Write) != NoFault &&
|
||||
itb->translateFunctional(req, _tc, BaseTLB::Write) != NoFault) {
|
||||
|
||||
if (!tryTLBs(req, BaseTLB::Write))
|
||||
return false;
|
||||
}
|
||||
|
||||
PortProxy::writeBlobPhys(
|
||||
req->getPaddr(), req->getFlags(), p, gen.size());
|
||||
@@ -110,19 +119,15 @@ FSTranslatingPortProxy::tryWriteBlob(
|
||||
bool
|
||||
FSTranslatingPortProxy::tryMemsetBlob(Addr address, uint8_t v, int size) const
|
||||
{
|
||||
BaseTLB *dtb = _tc->getDTBPtr();
|
||||
BaseTLB *itb = _tc->getDTBPtr();
|
||||
|
||||
for (ChunkGenerator gen(address, size, pageBytes); !gen.done();
|
||||
gen.next())
|
||||
{
|
||||
auto req = std::make_shared<Request>(
|
||||
gen.addr(), gen.size(), 0, Request::funcMasterId, 0,
|
||||
_tc->contextId());
|
||||
if (dtb->translateFunctional(req, _tc, BaseTLB::Write) != NoFault &&
|
||||
itb->translateFunctional(req, _tc, BaseTLB::Write) != NoFault) {
|
||||
|
||||
if (!tryTLBs(req, BaseTLB::Write))
|
||||
return false;
|
||||
}
|
||||
|
||||
PortProxy::memsetBlobPhys(
|
||||
req->getPaddr(), req->getFlags(), v, gen.size());
|
||||
|
||||
@@ -56,23 +56,33 @@
|
||||
#ifndef __MEM_FS_TRANSLATING_PORT_PROXY_HH__
|
||||
#define __MEM_FS_TRANSLATING_PORT_PROXY_HH__
|
||||
|
||||
#include "arch/generic/tlb.hh"
|
||||
#include "mem/port_proxy.hh"
|
||||
|
||||
class ThreadContext;
|
||||
|
||||
/**
|
||||
* A TranslatingPortProxy in FS mode translates a virtual address to a
|
||||
* physical address and then calls the read/write functions of the
|
||||
* port. If a thread context is provided the address can alway be
|
||||
* translated, If not it can only be translated if it is a simple
|
||||
* address masking operation (such as alpha super page accesses).
|
||||
* This proxy attempts to translate virtual addresses using the TLBs. If it
|
||||
* fails, subclasses can override the fixupAddr virtual method to try to
|
||||
* recover, and then attempt the translation again. If it still fails then the
|
||||
* access as a whole fails.
|
||||
*/
|
||||
class FSTranslatingPortProxy : public PortProxy
|
||||
{
|
||||
private:
|
||||
bool tryTLBsOnce(RequestPtr req, BaseTLB::Mode) const;
|
||||
bool tryTLBs(RequestPtr req, BaseTLB::Mode) const;
|
||||
|
||||
protected:
|
||||
ThreadContext* _tc;
|
||||
const Addr pageBytes;
|
||||
|
||||
virtual bool
|
||||
fixupAddr(Addr addr, BaseTLB::Mode mode) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
FSTranslatingPortProxy(ThreadContext* tc);
|
||||
|
||||
@@ -40,98 +40,28 @@
|
||||
|
||||
#include "mem/se_translating_port_proxy.hh"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "arch/isa_traits.hh"
|
||||
#include "base/chunk_generator.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "mem/page_table.hh"
|
||||
#include "sim/process.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
using namespace TheISA;
|
||||
|
||||
SETranslatingPortProxy::SETranslatingPortProxy(
|
||||
SendFunctionalFunc func, Process *p, AllocType alloc)
|
||||
: PortProxy(func, p->system->cacheLineSize()), pTable(p->pTable),
|
||||
process(p), allocating(alloc)
|
||||
{ }
|
||||
SETranslatingPortProxy::SETranslatingPortProxy(MasterPort &port,
|
||||
Process *p, AllocType alloc)
|
||||
: PortProxy(port, p->system->cacheLineSize()), pTable(p->pTable),
|
||||
process(p), allocating(alloc)
|
||||
{ }
|
||||
ThreadContext *tc, AllocType alloc)
|
||||
: FSTranslatingPortProxy(tc), allocating(alloc)
|
||||
{}
|
||||
|
||||
bool
|
||||
SETranslatingPortProxy::tryReadBlob(Addr addr, void *p, int size) const
|
||||
SETranslatingPortProxy::fixupAddr(Addr addr, BaseTLB::Mode mode) const
|
||||
{
|
||||
int prevSize = 0;
|
||||
auto *bytes = static_cast<uint8_t *>(p);
|
||||
auto *process = _tc->getProcessPtr();
|
||||
|
||||
for (ChunkGenerator gen(addr, size, PageBytes); !gen.done(); gen.next()) {
|
||||
Addr paddr;
|
||||
|
||||
if (!pTable->translate(gen.addr(),paddr))
|
||||
return false;
|
||||
|
||||
PortProxy::readBlobPhys(paddr, 0, bytes + prevSize, gen.size());
|
||||
prevSize += gen.size();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SETranslatingPortProxy::tryWriteBlob(Addr addr, const void *p, int size) const
|
||||
{
|
||||
int prevSize = 0;
|
||||
auto *bytes = static_cast<const uint8_t *>(p);
|
||||
|
||||
for (ChunkGenerator gen(addr, size, PageBytes); !gen.done(); gen.next()) {
|
||||
Addr paddr;
|
||||
|
||||
if (!pTable->translate(gen.addr(), paddr)) {
|
||||
if (allocating == Always) {
|
||||
process->allocateMem(roundDown(gen.addr(), PageBytes),
|
||||
PageBytes);
|
||||
} else if (allocating == NextPage) {
|
||||
// check if we've accessed the next page on the stack
|
||||
if (!process->fixupStackFault(gen.addr()))
|
||||
panic("Page table fault when accessing virtual address %#x "
|
||||
"during functional write\n", gen.addr());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
pTable->translate(gen.addr(), paddr);
|
||||
if (mode == BaseTLB::Write) {
|
||||
if (allocating == Always) {
|
||||
process->allocateMem(roundDown(addr, pageBytes), pageBytes);
|
||||
return true;
|
||||
} else if (allocating == NextPage && process->fixupStackFault(addr)) {
|
||||
// We've accessed the next page on the stack.
|
||||
return true;
|
||||
}
|
||||
|
||||
PortProxy::writeBlobPhys(paddr, 0, bytes + prevSize, gen.size());
|
||||
prevSize += gen.size();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SETranslatingPortProxy::tryMemsetBlob(Addr addr, uint8_t val, int size) const
|
||||
{
|
||||
for (ChunkGenerator gen(addr, size, PageBytes); !gen.done(); gen.next()) {
|
||||
Addr paddr;
|
||||
|
||||
if (!pTable->translate(gen.addr(), paddr)) {
|
||||
if (allocating == Always) {
|
||||
process->allocateMem(roundDown(gen.addr(), PageBytes),
|
||||
PageBytes);
|
||||
pTable->translate(gen.addr(), paddr);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PortProxy::memsetBlobPhys(paddr, 0, val, gen.size());
|
||||
}
|
||||
|
||||
return true;
|
||||
panic("Page table fault when accessing virtual address %#x "
|
||||
"during functional write.", addr);
|
||||
}
|
||||
|
||||
@@ -41,26 +41,9 @@
|
||||
#ifndef __MEM_SE_TRANSLATING_PORT_PROXY_HH__
|
||||
#define __MEM_SE_TRANSLATING_PORT_PROXY_HH__
|
||||
|
||||
#include "mem/port_proxy.hh"
|
||||
#include "mem/fs_translating_port_proxy.hh"
|
||||
|
||||
class EmulationPageTable;
|
||||
class Process;
|
||||
|
||||
/**
|
||||
* @file
|
||||
* TranslatingPortProxy Object Declaration for SE.
|
||||
*
|
||||
* Port proxies are used when non structural entities need access to
|
||||
* the memory system. Proxy objects replace the previous
|
||||
* FunctionalPort, TranslatingPort and VirtualPort objects, which
|
||||
* provided the same functionality as the proxies, but were instances
|
||||
* of ports not corresponding to real structural ports of the
|
||||
* simulated system. Via the port proxies all the accesses go through
|
||||
* an actual port and thus are transparent to a potentially
|
||||
* distributed memory and automatically adhere to the memory map of
|
||||
* the system.
|
||||
*/
|
||||
class SETranslatingPortProxy : public PortProxy
|
||||
class SETranslatingPortProxy : public FSTranslatingPortProxy
|
||||
{
|
||||
|
||||
public:
|
||||
@@ -71,21 +54,13 @@ class SETranslatingPortProxy : public PortProxy
|
||||
};
|
||||
|
||||
private:
|
||||
EmulationPageTable *pTable;
|
||||
Process *process;
|
||||
AllocType allocating;
|
||||
|
||||
public:
|
||||
SETranslatingPortProxy(SendFunctionalFunc func,
|
||||
Process* p, AllocType alloc);
|
||||
SETranslatingPortProxy(MasterPort &port, Process* p, AllocType alloc);
|
||||
~SETranslatingPortProxy() {}
|
||||
protected:
|
||||
bool fixupAddr(Addr addr, BaseTLB::Mode mode) const override;
|
||||
|
||||
void setPageTable(EmulationPageTable *p) { pTable = p; }
|
||||
void setProcess(Process *p) { process = p; }
|
||||
bool tryReadBlob(Addr addr, void *p, int size) const override;
|
||||
bool tryWriteBlob(Addr addr, const void *p, int size) const override;
|
||||
bool tryMemsetBlob(Addr addr, uint8_t val, int size) const override;
|
||||
public:
|
||||
SETranslatingPortProxy(ThreadContext *tc, AllocType alloc);
|
||||
};
|
||||
|
||||
#endif // __MEM_SE_TRANSLATING_PORT_PROXY_HH__
|
||||
|
||||
@@ -116,8 +116,6 @@ Process::Process(ProcessParams *params, EmulationPageTable *pTable,
|
||||
kvmInSE(params->kvmInSE),
|
||||
useForClone(false),
|
||||
pTable(pTable),
|
||||
initVirtMem(system->getSystemPort(), this,
|
||||
SETranslatingPortProxy::Always),
|
||||
objFile(obj_file),
|
||||
argv(params->cmd), envp(params->env),
|
||||
executable(params->executable),
|
||||
@@ -189,9 +187,6 @@ Process::clone(ThreadContext *otc, ThreadContext *ntc,
|
||||
*/
|
||||
delete np->pTable;
|
||||
np->pTable = pTable;
|
||||
auto &proxy = dynamic_cast<SETranslatingPortProxy &>(
|
||||
ntc->getVirtProxy());
|
||||
proxy.setPageTable(np->pTable);
|
||||
|
||||
np->memState = memState;
|
||||
} else {
|
||||
@@ -312,9 +307,12 @@ Process::initState()
|
||||
|
||||
pTable->initState();
|
||||
|
||||
initVirtMem.reset(new SETranslatingPortProxy(
|
||||
tc, SETranslatingPortProxy::Always));
|
||||
|
||||
// load object file into target memory
|
||||
image.write(initVirtMem);
|
||||
interpImage.write(initVirtMem);
|
||||
image.write(*initVirtMem);
|
||||
interpImage.write(*initVirtMem);
|
||||
}
|
||||
|
||||
DrainState
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -172,7 +173,8 @@ class Process : public SimObject
|
||||
|
||||
EmulationPageTable *pTable;
|
||||
|
||||
SETranslatingPortProxy initVirtMem; // memory proxy for initial image load
|
||||
// Memory proxy for initial image load.
|
||||
std::unique_ptr<SETranslatingPortProxy> initVirtMem;
|
||||
|
||||
/**
|
||||
* Each instance of a Loader subclass will have a chance to try to load
|
||||
|
||||
Reference in New Issue
Block a user