/*
- * Copyright (c) 2010-2014 ARM Limited
+ * Copyright (c) 2010-2016, 2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
#include <list>
+#include "arch/arm/faults.hh"
#include "arch/arm/miscregs.hh"
#include "arch/arm/system.hh"
#include "arch/arm/tlb.hh"
-#include "dev/dma_device.hh"
-#include "mem/mem_object.hh"
#include "mem/request.hh"
#include "params/ArmTableWalker.hh"
+#include "sim/clocked_object.hh"
#include "sim/eventq.hh"
class ThreadContext;
+class DmaPort;
+
namespace ArmISA {
class Translation;
class TLB;
class Stage2MMU;
-class TableWalker : public MemObject
+class TableWalker : public ClockedObject
{
public:
class WalkerState;
class DescriptorBase {
public:
+ DescriptorBase() : lookupLevel(L0) {}
+
/** Current lookup level for this descriptor */
LookupLevel lookupLevel;
Page
};
+ LongDescriptor() : data(0), _dirty(false) {}
+
/** The raw bits of the entry */
uint64_t data;
/** If the access comes from the secure state. */
bool isSecure;
+ /** True if table walks are uncacheable (for table descriptors) */
+ bool isUncacheable;
+
/** Helper variables used to implement hierarchical access permissions
* when the long-desc. format is used (LPAE only) */
bool secureLookup;
bool xnTable;
bool pxnTable;
+ /** Hierarchical access permission disable */
+ bool hpd;
+
/** Flag indicating if a second stage of lookup is required */
bool stage2Req;
- /** Indicates whether the translation has been passed onto the second
- * stage mmu, and no more work is required from the first stage.
- */
- bool doingStage2;
-
/** A pointer to the stage 2 translation that's in progress */
TLB::Translation *stage2Tran;
protected:
- /**
- * A snooping DMA port that currently does nothing besides
- * extending the DMA port to accept snoops without complaining.
- */
- class SnoopingDmaPort : public DmaPort
- {
-
- protected:
-
- virtual void recvTimingSnoopReq(PacketPtr pkt)
- { }
-
- virtual Tick recvAtomicSnoop(PacketPtr pkt)
- { return 0; }
-
- virtual void recvFunctionalSnoop(PacketPtr pkt)
- { }
-
- virtual bool isSnooping() const { return true; }
-
- public:
-
- /**
- * A snooping DMA port merely calls the construtor of the DMA
- * port.
- */
- SnoopingDmaPort(MemObject *dev, System *s) :
- DmaPort(dev, s)
- { }
- };
-
/** Queues of requests for all the different lookup levels */
std::list<WalkerState *> stateQueues[MAX_LOOKUP_LEVELS];
* currently busy. */
std::list<WalkerState *> pendingQueue;
-
- /** Port to issue translation requests from */
- SnoopingDmaPort port;
-
- /** If we're draining keep the drain event around until we're drained */
- DrainManager *drainManager;
-
/** The MMU to forward second stage look upts to */
Stage2MMU *stage2Mmu;
+ /** Port shared by the two table walkers. */
+ DmaPort* port;
+
+ /** Master id assigned by the MMU. */
+ MasterID masterId;
+
/** Indicates whether this table walker is part of the stage 2 mmu */
const bool isStage2;
/** If a timing translation is currently in progress */
bool pending;
- /** Request id for requests generated by this walker */
- MasterID masterId;
-
/** The number of walks belonging to squashed instructions that can be
* removed from the pendingQueue per cycle. */
unsigned numSquashable;
bool _haveVirtualization;
uint8_t physAddrRange;
bool _haveLargeAsid64;
- ArmSystem *armSys;
/** Statistics */
Stats::Scalar statWalks;
return dynamic_cast<const Params *>(_params);
}
+ void init() override;
+
bool haveLPAE() const { return _haveLPAE; }
bool haveVirtualization() const { return _haveVirtualization; }
bool haveLargeAsid64() const { return _haveLargeAsid64; }
/** Checks if all state is cleared and if so, completes drain */
void completeDrain();
- unsigned int drain(DrainManager *dm);
- virtual void drainResume();
- virtual BaseMasterPort& getMasterPort(const std::string &if_name,
- PortID idx = InvalidPortID);
- void regStats();
-
- /**
- * Allow the MMU (overseeing both stage 1 and stage 2 TLBs) to
- * access the table walker port through the TLB so that it can
- * orchestrate staged translations.
- *
- * @return Our DMA port
- */
- DmaPort& getWalkerPort() { return port; }
-
- Fault walk(RequestPtr req, ThreadContext *tc, uint16_t asid, uint8_t _vmid,
+ DrainState drain() override;
+ void drainResume() override;
+
+ Port &getPort(const std::string &if_name,
+ PortID idx=InvalidPortID) override;
+
+ void regStats() override;
+
+ Fault walk(const RequestPtr &req, ThreadContext *tc,
+ uint16_t asid, uint8_t _vmid,
bool _isHyp, TLB::Mode mode, TLB::Translation *_trans,
bool timing, bool functional, bool secure,
- TLB::ArmTranslationType tranType);
+ TLB::ArmTranslationType tranType, bool _stage2Req);
void setTlb(TLB *_tlb) { tlb = _tlb; }
TLB* getTlb() { return tlb; }
- void setMMU(Stage2MMU *m) { stage2Mmu = m; }
+ void setMMU(Stage2MMU *m, MasterID master_id);
void memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
uint8_t texcb, bool s);
void memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
LongDescriptor &lDescriptor);
- void memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx,
- uint8_t sh);
+ void memAttrsAArch64(ThreadContext *tc, TlbEntry &te,
+ LongDescriptor &lDescriptor);
static LookupLevel toLookupLevel(uint8_t lookup_level_as_int);
void doL1Descriptor();
void doL1DescriptorWrapper();
- EventWrapper<TableWalker,
- &TableWalker::doL1DescriptorWrapper> doL1DescEvent;
+ EventFunctionWrapper doL1DescEvent;
void doL2Descriptor();
void doL2DescriptorWrapper();
- EventWrapper<TableWalker,
- &TableWalker::doL2DescriptorWrapper> doL2DescEvent;
+ EventFunctionWrapper doL2DescEvent;
void doLongDescriptor();
void doL0LongDescriptorWrapper();
- EventWrapper<TableWalker,
- &TableWalker::doL0LongDescriptorWrapper> doL0LongDescEvent;
+ EventFunctionWrapper doL0LongDescEvent;
void doL1LongDescriptorWrapper();
- EventWrapper<TableWalker,
- &TableWalker::doL1LongDescriptorWrapper> doL1LongDescEvent;
+ EventFunctionWrapper doL1LongDescEvent;
void doL2LongDescriptorWrapper();
- EventWrapper<TableWalker,
- &TableWalker::doL2LongDescriptorWrapper> doL2LongDescEvent;
+ EventFunctionWrapper doL2LongDescEvent;
void doL3LongDescriptorWrapper();
- EventWrapper<TableWalker,
- &TableWalker::doL3LongDescriptorWrapper> doL3LongDescEvent;
+ EventFunctionWrapper doL3LongDescEvent;
void doLongDescriptorWrapper(LookupLevel curr_lookup_level);
+ Event* LongDescEventByLevel[4];
bool fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
Request::Flags flags, int queueIndex, Event *event,
void (TableWalker::*doDescriptor)());
+ Fault generateLongDescFault(ArmFault::FaultSource src);
+
void insertTableEntry(DescriptorBase &descriptor, bool longDescriptor);
Fault processWalk();
static bool checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange);
Fault processWalkAArch64();
void processWalkWrapper();
- EventWrapper<TableWalker, &TableWalker::processWalkWrapper> doProcessEvent;
+ EventFunctionWrapper doProcessEvent;
void nextWalk(ThreadContext *tc);
void pendingChange();
static uint8_t pageSizeNtoStatBin(uint8_t N);
+
+ Fault testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
+ LookupLevel lookup_level);
};
} // namespace ArmISA