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

Reply via email to