Hi!
I am currently using gem5 to develop and evaluate HPC Co-processors in
ARM-based systems. Most of such accelerators require direct access to
the memory, and have to be able to translate memory addresses from the
virtual address space to the physical address space. For doing so, I
have implemented TLB and page-walker structures.
Although the system seems to be capable of correctly translating
addresses, I am facing two problems:
- First, writes to the LLC cache are always unsuccessful. Either the LLC
acknowledges a successful write and no data is actually written, or the
simulation just finishes with 'panic: Page table fault when accessing
virtual address 0'. It is important to mention that the panic condition
occurs after the LLC acknowledges a successful write, and that all read
operations occur without any issue (and the correct data is obtained).
- Second, when crossing a TLB page, i.e., trying to translate an address
that falls under a different page than the previous ones, I always get a
page fault, which means that the page walker is not doing its job.
My code was inspired on Jason Lowe-Power's code that can be found in
https://github.com/powerjg/gem5/tree/devel/accel/src/accel, and it was
adapted to ARM.
I am implementing the write-to-memory operation as follows:
void
NDP::accessMemory(Addr addr, int size, bool write, uint8_t *data)
{
BaseTLB::Mode mode = write ? BaseTLB::Write : BaseTLB::Read;
Request::Flags flags = write ? Request::ARCH_BITS |
Request::INVALIDATE : Request::ARCH_BITS;
RequestPtr req = (RequestPtr) new Request(addr, size, flags, 0, 0,
0, 0);
DPRINTF(Mem, "Translating addr %#x\n", req->getVaddr());
WholeTranslationState *state = new WholeTranslationState(req, data,
NULL, mode);
DataTranslation<NDP*> *translation = new
DataTranslation<NDP*>(this, state);
dtb->translateTiming(req, context, translation, mode);
}
void
NDP::finishTranslation(WholeTranslationState *state)
{
if (state->getFault() != NoFault)
panic("Page fault in NDP. Addr: %#x", state->mainReq->getVaddr());
DPRINTF(Mem, "Got response for translation: %#x -> %#x\n",
state->mainReq->getVaddr(), state->mainReq->getPaddr());
sendData(state->mainReq, state->data, state->mode == BaseTLB::Write);
delete state;
}
void
NDP::sendData(RequestPtr req, uint8_t *data, bool write)
{
if (write)
DPRINTF(Mem, "Sending write request to addr %#x\n",
req->getPaddr());
else
DPRINTF(Mem, "Sending read request to addr %#x\n",
req->getPaddr());
PacketPtr pkt = write ? Packet::createWrite(req) :
Packet::createRead(req);
pkt->dataDynamic<uint8_t>(data);
memPort.schedTimingReq(pkt, nextCycle());
}
Also, here is my python implementation of the TLB and page walker:
# TLB
dtb = Param.ArmTLB(ArmTLB(), "Data TLB")
dstage2_mmu = Param.ArmStage2MMU(ArmStage2DMMU(), "Stage 2 trans")
If anyone has any idea of what seems to be wrong here, any help would be
much appreciated! I have exhausted all options so far...
Thanks in advance!
Kind regards,
Joao Vieira
_______________________________________________
gem5-users mailing list -- gem5-users@gem5.org
To unsubscribe send an email to gem5-users-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s