From da01b59a1cffb1336d1adfb0b7ab9c63b626a5a0 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 12 May 2021 16:17:33 +0100 Subject: [PATCH] arch-arm: Stop using the DmaPort in the TableWalker Using a custom TableWalker port instead Signed-off-by: Giacomo Travaglini Change-Id: I9e77324569ef0f74f6c8a3941f90bc988abf3c57 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/45599 Reviewed-by: Andreas Sandberg Reviewed-by: Daniel Carvalho Maintainer: Andreas Sandberg Tested-by: kokoro --- src/arch/arm/stage2_mmu.cc | 13 ++-- src/arch/arm/stage2_mmu.hh | 13 ++-- src/arch/arm/table_walker.cc | 126 ++++++++++++++++++++++++++++++----- src/arch/arm/table_walker.hh | 54 +++++++++++++-- src/arch/arm/tlb.cc | 2 +- 5 files changed, 173 insertions(+), 35 deletions(-) diff --git a/src/arch/arm/stage2_mmu.cc b/src/arch/arm/stage2_mmu.cc index a741537886..0071bd8125 100644 --- a/src/arch/arm/stage2_mmu.cc +++ b/src/arch/arm/stage2_mmu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2015 ARM Limited + * Copyright (c) 2012-2013, 2015, 2021 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -48,8 +48,8 @@ using namespace ArmISA; Stage2MMU::Stage2MMU(const Params &p) : SimObject(p), _stage1Tlb(p.tlb), _stage2Tlb(p.stage2_tlb), - port(_stage1Tlb->getTableWalker(), p.sys), - requestorId(p.sys->getRequestorId(_stage1Tlb->getTableWalker())) + requestorId(p.sys->getRequestorId(_stage1Tlb->getTableWalker())), + port(_stage1Tlb->getTableWalker(), requestorId) { // we use the stage-one table walker as the parent of the port, // and to get our requestor id, this is done to keep things @@ -131,9 +131,10 @@ Stage2MMU::Stage2Translation::finish(const Fault &_fault, } if (_fault == NoFault && !req->getFlags().isSet(Request::NO_ACCESS)) { - parent.getDMAPort().dmaAction( - MemCmd::ReadReq, req->getPaddr(), numBytes, event, data, - tc->getCpuPtr()->clockPeriod(), req->getFlags()); + TableWalker::Port &port = parent.getTableWalkerPort(); + port.sendTimingReq( + req->getPaddr(), numBytes, data, req->getFlags(), + tc->getCpuPtr()->clockPeriod(), event); } else { // We can't do the DMA access as there's been a problem, so tell the // event we're done diff --git a/src/arch/arm/stage2_mmu.hh b/src/arch/arm/stage2_mmu.hh index c416b15f64..ebf68203d9 100644 --- a/src/arch/arm/stage2_mmu.hh +++ b/src/arch/arm/stage2_mmu.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2015 ARM Limited + * Copyright (c) 2012-2013, 2015, 2021 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -39,8 +39,8 @@ #define __ARCH_ARM_STAGE2_MMU_HH__ #include "arch/arm/faults.hh" +#include "arch/arm/table_walker.hh" #include "arch/arm/tlb.hh" -#include "dev/dma_device.hh" #include "mem/request.hh" #include "params/ArmStage2MMU.hh" #include "sim/eventq.hh" @@ -55,13 +55,12 @@ class Stage2MMU : public SimObject TLB *_stage2Tlb; protected: - - /** Port to issue translation requests from */ - DmaPort port; - /** Request id for requests generated by this MMU */ RequestorID requestorId; + /** Port to issue translation requests from */ + TableWalker::Port port; + public: /** This translation class is used to trigger the data fetch once a timing translation returns the translated physical address */ @@ -109,7 +108,7 @@ class Stage2MMU : public SimObject * is used by the two table walkers, and is exposed externally and * connected through the stage-one table walker. */ - DmaPort& getDMAPort() { return port; } + TableWalker::Port& getTableWalkerPort() { return port; } Fault readDataUntimed(ThreadContext *tc, Addr oVAddr, Addr descAddr, uint8_t *data, int numBytes, Request::Flags flags, bool isFunctional); diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index 2452ebc2f6..e135cb8720 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2019 ARM Limited + * Copyright (c) 2010, 2012-2019, 2021 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -36,6 +36,7 @@ */ #include "arch/arm/table_walker.hh" +#include #include #include "arch/arm/faults.hh" @@ -50,7 +51,6 @@ #include "debug/PageTableWalker.hh" #include "debug/TLB.hh" #include "debug/TLBVerbose.hh" -#include "dev/dma_device.hh" #include "sim/system.hh" using namespace ArmISA; @@ -102,7 +102,7 @@ void TableWalker::setMMU(Stage2MMU *m, RequestorID requestor_id) { stage2Mmu = m; - port = &m->getDMAPort(); + port = &m->getTableWalkerPort(); requestorId = requestor_id; } @@ -143,6 +143,107 @@ TableWalker::WalkerState::WalkerState() : { } +TableWalker::Port::Port(TableWalker *_walker, RequestorID id) + : QueuedRequestPort(_walker->name() + ".port", _walker, + reqQueue, snoopRespQueue), + reqQueue(*_walker, *this), snoopRespQueue(*_walker, *this), + requestorId(id) +{ +} + +PacketPtr +TableWalker::Port::createPacket( + Addr desc_addr, int size, + uint8_t *data, Request::Flags flags, Tick delay, + Event *event) +{ + RequestPtr req = std::make_shared( + desc_addr, size, flags, requestorId); + req->taskId(ContextSwitchTaskId::DMA); + + PacketPtr pkt = new Packet(req, MemCmd::ReadReq); + pkt->dataStatic(data); + + auto state = new TableWalkerState; + state->event = event; + state->delay = delay; + + pkt->senderState = state; + return pkt; +} + +void +TableWalker::Port::sendFunctionalReq( + Addr desc_addr, int size, + uint8_t *data, Request::Flags flags) +{ + auto pkt = createPacket(desc_addr, size, data, flags, 0, nullptr); + + sendFunctional(pkt); + + handleRespPacket(pkt); +} + +void +TableWalker::Port::sendAtomicReq( + Addr desc_addr, int size, + uint8_t *data, Request::Flags flags, Tick delay) +{ + auto pkt = createPacket(desc_addr, size, data, flags, delay, nullptr); + + Tick lat = sendAtomic(pkt); + + handleRespPacket(pkt, lat); +} + +void +TableWalker::Port::sendTimingReq( + Addr desc_addr, int size, + uint8_t *data, Request::Flags flags, Tick delay, + Event *event) +{ + auto pkt = createPacket(desc_addr, size, data, flags, delay, event); + + schedTimingReq(pkt, curTick()); +} + +bool +TableWalker::Port::recvTimingResp(PacketPtr pkt) +{ + // We shouldn't ever get a cacheable block in Modified state. + assert(pkt->req->isUncacheable() || + !(pkt->cacheResponding() && !pkt->hasSharers())); + + handleRespPacket(pkt); + + return true; +} + +void +TableWalker::Port::handleRespPacket(PacketPtr pkt, Tick delay) +{ + // Should always see a response with a sender state. + assert(pkt->isResponse()); + + // Get the DMA sender state. + auto *state = dynamic_cast(pkt->senderState); + assert(state); + + handleResp(state, pkt->getAddr(), pkt->req->getSize(), delay); + + delete pkt; +} + +void +TableWalker::Port::handleResp(TableWalkerState *state, Addr addr, + Addr size, Tick delay) +{ + if (state->event) { + owner.schedule(state->event, curTick() + delay); + } + delete state; +} + void TableWalker::completeDrain() { @@ -2158,8 +2259,9 @@ TableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, } } else { if (isTiming) { - port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data, - currState->tc->getCpuPtr()->clockPeriod(),flags); + port->sendTimingReq(descAddr, numBytes, data, flags, + currState->tc->getCpuPtr()->clockPeriod(), event); + if (queueIndex >= 0) { DPRINTF(PageTableWalker, "Adding to walker fifo: " "queue size before adding: %d\n", @@ -2168,19 +2270,13 @@ TableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, currState = NULL; } } else if (!currState->functional) { - port->dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data, - currState->tc->getCpuPtr()->clockPeriod(), flags); + port->sendAtomicReq(descAddr, numBytes, data, flags, + currState->tc->getCpuPtr()->clockPeriod()); + (this->*doDescriptor)(); } else { - RequestPtr req = std::make_shared( - descAddr, numBytes, flags, requestorId); - - req->taskId(ContextSwitchTaskId::DMA); - PacketPtr pkt = new Packet(req, MemCmd::ReadReq); - pkt->dataStatic(data); - port->sendFunctional(pkt); + port->sendFunctionalReq(descAddr, numBytes, data, flags); (this->*doDescriptor)(); - delete pkt; } } return (isTiming); diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh index 778874782b..4b52be6aff 100644 --- a/src/arch/arm/table_walker.hh +++ b/src/arch/arm/table_walker.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016, 2019 ARM Limited + * Copyright (c) 2010-2016, 2019, 2021 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -45,6 +45,8 @@ #include "arch/arm/system.hh" #include "arch/arm/tlb.hh" #include "arch/arm/types.hh" +#include "mem/packet_queue.hh" +#include "mem/qport.hh" #include "mem/request.hh" #include "params/ArmTableWalker.hh" #include "sim/clocked_object.hh" @@ -52,8 +54,6 @@ class ThreadContext; -class DmaPort; - namespace ArmISA { class Translation; class TLB; @@ -855,6 +855,48 @@ class TableWalker : public ClockedObject std::string name() const { return tableWalker->name(); } }; + class TableWalkerState : public Packet::SenderState + { + public: + Tick delay = 0; + Event *event = nullptr; + }; + + class Port : public QueuedRequestPort + { + public: + Port(TableWalker* _walker, RequestorID id); + + void sendFunctionalReq(Addr desc_addr, int size, + uint8_t *data, Request::Flags flag); + void sendAtomicReq(Addr desc_addr, int size, + uint8_t *data, Request::Flags flag, Tick delay); + void sendTimingReq(Addr desc_addr, int size, + uint8_t *data, Request::Flags flag, Tick delay, + Event *event); + + bool recvTimingResp(PacketPtr pkt) override; + + private: + void handleRespPacket(PacketPtr pkt, Tick delay=0); + void handleResp(TableWalkerState *state, Addr addr, + Addr size, Tick delay=0); + + PacketPtr createPacket(Addr desc_addr, int size, + uint8_t *data, Request::Flags flag, + Tick delay, Event *event); + + private: + /** Packet queue used to store outgoing requests. */ + ReqPacketQueue reqQueue; + + /** Packet queue used to store outgoing snoop responses. */ + SnoopRespPacketQueue snoopRespQueue; + + /** Cached requestorId of the table walker */ + RequestorID requestorId; + }; + protected: /** Queues of requests for all the different lookup levels */ @@ -868,7 +910,7 @@ class TableWalker : public ClockedObject Stage2MMU *stage2Mmu; /** Port shared by the two table walkers. */ - DmaPort* port; + Port* port; /** Requestor id assigned by the MMU. */ RequestorID requestorId; @@ -938,8 +980,8 @@ class TableWalker : public ClockedObject DrainState drain() override; void drainResume() override; - Port &getPort(const std::string &if_name, - PortID idx=InvalidPortID) override; + ::Port &getPort(const std::string &if_name, + PortID idx=InvalidPortID) override; Fault walk(const RequestPtr &req, ThreadContext *tc, uint16_t asid, vmid_t _vmid, diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 2571eaf3cd..cd8155cd38 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -1374,7 +1374,7 @@ TLB::translateComplete(const RequestPtr &req, ThreadContext *tc, Port * TLB::getTableWalkerPort() { - return &stage2Mmu->getDMAPort(); + return &stage2Mmu->getTableWalkerPort(); } vmid_t