Discussion:
[gem5-dev] Change in gem5/gem5[master]: arch-arm: Reverting some changes in the headers for tlb and table_wal...
Ivan Pizarro (Gerrit)
2018-11-22 18:53:28 UTC
Permalink
Ivan Pizarro has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/14575


Change subject: arch-arm: Reverting some changes in the headers for tlb and
table_walker files to ease the review with the previous implementation and
reverting miscregs_types.hh and utility files to include them in a separate
commit
......................................................................

arch-arm: Reverting some changes in the headers for tlb and table_walker
files to ease the review with the previous implementation and reverting
miscregs_types.hh and utility files to include them in a separate commit

Change-Id: Ie6c4ae604f956ba93c2db535fc60f4e94b1379eb
---
A extras
M src/arch/arm/miscregs_types.hh
M src/arch/arm/table_walker.cc
M src/arch/arm/table_walker.hh
M src/arch/arm/tlb.cc
M src/arch/arm/tlb.hh
M src/arch/arm/utility.cc
M src/arch/arm/utility.hh
8 files changed, 1,118 insertions(+), 1,024 deletions(-)



diff --git a/extras b/extras
new file mode 120000
index 0000000..c6ac546
--- /dev/null
+++ b/extras
@@ -0,0 +1 @@
+../gem5-public-commit/extras
\ No newline at end of file
diff --git a/src/arch/arm/miscregs_types.hh b/src/arch/arm/miscregs_types.hh
index 940bf39..c3ee6ca 100644
--- a/src/arch/arm/miscregs_types.hh
+++ b/src/arch/arm/miscregs_types.hh
@@ -271,11 +271,6 @@
Bitfield<0> vm;
EndBitUnion(HCR)

- BitUnion32(HCR2)
- Bitfield<1> id;
- Bitfield<0> cd;
- EndBitUnion(HCR2)
-
BitUnion32(NSACR)
Bitfield<20> nstrcdis;
Bitfield<19> rfr;
@@ -324,7 +319,6 @@
// DC CVAC and IC IVAU instructions
// (AArch64 SCTLR_EL1 only)
Bitfield<25> ee; // Exception Endianness
- Bitfield<24> ve; // Interrupt Vectors Enable (ARMv7 only)
Bitfield<24> e0e; // Endianness of explicit data accesses at
EL0
// (AArch64 SCTLR_EL1 only)
Bitfield<23> xp; // Extended page table enable (dropped in
ARMv7)
@@ -466,7 +460,6 @@
Bitfield<5> pd1;
// Long-descriptor translation table format
Bitfield<2, 0> t0sz;
- Bitfield<6> t2e;
Bitfield<7> epd0;
Bitfield<9, 8> irgn0;
Bitfield<11, 10> orgn0;
@@ -488,8 +481,6 @@
// TCR_EL2/3 (AArch64)
Bitfield<18, 16> ps;
Bitfield<20> tbi;
- Bitfield<41> hpd0;
- Bitfield<42> hpd1;
EndBitUnion(TTBCR)

// Fields of TCR_EL{1,2,3} (mostly overlapping)
@@ -514,10 +505,6 @@
Bitfield<36> as; // EL1
Bitfield<37> tbi0; // EL1
Bitfield<38> tbi1; // EL1
- Bitfield<39> ha;
- Bitfield<40> hd;
- Bitfield<41> hpd0;
- Bitfield<42> hpd1;
EndBitUnion(TCR)

BitUnion32(HTCR)
@@ -525,7 +512,6 @@
Bitfield<9, 8> irgn0;
Bitfield<11, 10> orgn0;
Bitfield<13, 12> sh0;
- Bitfield<24> hpd;
EndBitUnion(HTCR)

BitUnion32(VTCR_t)
@@ -538,8 +524,6 @@
Bitfield<13, 12> sh0;
Bitfield<15, 14> tg0;
Bitfield<18, 16> ps; // Only defined for VTCR_EL2
- Bitfield<21> ha; // Only defined for VTCR_EL2
- Bitfield<22> hd; // Only defined for VTCR_EL2
EndBitUnion(VTCR_t)

BitUnion32(PRRR)
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index fbaba87..fea208a 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -59,10 +59,10 @@
using namespace ArmISA;

TableWalker::TableWalker(const Params *p)
- : MemObject(p), mmu(NULL), masterId(p->sys->getMasterId(this, name())),
+ : MemObject(p), mmu(NULL), currState(NULL), tlb(NULL), id(0),
+ currentId(-1), masterId(p->sys->getMasterId(this, name())),
isStage2(p->is_stage2), numSquashable(p->num_squash_per_cycle),
maxInflightWalks(p->max_inflight_walks), inflightWalks(0),
- cpuSidePort(NULL), memSidePort(NULL),
doL1ShortDescEvent([this]{ doL1ShortDescriptorWrapper(); }, name()),
doL2ShortDescEvent([this]{ doL2ShortDescriptorWrapper(); }, name()),
doL0LongDescEvent([this]{ doL0LongDescriptorWrapper(); }, name()),
@@ -71,8 +71,7 @@
doL3LongDescEvent([this]{ doL3LongDescriptorWrapper(); }, name()),
LongDescEventByLevel { &doL0LongDescEvent, &doL1LongDescEvent,
&doL2LongDescEvent, &doL3LongDescEvent },
- doProcessEvent([this]{ processWalkWrapper(); }, name()),
- tlb(NULL), currState(NULL)
+ doProcessEvent([this]{ processWalkWrapper(); }, name())
{
// Cache system-level properties
if (FullSystem) {
@@ -96,6 +95,11 @@
currentId = -1;
}

+TableWalker::~TableWalker()
+{
+ ;
+}
+
BaseSlavePort&
TableWalker::getSlavePort(const std::string &if_name, PortID idx)
{
@@ -2832,6 +2836,37 @@
}
}

+DrainState
+TableWalker::drain()
+{
+ bool state_queues_not_empty = false;
+
+ for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) {
+ if (!stateQueues[i].empty()) {
+ state_queues_not_empty = true;
+ break;
+ }
+ }
+
+ if (state_queues_not_empty || pendingQueue.size()) {
+ DPRINTF(Drain, "TableWalker not drained\n");
+ return DrainState::Draining;
+ } else {
+ DPRINTF(Drain, "TableWalker free, no need to drain\n");
+ return DrainState::Drained;
+ }
+}
+
+void
+TableWalker::drainResume()
+{
+ if (params()->sys->isTimingMode() && currState) {
+ delete currState;
+ currState = NULL;
+ }
+}
+
+
void
TableWalker::regStats()
{
diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh
index 462c346..2b84410 100644
--- a/src/arch/arm/table_walker.hh
+++ b/src/arch/arm/table_walker.hh
@@ -68,424 +68,431 @@

class TableWalker : public MemObject
{
- private:
+ public:
+ class WalkerState : public Packet::SenderState
+ {
+ public:
+ /** ID identifying the walk */
+ const uint64_t id;
+ /** Thread context that we're doing the walk for */
+ ThreadContext *tc;
+ /** Pointer to the Table Walker performing the translation */
+ TableWalker *walker;
+ /** If the access is performed in AArch64 state */
+ bool aarch64;
+ /** Current exception level */
+ ExceptionLevel el;
+ /** Current lookup level */
+ int level;
+ /** First block where the translation started */
+ int firstblocklevel;
+ /** Address descriptor used during the table walk */
+ AddressDescriptorPtr addrdesc;
+ /** Request that is currently being service */
+ RequestPtr req;
+ /** Cached copy of the sctlr when the translation started */
+ SCTLR sctlr;
+ /** Cached copy of the hcr when the translation started */
+ HCR hcr;
+ /** Cached copy of the mair when the translation started */
+ uint64_t mair;
+ /** Flag indicating if a we are a second stage walker */
+ bool isStage2;
+ /** Flag indicating if a second stage of lookup is required */
+ bool stage2Req;
+ /** If the mode is timing or atomic */
+ bool timing;
+ /** If the atomic mode should be functional */
+ bool functional;
+ /** Raw bits of the descriptor fetched */
+ uint64_t data;
+ /** Copy of the L1 short descriptor lookup */
+ uint32_t l1desc;
+ /** Address used to index in the inflight list */
+ Addr desc_addr;

- MMU* mmu; // Associated MMU for this table walker
+ /** Input address size for the current translation */
+ uint8_t inputsize;
+ /** Output address size for the current translation */
+ uint8_t outputsize;
+ /** Flag to indicate if we are using 64KB granule */
+ bool largegrain;
+ /** Flag to indicate if we are using 16KB granule */
+ bool midgrain;
+ /** Grain size used during the translation */
+ uint8_t grainsize;
+ /** Number of strides needed to consume the address */
+ uint8_t stride;

- /** Master id assigned by the MMU */
- MasterID masterId;
+ /** Access flags values */
+ uint8_t ap_table, ns_table, xn_table, pxn_table;
+ /** Flags to indicate update in the descriptor */
+ bool update_AP, update_AF;
+ /** Flag to indicate if the desciptor is in big endian */
+ bool reversedescriptors;
+ /** Other access flags values */
+ bool lookupsecure, singlepriv, hierattrsdisabled;

- /** Indicates whether this table walker is part of the stage 2 MMU
*/
- const bool isStage2;
- const unsigned numSquashable;
- const unsigned maxInflightWalks;
+ /** Access type of the translation */
+ AccType acctype;
+ /** Flag to indicate if it's a write */
+ bool iswrite;
+ /** Flag to indicate a stage 2 from stage 1 translation */
+ bool s2fs1walk;

- /** Keep track of how many walks are inflight */
- unsigned inflightWalks;
+ /** virtual address for this translation */
+ Addr address;
+ /** Base address register value for this translation */
+ Addr baseregister;
+ /** Next descriptor address bit selection */
+ uint8_t addrselecttop, addrselectbottom;

- /** Cached copies of system-level properties */
- bool haveSecurity;
- bool _haveLPAE;
- bool _haveVirtualization;
- uint8_t physAddrRange;
- bool _haveLargeAsid64;
+ /** Pointer to the translation structure being used */
+ TLB::TranslationStatePtr tran;

- /** Statistics */
- Stats::Scalar statWalks;
- Stats::Scalar statWalksShortDescriptor;
- Stats::Scalar statWalksLongDescriptor;
- Stats::Vector statWalksShortTerminatedAtLevel;
- Stats::Vector statWalksLongTerminatedAtLevel;
- Stats::Scalar statSquashedBefore;
- Stats::Scalar statSquashedAfter;
- Stats::Histogram statWalkWaitTime;
- Stats::Histogram statWalkServiceTime;
- // Essentially "L" of queueing theory
- Stats::Histogram statPendingWalks;
- Stats::Vector statPageSizes;
- Stats::Vector2d statRequestOrigin;
+ TLB::Translation* stage2Tran;
+ Event* next_event;
+ Tick startTime;
+ bool delayed;
+ bool partial_hit;
+ bool isInflight;

- static const unsigned REQUESTED = 0;
- static const unsigned COMPLETED = 1;
+ WalkerState(TableWalker*, uint64_t);
+ ~WalkerState();

- enum {
- SIZE_4GB = 0,
- SIZE_64GB,
- SIZE_1TB,
- SIZE_4TB,
- SIZE_16TB,
- SIZE_256TB,
- SIZE_4PB
- };
-
- enum class TG0 : std::uint8_t {
- GRANULE_4KB = 0,
- GRANULE_64KB = 1,
- GRANULE_16KB = 2,
- UNUSED = 3
- };
-
- enum class TG1 : long unsigned int {
- UNUSED = 0,
- GRANULE_16KB = 1,
- GRANULE_4KB = 2,
- GRANULE_64KB = 3
- };
-
- public:
-
- class WalkerState : public Packet::SenderState
+ void
+ s1AttrDecode64(uint8_t sh, uint8_t memattr)
{
- public:
-
- /** ID identifying the walk */
- const uint64_t id;
- /** Thread context that we're doing the walk for */
- ThreadContext *tc;
- /** Pointer to the Table Walker performing the translation
*/
- TableWalker *walker;
- /** If the access is performed in AArch64 state */
- bool aarch64;
- /** Current exception level */
- ExceptionLevel el;
- /** Current lookup level */
- int level;
- /** First block where the translation started */
- int firstblocklevel;
- /** Address descriptor used during the table walk */
- AddressDescriptorPtr addrdesc;
- /** Request that is currently being service */
- RequestPtr req;
- /** Cached copy of the sctlr when the translation started
*/
- SCTLR sctlr;
- /** Cached copy of the hcr when the translation started */
- HCR hcr;
- /** Cached copy of the mair when the translation started */
- uint64_t mair;
- /** Flag indicating if a we are a second stage walker */
- bool isStage2;
- /** Flag indicating if a second stage of lookup is
required */
- bool stage2Req;
- /** If the mode is timing or atomic */
- bool timing;
- /** If the atomic mode should be functional */
- bool functional;
- /** Raw bits of the descriptor fetched */
- uint64_t data;
- /** Copy of the L1 short descriptor lookup */
- uint32_t l1desc;
- /** Address used to index in the inflight list */
- Addr desc_addr;
-
- /** Input address size for the current translation */
- uint8_t inputsize;
- /** Output address size for the current translation */
- uint8_t outputsize;
- /** Flag to indicate if we are using 64KB granule */
- bool largegrain;
- /** Flag to indicate if we are using 16KB granule */
- bool midgrain;
- /** Grain size used during the translation */
- uint8_t grainsize;
- /** Number of strides needed to consume the address */
- uint8_t stride;
-
- /** Access flags values */
- uint8_t ap_table, ns_table, xn_table, pxn_table;
- /** Flags to indicate update in the descriptor */
- bool update_AP, update_AF;
- /** Flag to indicate if the desciptor is in big endian */
- bool reversedescriptors;
- /** Other access flags values */
- bool lookupsecure, singlepriv, hierattrsdisabled;
-
- /** Access type of the translation */
- AccType acctype;
- /** Flag to indicate if it's a write */
- bool iswrite;
- /** Flag to indicate a stage 2 from stage 1 translation */
- bool s2fs1walk;
-
- /** virtual address for this translation */
- Addr address;
- /** Base address register value for this translation */
- Addr baseregister;
- /** Next descriptor address bit selection */
- uint8_t addrselecttop, addrselectbottom;
-
- /** Pointer to the translation structure being used */
- TLB::TranslationStatePtr tran;
-
- TLB::Translation* stage2Tran;
- Event* next_event;
- Tick startTime;
- bool delayed;
- bool partial_hit;
- bool isInflight;
-
- WalkerState(TableWalker*, uint64_t);
- ~WalkerState();
-
- void
- s1AttrDecode64(uint8_t sh, uint8_t memattr)
- {
- MemoryAttributes* memattrs = addrdesc->memattrs;
- uint8_t attr = bits(memattr, 2, 0);
- SCTLR sctlr = tran->sctlr;
- HCR hcr = tran->hcr;
- uint64_t mair = tran->mair;
- walker->s1AttrDecode64(tc, memattrs, sh, attr,
acctype, el,
- sctlr, hcr, mair);
- }
-
- void
- s1AttrDecode32(uint8_t sh, uint8_t memattr)
- {
- MemoryAttributes* memattrs = addrdesc->memattrs;
- uint8_t attr = bits(memattr, 2, 0);
- walker->s1AttrDecode32(tc, memattrs, sh, attr,
acctype, el,
- sctlr, hcr, mair);
- }
-
- void
- s2AttrDecode(uint8_t sh, uint8_t memattr, AccType acctype)
- {
- MemoryAttributes* memattrs = addrdesc->memattrs;
- walker->s2AttrDecode(memattrs, sh, memattr, acctype);
- }
-
- void maxtickReached();
- EventFunctionWrapper* maxtickReachedEvent;
- };
-
- class CpuSidePort : public SlavePort
- {
- public:
- CpuSidePort(const std::string &_name, TableWalker *_walker,
- PortID _index) : SlavePort(_name, _walker),
- walker(_walker), index(_index) {}
-
- protected:
- TableWalker *walker;
- int index;
-
- virtual bool recvTimingReq(PacketPtr pkt);
- virtual Tick recvAtomic(PacketPtr pkt);
- virtual void recvFunctional(PacketPtr pkt) { };
- virtual void recvRangeChange() { };
- virtual void recvReqRetry();
- virtual void recvRespRetry();
- virtual AddrRangeList getAddrRanges() const
- {
- AddrRangeList range;
- return range;
- }
- };
-
- class MemSidePort : public MasterPort
- {
- public:
- MemSidePort(const std::string &_name, TableWalker *_walker,
- PortID _index) : MasterPort(_name, _walker),
- walker(_walker), index(_index) {}
-
- std::deque<PacketPtr> retries;
- std::multimap<Addr, PacketPtr> new_retries;
-
- protected:
- TableWalker *walker;
- int index;
-
- virtual bool recvTimingResp(PacketPtr pkt);
- virtual Tick recvAtomic(PacketPtr pkt) { return 0; }
- virtual void recvFunctional(PacketPtr pkt) { };
- virtual void recvRangeChange() { };
- virtual void recvReqRetry();
- };
-
- CpuSidePort* cpuSidePort;
- MemSidePort* memSidePort;
-
- BaseMasterPort&
- getMasterPort(const std::string &if_name, PortID idx) override;
- BaseSlavePort&
- getSlavePort(const std::string &if_name, PortID idx) override;
-
- void regStats() override;
-
- void increaseInflightWalks() {
- currState->isInflight = true;
- inflightWalks++;
+ MemoryAttributes* memattrs = addrdesc->memattrs;
+ uint8_t attr = bits(memattr, 2, 0);
+ SCTLR sctlr = tran->sctlr;
+ HCR hcr = tran->hcr;
+ uint64_t mair = tran->mair;
+ walker->s1AttrDecode64(tc, memattrs, sh, attr, acctype, el,
+ sctlr, hcr, mair);
}

- void decreaseInflightWalks() {
- if (currState->isInflight) {
- assert(inflightWalks > 0);
- inflightWalks--;
+ void
+ s1AttrDecode32(uint8_t sh, uint8_t memattr)
+ {
+ MemoryAttributes* memattrs = addrdesc->memattrs;
+ uint8_t attr = bits(memattr, 2, 0);
+ walker->s1AttrDecode32(tc, memattrs, sh, attr, acctype, el,
+ sctlr, hcr, mair);
+ }
+
+ void
+ s2AttrDecode(uint8_t sh, uint8_t memattr, AccType acctype)
+ {
+ MemoryAttributes* memattrs = addrdesc->memattrs;
+ walker->s2AttrDecode(memattrs, sh, memattr, acctype);
+ }
+
+ void maxtickReached();
+ EventFunctionWrapper* maxtickReachedEvent;
+ };
+
+ protected:
+
+ /** Queues of requests for all the different lookup levels */
+ std::map<uint64_t, WalkerState*> stateQueues[MAX_LOOKUP_LEVELS];
+
+ /** Queue of requests that have passed are waiting because the walker
is
+ * currently busy. */
+ std::map<uint64_t, WalkerState*> pendingQueue;
+
+ /** The MMU to forward second stage look upts to */
+ MMU* mmu;
+
+ /** Queue of walks in flight */
+ typedef std::queue<WalkerState*> WalksQueue;
+ std::map<Addr, WalksQueue> inflightDescriptors;
+
+ WalkerState* currState;
+
+ /** TLB that initiated the table walk. Used for functional lookups */
+ TLB *tlb;
+
+ /** Global walk ID */
+ uint64_t id, currentId;
+
+ /** Master id assigned by the MMU */
+ MasterID masterId;
+
+ /** Indicates whether this table walker is part of the stage 2 MMU */
+ const bool isStage2;
+ const unsigned numSquashable;
+ const unsigned maxInflightWalks;
+
+ /** Keep track of how many walks are inflight */
+ unsigned inflightWalks;
+
+ /** Cached copies of system-level properties */
+ bool haveSecurity;
+ bool _haveLPAE;
+ bool _haveVirtualization;
+ uint8_t physAddrRange;
+ bool _haveLargeAsid64;
+
+ /** Statistics */
+ Stats::Scalar statWalks;
+ Stats::Scalar statWalksShortDescriptor;
+ Stats::Scalar statWalksLongDescriptor;
+ Stats::Vector statWalksShortTerminatedAtLevel;
+ Stats::Vector statWalksLongTerminatedAtLevel;
+ Stats::Scalar statSquashedBefore;
+ Stats::Scalar statSquashedAfter;
+ Stats::Histogram statWalkWaitTime;
+ Stats::Histogram statWalkServiceTime;
+ // Essentially "L" of queueing theory
+ Stats::Histogram statPendingWalks;
+ Stats::Vector statPageSizes;
+ Stats::Vector2d statRequestOrigin;
+
+ static const unsigned REQUESTED = 0;
+ static const unsigned COMPLETED = 1;
+
+ enum {
+ SIZE_4GB = 0,
+ SIZE_64GB,
+ SIZE_1TB,
+ SIZE_4TB,
+ SIZE_16TB,
+ SIZE_256TB,
+ SIZE_4PB
+ };
+
+ enum class TG0 : std::uint8_t {
+ GRANULE_4KB = 0,
+ GRANULE_64KB = 1,
+ GRANULE_16KB = 2,
+ UNUSED = 3
+ };
+
+ enum class TG1 : long unsigned int {
+ UNUSED = 0,
+ GRANULE_16KB = 1,
+ GRANULE_4KB = 2,
+ GRANULE_64KB = 3
+ };
+
+ public:
+ typedef ArmTableWalkerParams Params;
+ TableWalker(const Params *p);
+ virtual ~TableWalker();
+
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(_params);
+ }
+
+ 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();
+ DrainState drain() override;
+ void drainResume() override;
+
+ void regStats() override;
+
+ class CpuSidePort : public SlavePort
+ {
+ public:
+ CpuSidePort(const std::string &_name, TableWalker *_walker,
+ PortID _index) : SlavePort(_name, _walker),
+ walker(_walker), index(_index) {}
+
+ protected:
+ TableWalker *walker;
+ int index;
+
+ virtual bool recvTimingReq(PacketPtr pkt);
+ virtual Tick recvAtomic(PacketPtr pkt);
+ virtual void recvFunctional(PacketPtr pkt) { };
+ virtual void recvRangeChange() { };
+ virtual void recvReqRetry();
+ virtual void recvRespRetry();
+ virtual AddrRangeList getAddrRanges() const
+ {
+ AddrRangeList range;
+ return range;
}
+ };
+
+ class MemSidePort : public MasterPort
+ {
+ public:
+ MemSidePort(const std::string &_name, TableWalker *_walker,
+ PortID _index) : MasterPort(_name, _walker),
+ walker(_walker), index(_index) {}
+
+ std::deque<PacketPtr> retries;
+
+ protected:
+ TableWalker *walker;
+ int index;
+
+ virtual bool recvTimingResp(PacketPtr pkt);
+ virtual Tick recvAtomic(PacketPtr pkt) { return 0; }
+ virtual void recvFunctional(PacketPtr pkt) { };
+ virtual void recvRangeChange() { };
+ virtual void recvReqRetry();
+ };
+
+ CpuSidePort* cpuSidePort;
+ MemSidePort* memSidePort;
+
+ BaseMasterPort&
+ getMasterPort(const std::string &if_name, PortID idx) override;
+ BaseSlavePort&
+ getSlavePort(const std::string &if_name, PortID idx) override;
+
+ void increaseInflightWalks() {
+ currState->isInflight = true;
+ inflightWalks++;
+ }
+
+ void decreaseInflightWalks() {
+ if (currState->isInflight) {
+ assert(inflightWalks > 0);
+ inflightWalks--;
}
+ }

- private:
+private:

- // Returns TRUE if the bits of the input (n) between the high bit
(h)
- // and the low bit (l) are ones
- bool isOnes(uint64_t n, uint32_t h, uint32_t l);
+ // Returns TRUE if the bits of the input (n) between the high bit (h)
+ // and the low bit (l) are ones
+ bool isOnes(uint64_t n, uint32_t h, uint32_t l);

- /** Short descriptor event functions */
- void doL1ShortDescriptor();
- void doL1ShortDescriptorWrapper();
- EventFunctionWrapper doL1ShortDescEvent;
+ /** Short descriptor event functions */
+ void doL1ShortDescriptor();
+ void doL1ShortDescriptorWrapper();
+ EventFunctionWrapper doL1ShortDescEvent;

- void doL2ShortDescriptor();
- void doL2ShortDescriptorWrapper();
- EventFunctionWrapper doL2ShortDescEvent;
+ void doL2ShortDescriptor();
+ void doL2ShortDescriptorWrapper();
+ EventFunctionWrapper doL2ShortDescEvent;

- /** Long descriptor event functions for LPAE and AArch64*/
- void doL0LongDescriptorWrapper();
- EventFunctionWrapper doL0LongDescEvent;
- void doL1LongDescriptorWrapper();
- EventFunctionWrapper doL1LongDescEvent;
- void doL2LongDescriptorWrapper();
- EventFunctionWrapper doL2LongDescEvent;
- void doL3LongDescriptorWrapper();
- EventFunctionWrapper doL3LongDescEvent;
+ /** Long descriptor event functions for LPAE and AArch64*/
+ void doL0LongDescriptorWrapper();
+ EventFunctionWrapper doL0LongDescEvent;
+ void doL1LongDescriptorWrapper();
+ EventFunctionWrapper doL1LongDescEvent;
+ void doL2LongDescriptorWrapper();
+ EventFunctionWrapper doL2LongDescEvent;
+ void doL3LongDescriptorWrapper();
+ EventFunctionWrapper doL3LongDescEvent;

- void doLongDescriptor();
- void doLongDescriptorWrapper(int);
- Event* LongDescEventByLevel[4];
+ void doLongDescriptor();
+ void doLongDescriptorWrapper(int);
+ Event* LongDescEventByLevel[4];

- /** AArch64 descriptor event functions */
- void doAArch64Descriptor();
- void doAArch64DescriptorWrapper(int);
+ /** AArch64 descriptor event functions */
+ void doAArch64Descriptor();
+ void doAArch64DescriptorWrapper(int);

- void processWalkWrapper();
- EventFunctionWrapper doProcessEvent;
+ void processWalkWrapper();
+ EventFunctionWrapper doProcessEvent;

- // Returns the descriptor at the physical address specified by the
- // AddressDescriptor, checks access permissions and sets the fault
- // field if needed
- bool fetchDescriptor(AddressDescriptorPtr, int, Request::Flags,
int,
- Event *event, void
(TableWalker::*doDescriptor)());
+ // Returns the descriptor at the physical address specified by the
+ // AddressDescriptor, checks access permissions and sets the fault
+ // field if needed
+ bool fetchDescriptor(AddressDescriptorPtr, int, Request::Flags, int,
+ Event *event, void (TableWalker::*doDescriptor)());

- // Schedule the next table walk in the pending queue
- void nextWalk();
+ // Schedule the next table walk in the pending queue
+ void nextWalk();

- void completeDrain();
+ void sendTimingResponse();

- void sendTimingResponse();
+ void insertPartialTranslation();

- void insertPartialTranslation();
+ // Annotate the fault as it was produced during a stage 1 translation
+ // in a stage 2 page walk
+ void annotateStage2Fault();

- // Annotate the fault as it was produced during a stage 1
translation
- // in a stage 2 page walk
- void annotateStage2Fault();
+protected:

- protected:
+ // Process the queue with pending descriptor requests and continue the
+ // walk for the ones with the matching address
+ bool processInflightDescriptors(Addr);

- // TLB that initiated the table walk. Used for functional lookups
- TLB *tlb;
+ void accessFlagFault(uint8_t, ArmFault::TranMethod);
+ void addressSizeFault(uint8_t, bool, ArmFault::TranMethod);
+ void translationFault(uint8_t, ArmFault::TranMethod);

- // Global walk ID
- uint64_t id, currentId;
- // Queues of requests for all the the different lookup levels
- std::map<uint64_t, WalkerState*> stateQueues[MAX_LOOKUP_LEVELS];
+ bool s1CacheDisabled(AccType);
+ bool s2CacheDisabled(AccType);

- // Queue of requests that have passed are waiting because the
walker
- // is currently busy
- std::map<uint64_t, WalkerState*> pendingQueue;
- std::queue<WalkerState*> newPendingQueue;
+ // Converts the Stage 1 attribute fields, using the uint64_t
+ // to orthogonal attributes and hints
+ void s1AttrDecode32(ThreadContext*, MemoryAttributes*, uint8_t,
+ uint8_t, AccType, ExceptionLevel, SCTLR, HCR, uint64_t);
+ void s1AttrDecode64(ThreadContext*, MemoryAttributes*, uint8_t,
+ uint8_t, AccType, ExceptionLevel, SCTLR, HCR, uint64_t);

- WalkerState* currState;
+ // Converts the Stage 2 attribute fields into othogonal attributes and
+ // hints
+ void s2AttrDecode(MemoryAttributes*, uint8_t, uint8_t, AccType);

- typedef std::queue<WalkerState*> WalksQueue;
- std::map<Addr, WalksQueue> inflightDescriptors;
+ // Converts the short attribute fields for Normal memory as used in the
+ // TTBR and TEX fields to orthogonal attributes and hints
+ MemAttrHints shortConvertAttrsHints(uint8_t, AccType);

- // Process the queue with pending descriptor requests and continue
the
- // walk for the ones with the matching address
- bool processInflightDescriptors(Addr);
+ // Converts the long attribute fields for Normal memory as used in the
+ // uint64_t fields to orthogonal attributes and hints
+ MemAttrHints longConvertAttrsHints(uint8_t, AccType, SCTLR, HCR);

- void accessFlagFault(uint8_t, ArmFault::TranMethod);
- void addressSizeFault(uint8_t, bool, ArmFault::TranMethod);
- void translationFault(uint8_t, ArmFault::TranMethod);
+ // Converts the attribute fields for Normal memory as used in stage 2
+ // descriptors to orthogonal attributes and hints
+ MemAttrHints s2ConvertAttrsHints(uint8_t, AccType);

- bool s1CacheDisabled(AccType);
- bool s2CacheDisabled(AccType);
+ void walkAttrDecode(ThreadContext*, MemoryAttributes*, uint8_t,
+ uint8_t, uint8_t, ExceptionLevel, SCTLR, HCR);

- // Converts the Stage 1 attribute fields, using the uint64_t
- // to orthogonal attributes and hints
- void s1AttrDecode32(ThreadContext*, MemoryAttributes*, uint8_t,
- uint8_t, AccType, ExceptionLevel, SCTLR, HCR,
uint64_t);
- void s1AttrDecode64(ThreadContext*, MemoryAttributes*, uint8_t,
- uint8_t, AccType, ExceptionLevel, SCTLR, HCR,
uint64_t);
+ void defaultTEXDecode(MemoryAttributes*, uint8_t, bool, bool, bool,
+ AccType);

- // Converts the Stage 2 attribute fields into othogonal attributes
and
- // hints
- void s2AttrDecode(MemoryAttributes*, uint8_t, uint8_t, AccType);
+ void remappedTEXDecode(MemoryAttributes*, uint8_t, bool, bool, bool,
+ AccType);

- // Converts the short attribute fields for Normal memory as used
in the
- // TTBR and TEX fields to orthogonal attributes and hints
- MemAttrHints shortConvertAttrsHints(uint8_t, AccType);
+ void setCurrentStateId(uint64_t currId) {
+ currentId = currId;
+ }

- // Converts the long attribute fields for Normal memory as used in
the
- // uint64_t fields to orthogonal attributes and hints
- MemAttrHints longConvertAttrsHints(uint8_t, AccType, SCTLR, HCR);
+public:

- // Converts the attribute fields for Normal memory as used in
stage 2
- // descriptors to orthogonal attributes and hints
- MemAttrHints s2ConvertAttrsHints(uint8_t, AccType);
+ // Clean up the currState and pending walk
+ void cleanup();

- void walkAttrDecode(ThreadContext*, MemoryAttributes*, uint8_t,
- uint8_t, uint8_t, ExceptionLevel, SCTLR, HCR);
+ bool haveLPAE() {
+ return _haveLPAE;
+ }

- void defaultTEXDecode(MemoryAttributes*, uint8_t, bool, bool, bool,
- AccType);
+ bool haveVirtualization() {
+ return _haveVirtualization;
+ }

- void remappedTEXDecode(MemoryAttributes*, uint8_t, bool, bool,
bool,
- AccType);
+ bool haveLargeAsid64() {
+ return _haveLargeAsid64;
+ }

- void setCurrentStateId(uint64_t currId) {
- currentId = currId;
- }
+ void walk(TLB::TranslationStatePtr);

- public:
+ void setMMU(MMU*, TLB*);

- // Clean up the currState and pending walk
- void cleanup();
+ // Returns TRUE if the page walk is being delayed, FALSE otherwise
+ // The result of the page walk will be updated in the TranslationState
+ // structure
+ void translationTableWalkSD(TLB::TranslationStatePtr);
+ void translationTableWalkLD(TLB::TranslationStatePtr);
+ void translationTableWalk64(TLB::TranslationStatePtr);

- bool haveLPAE() {
- return _haveLPAE;
- }
-
- bool haveVirtualization() {
- return _haveVirtualization;
- }
-
- bool haveLargeAsid64() {
- return _haveLargeAsid64;
- }
-
- void walk(TLB::TranslationStatePtr);
-
- typedef ArmTableWalkerParams Params;
- TableWalker(const Params *p);
-
- const Params *
- params() const
- {
- return dynamic_cast<const Params *>(_params);
- }
-
- void setMMU(MMU*, TLB*);
-
- // Returns TRUE if the page walk is being delayed, FALSE otherwise
- // The result of the page walk will be updated in the
TranslationState
- // structure
- void translationTableWalkSD(TLB::TranslationStatePtr);
- void translationTableWalkLD(TLB::TranslationStatePtr);
- void translationTableWalk64(TLB::TranslationStatePtr);
-
- Fault testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
- LookupLevel lookup_level);
+ Fault testWalk(Addr pa, Addr size, TlbEntry::DomainType domain,
+ LookupLevel lookup_level);
};

} // namespace ArmISA
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 228535b..7b5b631 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -62,15 +62,16 @@
using namespace ArmISA;

TLB::TLB(const Params *p)
- : BaseTLB(p), size(p->size), assoc(p->assoc),
- allowPartial(p->allow_partial_translations), table(size),
+ : BaseTLB(p), table(p->size), size(p->size), assoc(p->assoc),
+ isStage2(p->is_stage2), stage2Req(false), stage2DescReq(false),
_attr(0),
+ directToStage2(false), level(p->level),
+ allowPartial(p->allow_partial_translations), access_latency(p->lat),
indexingPolicy(p->indexing_policy),
- replacementPolicy(p->replacement_policy), isStage2(p->is_stage2),
- level(p->level), access_latency(p->lat), next_tlb(p->next_tlb),
- stage2Tlb(p->stage2tlb), tableWalker(p->walker), mmu(NULL),
- test(nullptr), stage2Req(false), directToStage2(false),
aarch64(false),
- aarch64EL(EL0), isPriv(false), isSecure(false), isHyp(false),
asid(0),
- vmid(0), miscRegValid(false)
+ replacementPolicy(p->replacement_policy), tableWalker(p->walker),
+ stage2Tlb(NULL), next_tlb(NULL), mmu(NULL), test(nullptr),
rangeMRU(1),
+ aarch64(false), aarch64EL(EL0), isPriv(false), isSecure(false),
+ isHyp(false), asid(0), vmid(0), dacr(0),
+ miscRegValid(false), miscRegContext(0), curTranType(NormalTran)
{
assert(assoc < size);

@@ -180,6 +181,22 @@
return fault;
}

+Fault
+TLB::finalizePhysical(const RequestPtr &req,
+ ThreadContext *tc, Mode mode) const
+{
+ const Addr paddr = req->getPaddr();
+
+ if (m5opRange.contains(paddr)) {
+ req->setFlags(Request::MMAPPED_IPR | Request::GENERIC_IPR);
+ req->setPaddr(GenericISA::iprAddressPseudoInst(
+ (paddr >> 8) & 0xFF,
+ paddr & 0xFF));
+ }
+
+ return NoFault;
+}
+
void
TLB::translateTiming(const RequestPtr &req, ThreadContext *tc,
Translation *translation, Mode mode, TLB::ArmTranslationType tranType)
@@ -338,6 +355,12 @@
return delay ? NoFault : finalizeTranslation(tran);
}

+void
+TLB::regProbePoints()
+{
+ ppRefills.reset(new ProbePoints::PMU(getProbeManager(), "Refills"));
+}
+
Fault
TLB::translateSe(const RequestPtr &req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing)
@@ -381,13 +404,13 @@

Fault
TLB::translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode,
- ArmTranslationType tranType, TranslationStatePtr ts)
+ ArmTranslationType tranType)
{
updateMiscReg(tc, tranType);

if (directToStage2) {
assert(stage2Tlb);
- return stage2Tlb->translateAtomic(req, tc, mode, tranType, ts);
+ return stage2Tlb->translateAtomic(req, tc, mode, tranType);
}

bool delay = false;
@@ -610,10 +633,6 @@
te->pfn, te->size, te->vpn, te->asid, te->vmid, te->N,
te->global, te->valid, xn, ap, te->ns, te->nstid,
te->isHyp);
-
- // Sanity check
- bool tlb_hit = lookup(tran, true, true, from_ptw);
- assert(tlb_hit);
}

bool
@@ -640,7 +659,7 @@
target_el = tran->aarch64 ? tran->aarch64EL : 1;
} else {
va = tran->ptw_desc_addr;
- if (!functional) printTLB();
+ if (!functional) printTlb();
}

TlbEntryPtr _te = nullptr; // For debugging
@@ -1895,6 +1914,30 @@
}

void
+TLB::takeOverFrom(BaseTLB *_otlb)
+{
+ TLB *otlb = dynamic_cast<TLB*>(_otlb);
+ /* Make sure we actually have a valid type */
+ if (otlb) {
+ _attr = otlb->_attr;
+ haveLPAE = otlb->haveLPAE;
+ directToStage2 = otlb->directToStage2;
+ stage2Req = otlb->stage2Req;
+ stage2DescReq = otlb->stage2DescReq;
+
+ /* Sync the stage2 MMU if they exist in both
+ * the old CPU and the new
+ */
+ if (!isStage2 &&
+ stage2Tlb && otlb->stage2Tlb) {
+ stage2Tlb->takeOverFrom(otlb->stage2Tlb);
+ }
+ } else {
+ panic("Incompatible TLB type!");
+ }
+}
+
+void
TLB::regStats()
{
BaseTLB::regStats();
@@ -2308,15 +2351,15 @@
}

void
-TLB::printTLB()
+TLB::printTlb() const
{
- DPRINTF(TLB, "Current TLB contents:\n");
-
- for (unsigned int i = 0; i < size; i++) {
- if (table[i].getData()) {
- DPRINTF(TLB, " * [%u] %s\n", i, table[i].getData()->print());
- }
- }
+// DPRINTF(TLB, "Current TLB contents:\n");
+//
+// for (unsigned int i = 0; i < size; i++) {
+// if (table[i].getData()) {
+// DPRINTF(TLB, " * [%u] %s\n", i, table[i].getData()->print());
+// }
+// }
}

void
@@ -2332,7 +2375,8 @@
}

Fault
-TLB::testTranslation(RequestPtr req, Mode mode, TlbEntry::DomainType
domain)
+TLB::testTranslation(const RequestPtr &req, Mode mode,
+ TlbEntry::DomainType domain)
{
if (!test || !req->hasSize() || req->getSize() == 0 ||
req->isCacheMaintenance()) {
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index 7702e8a..9cadc6c 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -109,661 +109,692 @@

class TLB : public BaseTLB
{
- private:
+ public:
+ enum ArmFlags {
+ AlignmentMask = 0x7,

- // Number of TLB entries
- unsigned int size;
- unsigned int assoc;
- // Allow storing partial translations
- const bool allowPartial;
+ AlignByte = 0x0,
+ AlignHalfWord = 0x1,
+ AlignWord = 0x2,
+ AlignDoubleWord = 0x3,
+ AlignQuadWord = 0x4,
+ AlignOctWord = 0x5,

- std::vector<TlbEntryRepl> table;
+ AllowUnaligned = 0x8,
+ // Priv code operating as if it wasn't
+ UserMode = 0x10,
+ // Because zero otherwise looks like a valid setting and may be
used
+ // accidentally, this bit must be non-zero to show it was used on
+ // purpose.
+ MustBeOne = 0x40
+ };

- BaseIndexingPolicy *indexingPolicy;
- BaseReplacementPolicy *replacementPolicy;
+ enum ArmTranslationType {
+ NormalTran = 0,
+ S1CTran = 0x1,
+ HypMode = 0x2,
+ // Secure code operating as if it wasn't (required by some Address
+ // Translate operations)
+ S1S2NsTran = 0x4,
+ // Address translation instructions (eg AT S1E0R_Xt) need to be
handled
+ // in special ways during translation because they could need to
act
+ // like a different EL than the current EL. The following flags are
+ // for these instructions
+ S1E0Tran = 0x8,
+ S1E1Tran = 0x10,
+ S1E2Tran = 0x20,
+ S1E3Tran = 0x40,
+ S12E0Tran = 0x80,
+ S12E1Tran = 0x100
+ };

- bool isStage2; // The TLB is part of the Stage 2 MMU
- uint8_t level; // TLB level
+ /**
+ * Determine the EL to use for the purpose of a translation given
+ * a specific translation type. If the translation type doesn't
+ * specify an EL, we use the current EL.
+ */
+ static ExceptionLevel tranTypeEL(CPSR cpsr, ArmTranslationType type);

- Cycles access_latency;
+ protected:
+ std::vector<TlbEntryRepl> table; // the Page Table
+ int size; // TLB Size
+ unsigned int assoc; // Associativity of the TLB
+ bool isStage2; // Indicates this TLB is part of the second stage
MMU
+ bool stage2Req; // Indicates whether a stage 2 lookup is also
required
+ // Indicates whether a stage 2 lookup of the table descriptors is
required.
+ // Certain address translation instructions will intercept the IPA but
the
+ // table descriptors still need to be translated by the stage2.
+ bool stage2DescReq;
+ uint64_t _attr; // Memory attributes for last accessed TLB entry
+ bool directToStage2; // Indicates whether all translation requests
should
+ // be routed directly to the stage 2 TLB
+ const uint8_t level; // TLB level
+ const bool allowPartial; // Allow storing partial translations

- TLB *next_tlb;
- TLB *stage2Tlb;
- TableWalker *tableWalker;
- MMU *mmu;
+ const Cycles access_latency;

- TlbTestInterface *test;
+ BaseIndexingPolicy *indexingPolicy;
+ BaseReplacementPolicy *replacementPolicy;

- // Access Stats
- mutable Stats::Scalar instHits;
- mutable Stats::Scalar instMisses;
- mutable Stats::Scalar readHits;
- mutable Stats::Scalar readMisses;
- mutable Stats::Scalar writeHits;
- mutable Stats::Scalar writeMisses;
- mutable Stats::Scalar partialHits;
- mutable Stats::Scalar partialMisses;
- mutable Stats::Scalar inserts;
- mutable Stats::Scalar flushTlb;
- mutable Stats::Scalar flushTlbMva;
- mutable Stats::Scalar flushTlbMvaAsid;
- mutable Stats::Scalar flushTlbAsid;
- mutable Stats::Scalar flushedEntries;
- mutable Stats::Scalar alignFaults;
- mutable Stats::Scalar prefetchFaults;
- mutable Stats::Scalar domainFaults;
- mutable Stats::Scalar permsFaults;
+ TableWalker *tableWalker;
+ TLB *stage2Tlb;
+ TLB *next_tlb;
+ MMU *mmu;

- Stats::Formula readAccesses;
- Stats::Formula writeAccesses;
- Stats::Formula instAccesses;
- Stats::Formula hits;
- Stats::Formula misses;
- Stats::Formula accesses;
- Stats::Formula partialAccesses;
+ TlbTestInterface *test;

- uint64_t _attr; // Memory attributes for last accessed TLB entry
+ // Access Stats
+ mutable Stats::Scalar instHits;
+ mutable Stats::Scalar instMisses;
+ mutable Stats::Scalar readHits;
+ mutable Stats::Scalar readMisses;
+ mutable Stats::Scalar writeHits;
+ mutable Stats::Scalar writeMisses;
+ mutable Stats::Scalar inserts;
+ mutable Stats::Scalar flushTlb;
+ mutable Stats::Scalar flushTlbMva;
+ mutable Stats::Scalar flushTlbMvaAsid;
+ mutable Stats::Scalar flushTlbAsid;
+ mutable Stats::Scalar flushedEntries;
+ mutable Stats::Scalar alignFaults;
+ mutable Stats::Scalar prefetchFaults;
+ mutable Stats::Scalar domainFaults;
+ mutable Stats::Scalar permsFaults;
+ mutable Stats::Scalar partialHits;
+ mutable Stats::Scalar partialMisses;

- public:
+ Stats::Formula readAccesses;
+ Stats::Formula writeAccesses;
+ Stats::Formula instAccesses;
+ Stats::Formula hits;
+ Stats::Formula misses;
+ Stats::Formula accesses;
+ Stats::Formula partialAccesses;

- enum ArmFlags {
- AlignmentMask = 0x7,
+ /** PMU probe for TLB refills */
+ ProbePoints::PMUUPtr ppRefills;

- AlignByte = 0x0,
- AlignHalfWord = 0x1,
- AlignWord = 0x2,
- AlignDoubleWord = 0x3,
- AlignQuadWord = 0x4,
- AlignOctWord = 0x5,
+ int rangeMRU; //On lookup, only move entries ahead when outside
rangeMRU

- AllowUnaligned = 0x8,
- // Priv code operating as if it wasn't
- UserMode = 0x10,
- // Because zero otherwise looks like a valid setting
- // and may be used accidentally, this bit must be
- // non-zero to show it was used on purpose.
- MustBeOne = 0x40
- };
+ public:
+ TLB(const ArmTLBParams *p);
+ TLB(const Params *p, int _size, TableWalker *_walker);

- enum ArmTranslationType {
- NormalTran = 0,
- S1CTran = 0x1,
- HypMode = 0x2,
- // Secure code operating as if it wasn't (required by some
Address
- // Translate operations)
- S1S2NsTran = 0x4,
- // Address translation instructions (eg AT S1E0R_Xt) need to be
- // handled in special ways during translation because they
could
- // need to act like a different EL than the current EL.
- // The following flags are for these instructions
- S1E0Tran = 0x8,
- S1E1Tran = 0x10,
- S1E2Tran = 0x20,
- S1E3Tran = 0x40,
- S12E0Tran = 0x80,
- S12E1Tran = 0x100
- };
+ virtual ~TLB();

- enum LookupStatus {
- TLB_HIT,
- TLB_MISS,
- PAGE_WALK,
- UNDEFINED
- };
+ void takeOverFrom(BaseTLB *otlb) override;

- bool is_stage2() {
- return isStage2;
- }
+ void setTestInterface(SimObject *ti);

- private:
+ TableWalker *getTableWalker() { return tableWalker; }

- // Cached registers
- Addr ttbr0_el1;
- Addr ttbr1_el1;
- Addr vttbr_el2;
+ void setMMU(MMU*, MasterID);

- bool stage2Req; // Whether a stage 2 lookup is also required
- bool directToStage2; // Whether all translation requests should be
- // routed directly to the stage 2 TLB
+ int getsize() const { return size; }

- CPSR cpsr;
- bool aarch64;
- ExceptionLevel aarch64EL;
- SCTLR sctlr;
- SCR scr;
- bool isPriv;
- bool isSecure;
- bool isHyp;
- TTBCR ttbcr;
- HTCR htcr;
- uint16_t asid;
- uint8_t vmid;
- PRRR prrr;
- NMRR nmrr;
- HCR hcr;
- uint64_t mair;
- uint64_t hcr_el2;
- uint32_t dacr;
- ContextID miscRegContext;
- bool miscRegValid;
- TLB::ArmTranslationType curTranType;
+ /** Reset the entire TLB
+ * @param secure_lookup if the operation affects the secure world
+ */
+ void flushAllSecurity(bool secure_lookup, uint8_t target_el,
+ bool ignore_el = false);

- // Cached copies of system-level properties
- bool haveLPAE;
- bool haveVirtualization;
- bool haveLargeAsid64;
+ /** Remove all entries in the non secure world, depending on whether
they
+ * were allocated in hyp mode or not
+ * @param hyp if the opperation affects hyp mode
+ */
+ void flushAllNs(bool hyp, uint8_t target_el, bool ignore_el = false);

- protected:

- void updateMiscReg(ThreadContext *tc,
- ArmTranslationType tranType = NormalTran);
+ /** Reset the entire TLB. Used for CPU switching to prevent stale
+ * translations after multiple switches
+ */
+ void flushAll() override
+ {
+ flushAllSecurity(false, 0, true);
+ flushAllSecurity(true, 0, true);
+ }

- public:
+ /** Remove any entries that match both a va and asn
+ * @param mva virtual address to flush
+ * @param asn contextid/asn to flush on match
+ * @param secure_lookup if the operation affects the secure world
+ */
+ void flushMvaAsid(Addr mva, uint64_t asn, bool secure_lookup,
+ uint8_t target_el);

- class CpuSidePort : public SlavePort
- {
- public:
- CpuSidePort(const std::string &_name, TLB *_tlb, PortID
_index)
- : SlavePort(_name, _tlb), tlb(_tlb), index(_index){}
+ /** Remove any entries that match the asn
+ * @param asn contextid/asn to flush on match
+ * @param secure_lookup if the operation affects the secure world
+ */
+ void flushAsid(uint64_t asn, bool secure_lookup, uint8_t target_el);

- protected:
- TLB *tlb;
- int index;
+ /** Remove all entries that match the va regardless of asn
+ * @param mva address to flush from cache
+ * @param secure_lookup if the operation affects the secure world
+ * @param hyp if the operation affects hyp mode
+ */
+ void flushMva(Addr mva, bool secure_lookup, bool hyp, uint8_t
target_el);

- virtual bool recvTimingReq(PacketPtr pkt);
- virtual Tick recvAtomic(PacketPtr pkt);
- virtual void recvFunctional(PacketPtr pkt) { };
- virtual void recvRangeChange() { };
- virtual void recvReqRetry();
- virtual void recvRespRetry();
- virtual AddrRangeList getAddrRanges() const
- {
- AddrRangeList range;
- return range;
- }
- };
+ /**
+ * Invalidate all entries in the stage 2 TLB that match the given ipa
+ * and the current VMID
+ * @param ipa the address to invalidate
+ * @param secure_lookup if the operation affects the secure world
+ * @param hyp if the operation affects hyp mode
+ */
+ void flushIpaVmid(Addr ipa, bool secure_lookup, bool hyp,
+ uint8_t target_el);

- class MemSidePort : public MasterPort
- {
- public:
- MemSidePort(const std::string &_name, TLB *_tlb, PortID
_index)
- : MasterPort(_name, _tlb), tlb(_tlb), index(_index){}
+ Fault trickBoxCheck(const RequestPtr &req, Mode mode,
+ TlbEntry::DomainType domain);

- std::deque<PacketPtr> retries;
-
- protected:
- TLB *tlb;
- int index;
-
- virtual bool recvTimingResp(PacketPtr pkt);
- virtual Tick recvAtomic(PacketPtr pkt);
- virtual void recvFunctional(PacketPtr pkt) { };
- virtual void recvRangeChange() { };
- virtual void recvReqRetry();
- };
-
- std::vector<CpuSidePort*> cpuSidePort;
- MemSidePort* memSidePort;
-
- class TLBEvent;
-
- struct TranslationState
- {
- /** Pointer to the TLBRecord used in the stage 1 translation */
- TLBRecordPtr s1;
- /** Pointer to the TLBRecord used in the stage 2 translation */
- TLBRecordPtr s2;
-
- bool timing;
- bool functional;
-
- RequestPtr req;
- ThreadContext *tc;
- BaseTLB::Mode mode;
- ArmTranslationType tranType;
-
- Addr vaddress;
- Addr ipaddress;
- Addr s1_physaddr;
- Addr s2_physaddr;
- AccType acctype;
- bool wasaligned;
- bool hwupdatewalk;
- bool s2fs1walk;
- int size;
- ExceptionLevel aarch64EL;
-
- bool aarch64;
- bool isHyp;
- bool _isPriv;
- bool isSecure;
- bool stage2Req;
- bool usingLongDescFormat;
-
- uint16_t asid;
- uint8_t vmid;
-
- bool delayed;
- bool finished;
- bool s1_enabled;
- bool s2_enabled;
- bool stage2lookup;
- bool stage2lookupDone;
-
- bool permissioncheck;
- bool domaincheck;
-
- TlbEntry::DomainType domain;
-
- /** Cached system registers */
- CPSR cpsr;
- SCTLR sctlr;
- SCR scr;
- union {
- TTBCR ttbcr;
- TCR tcr;
- };
- HTCR htcr;
- Addr ttbr0_el1;
- Addr ttbr1_el1;
- uint64_t mair;
- uint32_t dacr;
- HCR hcr;
- PRRR prrr;
- NMRR nmrr;
-
- Fault fault;
- ArmFault::TranMethod tranMethod;
-
- /** Flag to indicate if we are returning from a page walk */
- bool fromPTW;
-
- /** Pointer to the TLB starting the translation */
- TLB *tlb;
- /** Pointer to the Stage 2 TLB to be used for a stage 2 lookup
*/
- TLB *stage2Tlb;
-
- /** Remember the port this came from */
- std::vector<SlavePort*>ports;
-
- Translation *translation;
-
- Cycles latency;
-
- /** Pointer to the TLB entry in a lower level to use in a fill
*/
- TlbEntryPtr s1te;
- TlbEntryPtr s2te;
-
- Tick start;
- Addr pc;
-
- Addr ptw_desc_addr;
- uint64_t ptw_desc_value;
-
- /** Flag indicating if we are returning from a walk which was
- * squashed */
- bool walkSquashed;
-
- void tickLimitReached();
- EventFunctionWrapper* tickLimitReachedEvent;
-
- bool isFetch() {
- return (mode == Execute);
- }
- bool isPrefetch() {
- return req->isPrefetch();
- }
- bool isWrite() {
- return (mode == Write);
- }
- bool accessIsPrivileged() {
- return (_isPriv && !(req->getFlags() &
ArmFlags::UserMode));
- }
-
- // Return TRUE if the request is of the specified 'AccType'
- // FALSE otherwise
- bool hasAcctype(AccType);
-
- bool isPartial;
-
- TranslationState(TLB*);
- ~TranslationState();
- };
-
- typedef std::shared_ptr<TranslationState> TranslationStatePtr;
-
- // Wrapper struct to use with the send/recv functions. Only the
- // SenderState class can be used to transfer information so we
need a
- // struct that can be cast to its type
- struct TranslationSender : public Packet::SenderState
- {
- TranslationStatePtr tran;
-
- TranslationSender(TranslationStatePtr _tran) : tran(_tran) {
- }
- };
-
- // This function will be called N cycles after the lookup depending
- // if it was hit or miss and take the aproppiate action. In a TLB
miss
- // the request will be sent to the next TLB level (if any) or issue
- // a table walk if this is the last TLB level
- void lookupReturn(TranslationStatePtr, LookupStatus);
-
- // Finalize the translation setting the request physical address
- Fault finalizeTranslation(TranslationStatePtr);
-
- class TLBEvent : public Event
- {
- private:
- TLB *tlb;
- TranslationStatePtr tran;
- LookupStatus status;
-
- public:
- TLBEvent(TLB*, TranslationStatePtr, LookupStatus);
- void process();
- void updateStatus(LookupStatus _status) {
- status = _status;
- }
- TLB* getTLB() {
- return tlb;
- }
- TranslationStatePtr getTranslation() {
- return tran;
- }
- Addr getPC() {
- return tran->req->getPC();
- }
- };
-
- std::vector<TLBEvent*> translationReturnEvent;
-
- // Schedule event for the specified address and lookup status
- void scheduleEvent(TranslationStatePtr, LookupStatus);
-
- void cleanupEvent(TLBEvent*);
-
- void sendTimingResponse(TranslationStatePtr);
-
- BaseMasterPort&
- getMasterPort(const std::string &if_name, PortID idx) override;
- BaseSlavePort&
- getSlavePort(const std::string &if_name, PortID idx) override;
-
- void setTestInterface(SimObject *ti);
-
- void setMMU(MMU*, MasterID);
-
- MMU* getMMU() { return mmu; }
-
- inline void invalidateMiscReg() { miscRegValid = false; }
-
- bool checkELMatch(uint8_t, uint8_t, bool);
-
- /** Reset the entire TLB
- * @param secure_lookup if the operation affects the secure world
- */
- void flushAllSecurity(bool, uint8_t, bool ignore_el = false);
-
- /** Remove all entries in the non secure world, depending on
whether
- * they were allocated in hyp mode or not
- * @param hyp if the opperation affects hyp mode
- */
- void flushAllNs(bool, uint8_t, bool ignore_el = false);
-
- /** Reset the entire TLB. Used for CPU switching to prevent stale
- * translations after multiple switches
- */
- void flushAll() override
- {
- flushAllSecurity(false, 0, true);
- flushAllSecurity(true, 0, true);
- }
-
- /** Remove any entries that match both a va and asn
- * @param mva virtual address to flush
- * @param asn contextid/asn to flush on match
- * @param secure_lookup if the operation affects the secure world
- */
- void flushMvaAsid(Addr, uint64_t, bool, uint8_t);
-
- /** Remove any entries that match the asn
- * @param asn contextid/asn to flush on match
- * @param secure_lookup if the operation affects the secure world
- */
- void flushAsid(uint64_t asn, bool secure_lookup, uint8_t
target_el);
-
- /** Remove all entries that match the va regardless of asn
- * @param mva address to flush from cache
- * @param secure_lookup if the operation affects the secure world
- * @param hyp if the operation affects hyp mode
- */
- void flushMva(Addr mva, bool secure_lookup, bool hyp,
- uint8_t target_el);
-
- void _flushMva(Addr, uint64_t, bool, bool, bool, uint8_t);
+ Fault walkTrickBoxCheck(Addr pa, bool is_secure, Addr va, Addr sz,
+ bool is_exec, bool is_write,
+ TlbEntry::DomainType domain,
+ LookupLevel lookup_level);

- /**
- * Invalidate all entries in the stage 2 TLB that match the given
ipa
- * and the current VMID
- * @param ipa the address to invalidate
- * @param secure_lookup if the operation affects the secure world
- * @param hyp if the operation affects hyp mode
- */
- void flushIpaVmid(Addr ipa, bool secure_lookup, bool hyp,
- uint8_t target_el);
+ void printTlb() const;

- void demapPage(Addr vaddr, uint64_t asn) override
- {
- // needed for x86 only
- panic("%s: not implemented", __func__);
- }
+ void demapPage(Addr vaddr, uint64_t asn) override
+ {
+ // needed for x86 only
+ panic("demapPage() is not implemented.\n");
+ }

- /**
- * Do a functional lookup on the TLB (for debugging)
- * and don't modify any internal state
- * @param tc thread context to get the context id from
- * @param vaddr virtual address to translate
- * @param pa returned physical address
- * @return if the translation was successful
- */
- bool translateFunctional(ThreadContext *tc, Addr vaddr, Addr
&paddr);
+ /**
+ * Do a functional lookup on the TLB (for debugging)
+ * and don't modify any internal state
+ * @param tc thread context to get the context id from
+ * @param vaddr virtual address to translate
+ * @param pa returned physical address
+ * @return if the translation was successful
+ */
+ bool translateFunctional(ThreadContext *tc, Addr vaddr, Addr &paddr);

- /**
- * Do a functional lookup on the TLB (for checker cpu) that
- * behaves like a normal lookup without modifying any page table
state.
- */
- Fault translateFunctional(const RequestPtr &req, ThreadContext *tc,
+ /**
+ * Do a functional lookup on the TLB (for checker cpu) that
+ * behaves like a normal lookup without modifying any page table state.
+ */
+ Fault translateFunctional(const RequestPtr &req, ThreadContext *tc,
Mode mode, ArmTranslationType tranType);
- Fault translateFunctional(
- const RequestPtr &req, ThreadContext *tc, Mode mode) override
- {
- return translateFunctional(req, tc, mode, NormalTran);
- }
+ Fault
+ translateFunctional(const RequestPtr &req,
+ ThreadContext *tc, Mode mode) override
+ {
+ return translateFunctional(req, tc, mode, NormalTran);
+ }

- Fault translateFs(const RequestPtr &req, ThreadContext *tc, Mode
mode,
- Translation *translation, bool &delay, bool timing,
- ArmTranslationType tranType, bool functional = false);
+ /** Accessor functions for memory attributes for last accessed TLB
entry
+ */
+ void
+ setAttr(uint64_t attr)
+ {
+ _attr = attr;
+ }

- Fault translateSe(const RequestPtr &req, ThreadContext *tc, Mode
mode,
+ uint64_t
+ getAttr() const
+ {
+ return _attr;
+ }
+
+ Fault translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
+ Translation *translation, bool &delay,
+ bool timing, ArmTranslationType tranType, bool functional =
false);
+ Fault translateSe(const RequestPtr &req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing);
-
- Fault translateAtomic(const RequestPtr &req, ThreadContext *tc,
- Mode mode, ArmTranslationType tranType,
TLB::TranslationStatePtr);
-
- Fault translateAtomic(
- const RequestPtr &req, ThreadContext *tc, Mode mode) override
- {
- return translateAtomic(req, tc, mode, NormalTran, NULL);
- }
-
- void translateTiming(const RequestPtr &req, ThreadContext *tc,
- Translation *translation, Mode mode, ArmTranslationType
tranType);
-
- void translateTiming(
- const RequestPtr &req, ThreadContext *tc, Translation
*translation,
- Mode mode) override
- {
- translateTiming(req, tc, translation, mode, NormalTran);
- }
-
- Fault translateComplete(const RequestPtr &req, ThreadContext *tc,
+ Fault translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode
mode,
+ ArmTranslationType tranType);
+ Fault
+ translateAtomic(const RequestPtr &req,
+ ThreadContext *tc, Mode mode) override
+ {
+ return translateAtomic(req, tc, mode, NormalTran);
+ }
+ void translateTiming(
+ const RequestPtr &req, ThreadContext *tc,
+ Translation *translation, Mode mode,
+ ArmTranslationType tranType);
+ void
+ translateTiming(const RequestPtr &req, ThreadContext *tc,
+ Translation *translation, Mode mode) override
+ {
+ translateTiming(req, tc, translation, mode, NormalTran);
+ }
+ Fault translateComplete(const RequestPtr &req, ThreadContext *tc,
Translation *translation, Mode mode, ArmTranslationType
tranType,
bool callFromS2);
+ Fault finalizePhysical(
+ const RequestPtr &req,
+ ThreadContext *tc, Mode mode) const override;

- Fault finalizePhysical(
- const RequestPtr &req, ThreadContext *tc, Mode mode) const
override
- {
- panic("%s: not implemented", __func__);
- return 0;
+ void drainResume() override;
+
+ void regStats() override;
+
+ void regProbePoints() override;
+
+ // Caching misc register values here.
+ // Writing to misc registers needs to invalidate them.
+ // translateFunctional/translateSe/translateFs checks if they are
+ // invalid and call updateMiscReg if necessary.
+protected:
+ CPSR cpsr;
+ bool aarch64;
+ ExceptionLevel aarch64EL;
+ SCTLR sctlr;
+ SCR scr;
+ bool isPriv;
+ bool isSecure;
+ bool isHyp;
+ TTBCR ttbcr;
+ uint16_t asid;
+ uint8_t vmid;
+ PRRR prrr;
+ NMRR nmrr;
+ HCR hcr;
+ uint32_t dacr;
+ bool miscRegValid;
+ ContextID miscRegContext;
+ ArmTranslationType curTranType;
+
+ // Cached copies of system-level properties
+ bool haveLPAE;
+ bool haveVirtualization;
+ bool haveLargeAsid64;
+
+ AddrRange m5opRange;
+
+ Addr ttbr0_el1;
+ Addr ttbr1_el1;
+ Addr vttbr_el2;
+
+ HTCR htcr;
+ uint64_t mair;
+ uint64_t hcr_el2;
+
+ void updateMiscReg(ThreadContext *tc,
+ ArmTranslationType tranType = NormalTran);
+
+public:
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(_params);
+ }
+ inline void invalidateMiscReg() { miscRegValid = false; }
+
+private:
+ /** Remove any entries that match both a va and asn
+ * @param mva virtual address to flush
+ * @param asn contextid/asn to flush on match
+ * @param secure_lookup if the operation affects the secure world
+ * @param hyp if the operation affects hyp mode
+ * @param ignore_asn if the flush should ignore the asn
+ */
+ void _flushMva(Addr mva, uint64_t asn, bool secure_lookup,
+ bool hyp, bool ignore_asn, uint8_t target_el);
+
+ bool checkELMatch(uint8_t target_el, uint8_t tentry_el, bool
ignore_el);
+
+ public: /* Testing */
+ Fault testTranslation(const RequestPtr &req, Mode mode,
+ TlbEntry::DomainType domain);
+ Fault testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode,
+ TlbEntry::DomainType domain,
+ LookupLevel lookup_level);
+
+ enum LookupStatus {
+ TLB_HIT,
+ TLB_MISS,
+ PAGE_WALK,
+ UNDEFINED
+ };
+
+ bool is_stage2() {
+ return isStage2;
+ }
+
+ class CpuSidePort : public SlavePort
+ {
+ public:
+ CpuSidePort(const std::string &_name, TLB *_tlb, PortID _index)
+ : SlavePort(_name, _tlb), tlb(_tlb), index(_index){}
+
+ protected:
+ TLB *tlb;
+ int index;
+
+ virtual bool recvTimingReq(PacketPtr pkt);
+ virtual Tick recvAtomic(PacketPtr pkt);
+ virtual void recvFunctional(PacketPtr pkt) { };
+ virtual void recvRangeChange() { };
+ virtual void recvReqRetry();
+ virtual void recvRespRetry();
+ virtual AddrRangeList getAddrRanges() const
+ {
+ AddrRangeList range;
+ return range;
+ }
+ };
+
+ class MemSidePort : public MasterPort
+ {
+ public:
+ MemSidePort(const std::string &_name, TLB *_tlb, PortID _index)
+ : MasterPort(_name, _tlb), tlb(_tlb), index(_index){}
+
+ std::deque<PacketPtr> retries;
+
+ protected:
+ TLB *tlb;
+ int index;
+
+ virtual bool recvTimingResp(PacketPtr pkt);
+ virtual Tick recvAtomic(PacketPtr pkt);
+ virtual void recvFunctional(PacketPtr pkt) { };
+ virtual void recvRangeChange() { };
+ virtual void recvReqRetry();
+ };
+
+ std::vector<CpuSidePort*> cpuSidePort;
+ MemSidePort* memSidePort;
+
+ class TLBEvent;
+
+ struct TranslationState
+ {
+ /** Pointer to the TLBRecord used in the stage 1 translation */
+ TLBRecordPtr s1;
+ /** Pointer to the TLBRecord used in the stage 2 translation */
+ TLBRecordPtr s2;
+
+ bool timing;
+ bool functional;
+
+ RequestPtr req;
+ ThreadContext *tc;
+ BaseTLB::Mode mode;
+ ArmTranslationType tranType;
+
+ Addr vaddress;
+ Addr ipaddress;
+ Addr s1_physaddr;
+ Addr s2_physaddr;
+ AccType acctype;
+ bool wasaligned;
+ bool hwupdatewalk;
+ bool s2fs1walk;
+ int size;
+ ExceptionLevel aarch64EL;
+
+ bool aarch64;
+ bool isHyp;
+ bool _isPriv;
+ bool isSecure;
+ bool stage2Req;
+ bool usingLongDescFormat;
+
+ uint16_t asid;
+ uint8_t vmid;
+
+ bool delayed;
+ bool finished;
+ bool s1_enabled;
+ bool s2_enabled;
+ bool stage2lookup;
+ bool stage2lookupDone;
+
+ bool permissioncheck;
+ bool domaincheck;
+
+ TlbEntry::DomainType domain;
+
+ /** Cached system registers */
+ CPSR cpsr;
+ SCTLR sctlr;
+ SCR scr;
+ union {
+ TTBCR ttbcr;
+ TCR tcr;
+ };
+ HTCR htcr;
+ Addr ttbr0_el1;
+ Addr ttbr1_el1;
+ uint64_t mair;
+ uint32_t dacr;
+ HCR hcr;
+ PRRR prrr;
+ NMRR nmrr;
+
+ Fault fault;
+ ArmFault::TranMethod tranMethod;
+
+ /** Flag to indicate if we are returning from a page walk */
+ bool fromPTW;
+
+ /** Pointer to the TLB starting the translation */
+ TLB *tlb;
+ /** Pointer to the Stage 2 TLB to be used for a stage 2 lookup */
+ TLB *stage2Tlb;
+
+ /** Remember the port this came from */
+ std::vector<SlavePort*>ports;
+
+ Translation *translation;
+
+ Cycles latency;
+
+ /** Pointer to the TLB entry in a lower level to use in a fill */
+ TlbEntryPtr s1te;
+ TlbEntryPtr s2te;
+
+ Tick start;
+ Addr pc;
+
+ Addr ptw_desc_addr;
+ uint64_t ptw_desc_value;
+
+ /** Flag indicating if we are returning from a walk which was
+ * squashed */
+ bool walkSquashed;
+
+ void tickLimitReached();
+ EventFunctionWrapper* tickLimitReachedEvent;
+
+ bool isFetch() {
+ return (mode == Execute);
+ }
+ bool isPrefetch() {
+ return req->isPrefetch();
+ }
+ bool isWrite() {
+ return (mode == Write);
+ }
+ bool accessIsPrivileged() {
+ return (_isPriv && !(req->getFlags() & ArmFlags::UserMode));
}

- static ExceptionLevel tranTypeEL(CPSR, ArmTranslationType);
-
- void drainResume() override;
-
- void regStats() override;
-
- /* Accessor functions for memory attributes for last accessed
- * TLB entry
- */
- void
- setAttr(uint64_t attr)
- {
- _attr = attr;
- }
-
- uint64_t
- getAttr() const
- {
- return _attr;
- }
-
- void takeOverFrom(BaseTLB *otlb) override
- {
- panic("%s: not implemented", __func__);
- }
-
- typedef ArmTLBParams Params;
- TLB(const Params *p);
- virtual ~TLB();
-
- // Update the misc registers in the TranslationState structure
- void updateTranslationRegisters(TranslationStatePtr);
-
- protected:
-
- Fault permissionFault(TranslationStatePtr);
-
- void stage2lookup(TranslationStatePtr);
-
- // Creates a basic access descriptor
- AccessDescriptor* createAccessDescriptor(AccType);
- AccessDescriptor* createAccessDescriptorPTW(AccType, bool, bool,
int);
-
- // Perform a stage 1 translation. It will use the cached values in
the
- // TLB if a valid entry is found, issue a table walk if not
- void firstStageTranslate32(TranslationStatePtr);
- void firstStageTranslate64(TranslationStatePtr);
-
- // Perform a stage 2 translation. It will use the cached values in
the
- // TLB if a valid entry is found, issue a table walk if not
- void secondStageTranslate(TranslationStatePtr);
-
- // Called for stage 1 translations when translation is enabled.
Will
- // launch a page walk if miss in all TLB levels
- void translateAddressOn(TranslationStatePtr);
-
- // Called for stage 1 translations when translation is disabled to
- // supply a default translation
- void translateAddressS1Off32(TranslationStatePtr);
- void translateAddressS1Off64(TranslationStatePtr);
-
- Fault checkPermissions64(TranslationStatePtr);
- Fault checkPermissions(TranslationStatePtr);
-
- // Permission checking from AArch64 stage 1 and 2 translations
- Fault checkS1Permission32(TranslationStatePtr);
- Fault checkS1Permission64(TranslationStatePtr);
- Fault checkS2Permission32(TranslationStatePtr);
- Fault checkS2Permission64(TranslationStatePtr);
-
- // Domain checking for AArch32 stage 1 translations
- Fault checkDomain(TranslationStatePtr);
-
- // Combines the address descriptors from stage 1 and stage 2
- AddressDescriptorPtr combineS1S2Desc(AddressDescriptorPtr,
- AddressDescriptorPtr);
- // Combines device types from stage 1 and stage 2
- DeviceType combineS1S2Device(DeviceType, DeviceType);
- MemAttrHints combineS1S2AttrHints(MemAttrHints, MemAttrHints);
-
- public:
-
- // Return a TRUE if a valid entry for the translation is found in
the
- // TLB and update the record field in TranslationState structure.
+ // Return TRUE if the request is of the specified 'AccType'
// FALSE otherwise
- bool lookup(TranslationStatePtr, bool,
- bool update_alloc=true, bool from_ptw=false);
+ bool hasAcctype(AccType);

- // Insert an entry for the specified address
- void insert(TranslationStatePtr, bool from_ptw=false);
+ bool isPartial;

- // Supply default values for memory attributes, including
overriding
- // the shareability attributes for Device and Non-cacheable memory
- // types
- static void memAttrDefaults(MemoryAttributes*);
+ TranslationState(TLB*);
+ ~TranslationState();
+ };

- static
- AddressDescriptorPtr initAddressDescriptor()
- {
- AddressDescriptorPtr d = std::make_shared<AddressDescriptor>();
- d->fault = NoFault;
- d->memattrs = new MemoryAttributes;
- return d;
+ typedef std::shared_ptr<TranslationState> TranslationStatePtr;
+
+ // Wrapper struct to use with the send/recv functions. Only the
+ // SenderState class can be used to transfer information so we need a
+ // struct that can be cast to its type
+ struct TranslationSender : public Packet::SenderState
+ {
+ TranslationStatePtr tran;
+
+ TranslationSender(TranslationStatePtr _tran) : tran(_tran) {
}
+ };

- static
- DescriptorUpdate* initDescriptorUpdate()
- {
- DescriptorUpdate *d = new DescriptorUpdate;
- d->AF = false;
- d->AP = false;
- d->descaddr = initAddressDescriptor();
- return d;
- }
+ Fault checkPermissions(TranslationStatePtr);
+ Fault checkPermissions64(TranslationStatePtr);

- static
- TLBRecordPtr initTLBRecord()
- {
- TLBRecordPtr r = std::make_shared<TLBRecord>();
- r->descupdate = initDescriptorUpdate();
- r->addrdesc = initAddressDescriptor();
- return r;
- }
+ // This function will be called N cycles after the lookup depending
+ // if it was hit or miss and take the aproppiate action. In a TLB miss
+ // the request will be sent to the next TLB level (if any) or issue
+ // a table walk if this is the last TLB level
+ void lookupReturn(TranslationStatePtr, LookupStatus);

- static
- TLBRecordPtr initTLBRecord(AddressDescriptorPtr addrdesc)
- {
- TLBRecordPtr r = std::make_shared<TLBRecord>();
- r->descupdate = initDescriptorUpdate();
- r->addrdesc = addrdesc;
- return r;
- }
+ // Finalize the translation setting the request physical address
+ Fault finalizeTranslation(TranslationStatePtr);

- TLB* getStage2TLB() {
- return stage2Tlb;
- }
+ class TLBEvent : public Event
+ {
+ private:
+ TLB *tlb;
+ TranslationStatePtr tran;
+ LookupStatus status;

- void printTLB();
+ public:
+ TLBEvent(TLB*, TranslationStatePtr, LookupStatus);
+ void process();
+ void updateStatus(LookupStatus _status) {
+ status = _status;
+ }
+ TLB* getTLB() {
+ return tlb;
+ }
+ TranslationStatePtr getTranslation() {
+ return tran;
+ }
+ Addr getPC() {
+ return tran->req->getPC();
+ }
+ };

- public: /* Testing */
+ std::vector<TLBEvent*> translationReturnEvent;

- Fault testTranslation(RequestPtr req, Mode mode,
- TlbEntry::DomainType domain);
- Fault testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode
mode,
- TlbEntry::DomainType domain,
- LookupLevel lookup_level);
+ // Schedule event for the specified address and lookup status
+ void scheduleEvent(TranslationStatePtr, LookupStatus);
+
+ void cleanupEvent(TLBEvent*);
+
+ void sendTimingResponse(TranslationStatePtr);
+
+ BaseMasterPort&
+ getMasterPort(const std::string &if_name, PortID idx) override;
+ BaseSlavePort&
+ getSlavePort(const std::string &if_name, PortID idx) override;
+
+ MMU* getMMU() { return mmu; }
+
+ typedef ArmTLBParams Params;
+
+ // Update the misc registers in the TranslationState structure
+ void updateTranslationRegisters(TranslationStatePtr);
+
+protected:
+
+ Fault permissionFault(TranslationStatePtr);
+
+ void stage2lookup(TranslationStatePtr);
+
+ // Creates a basic access descriptor
+ AccessDescriptor* createAccessDescriptor(AccType);
+ AccessDescriptor* createAccessDescriptorPTW(AccType, bool, bool, int);
+
+ // Perform a stage 1 translation. It will use the cached values in the
+ // TLB if a valid entry is found, issue a table walk if not
+ void firstStageTranslate32(TranslationStatePtr);
+ void firstStageTranslate64(TranslationStatePtr);
+
+ // Perform a stage 2 translation. It will use the cached values in the
+ // TLB if a valid entry is found, issue a table walk if not
+ void secondStageTranslate(TranslationStatePtr);
+
+ // Called for stage 1 translations when translation is enabled. Will
+ // launch a page walk if miss in all TLB levels
+ void translateAddressOn(TranslationStatePtr);
+
+ // Called for stage 1 translations when translation is disabled to
+ // supply a default translation
+ void translateAddressS1Off32(TranslationStatePtr);
+ void translateAddressS1Off64(TranslationStatePtr);
+
+ // Permission checking from AArch64 stage 1 and 2 translations
+ Fault checkS1Permission32(TranslationStatePtr);
+ Fault checkS1Permission64(TranslationStatePtr);
+ Fault checkS2Permission32(TranslationStatePtr);
+ Fault checkS2Permission64(TranslationStatePtr);
+
+ // Domain checking for AArch32 stage 1 translations
+ Fault checkDomain(TranslationStatePtr);
+
+ // Combines the address descriptors from stage 1 and stage 2
+ AddressDescriptorPtr combineS1S2Desc(AddressDescriptorPtr,
+ AddressDescriptorPtr);
+ // Combines device types from stage 1 and stage 2
+ DeviceType combineS1S2Device(DeviceType, DeviceType);
+ MemAttrHints combineS1S2AttrHints(MemAttrHints, MemAttrHints);
+
+public:
+
+ // Return a TRUE if a valid entry for the translation is found in the
+ // TLB and update the record field in TranslationState structure.
+ // FALSE otherwise
+ bool lookup(TranslationStatePtr, bool,
+ bool update_alloc=true, bool from_ptw=false);
+
+ // Insert an entry for the specified address
+ void insert(TranslationStatePtr, bool from_ptw=false);
+
+ // Supply default values for memory attributes, including overriding
+ // the shareability attributes for Device and Non-cacheable memory
+ // types
+ static void memAttrDefaults(MemoryAttributes*);
+
+ static
+ AddressDescriptorPtr initAddressDescriptor()
+ {
+ AddressDescriptorPtr d = std::make_shared<AddressDescriptor>();
+ d->fault = NoFault;
+ d->memattrs = new MemoryAttributes;
+ return d;
+ }
+
+ static
+ DescriptorUpdate* initDescriptorUpdate()
+ {
+ DescriptorUpdate *d = new DescriptorUpdate;
+ d->AF = false;
+ d->AP = false;
+ d->descaddr = initAddressDescriptor();
+ return d;
+ }
+
+ static
+ TLBRecordPtr initTLBRecord()
+ {
+ TLBRecordPtr r = std::make_shared<TLBRecord>();
+ r->descupdate = initDescriptorUpdate();
+ r->addrdesc = initAddressDescriptor();
+ return r;
+ }
+
+ static
+ TLBRecordPtr initTLBRecord(AddressDescriptorPtr addrdesc)
+ {
+ TLBRecordPtr r = std::make_shared<TLBRecord>();
+ r->descupdate = initDescriptorUpdate();
+ r->addrdesc = addrdesc;
+ return r;
+ }
+
+ TLB* getStage2TLB() {
+ return stage2Tlb;
+ }
};

template<typename T>
diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc
index bf22c34..d30d54a 100644
--- a/src/arch/arm/utility.cc
+++ b/src/arch/arm/utility.cc
@@ -184,7 +184,7 @@
scr, tc->readMiscReg(MISCREG_CPSR));
}

-bool
+inline bool
isSecureBelowEL3(ThreadContext *tc)
{
SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
@@ -250,12 +250,6 @@
return aarch32;
}

-bool
-ELUsingAArch32(ThreadContext *tc, ExceptionLevel el)
-{
- return ELIs32(tc, el);
-}
-
std::pair<bool, bool>
ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
{
diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh
index dca1a79..3369698 100644
--- a/src/arch/arm/utility.hh
+++ b/src/arch/arm/utility.hh
@@ -175,8 +175,6 @@
std::pair<bool, bool>
ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el);

-bool ELUsingAArch32(ThreadContext *tc, ExceptionLevel el);
-
bool ELIs32(ThreadContext *tc, ExceptionLevel el);

bool ELIs64(ThreadContext *tc, ExceptionLevel el);
@@ -248,7 +246,7 @@
* Differs from inSecureState in that it ignores the current EL
* or Mode in considering security state.
*/
-bool isSecureBelowEL3(ThreadContext *tc);
+inline bool isSecureBelowEL3(ThreadContext *tc);

bool longDescFormatInUse(ThreadContext *tc);
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/14575
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: Ie6c4ae604f956ba93c2db535fc60f4e94b1379eb
Gerrit-Change-Number: 14575
Gerrit-PatchSet: 1
Gerrit-Owner: Ivan Pizarro <***@metempsy.com>
Gerrit-MessageType: newchange
Loading...