arch-arm: Stop using the DmaPort in the TableWalker

Using a custom TableWalker port instead

Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Change-Id: I9e77324569ef0f74f6c8a3941f90bc988abf3c57
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/45599
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Giacomo Travaglini
2021-05-12 16:17:33 +01:00
parent f30d15a29e
commit da01b59a1c
5 changed files with 173 additions and 35 deletions

View File

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

View File

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

View File

@@ -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 <cassert>
#include <memory>
#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<Request>(
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<TableWalkerState*>(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<Request>(
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);

View File

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

View File

@@ -1374,7 +1374,7 @@ TLB::translateComplete(const RequestPtr &req, ThreadContext *tc,
Port *
TLB::getTableWalkerPort()
{
return &stage2Mmu->getDMAPort();
return &stage2Mmu->getTableWalkerPort();
}
vmid_t