From 8d8e926b04702e891553198bed99ef55f018d160 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Mon, 21 Mar 2016 15:54:58 +0000 Subject: [PATCH] arm: Refactor the TLB test interface Refactor the TLB and page table walker test interface to use a dynamic registration mechanism. Instead of patching a couple of empty methods to wire up a TLB tester, this change allows such testers to register themselves using the setTestInterface() method. --- src/arch/arm/table_walker.cc | 41 +++++++++++++------------- src/arch/arm/table_walker.hh | 3 ++ src/arch/arm/tlb.cc | 57 ++++++++++++++++++++++++------------ src/arch/arm/tlb.hh | 52 +++++++++++++++++++++++++++++--- 4 files changed, 110 insertions(+), 43 deletions(-) diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index fd8645e97..e1e00442d 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -502,9 +502,8 @@ TableWalker::processWalk() // Trickbox address check Fault f; - f = tlb->walkTrickBoxCheck(l1desc_addr, currState->isSecure, - currState->vaddr, sizeof(uint32_t), currState->isFetch, - currState->isWrite, TlbEntry::DomainType::NoAccess, L1); + f = testWalk(l1desc_addr, sizeof(uint32_t), + TlbEntry::DomainType::NoAccess, L1); if (f) { DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); if (currState->timing) { @@ -668,10 +667,8 @@ TableWalker::processWalkLPAE() } // Trickbox address check - Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure, - currState->vaddr, sizeof(uint64_t), currState->isFetch, - currState->isWrite, TlbEntry::DomainType::NoAccess, - start_lookup_level); + Fault f = testWalk(desc_addr, sizeof(uint64_t), + TlbEntry::DomainType::NoAccess, start_lookup_level); if (f) { DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); if (currState->timing) { @@ -913,10 +910,8 @@ TableWalker::processWalkAArch64() stride * (3 - start_lookup_level) + tg) << 3); // Trickbox address check - Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure, - currState->vaddr, sizeof(uint64_t), currState->isFetch, - currState->isWrite, TlbEntry::DomainType::NoAccess, - start_lookup_level); + Fault f = testWalk(desc_addr, sizeof(uint64_t), + TlbEntry::DomainType::NoAccess, start_lookup_level); if (f) { DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); if (currState->timing) { @@ -1437,10 +1432,8 @@ TableWalker::doL1Descriptor() l2desc_addr, currState->isSecure ? "s" : "ns"); // Trickbox address check - currState->fault = tlb->walkTrickBoxCheck( - l2desc_addr, currState->isSecure, currState->vaddr, - sizeof(uint32_t), currState->isFetch, currState->isWrite, - currState->l1Desc.domain(), L2); + currState->fault = testWalk(l2desc_addr, sizeof(uint32_t), + currState->l1Desc.domain(), L2); if (currState->fault) { if (!currState->timing) { @@ -1616,12 +1609,9 @@ TableWalker::doLongDescriptor() } // Trickbox address check - currState->fault = tlb->walkTrickBoxCheck( - next_desc_addr, currState->vaddr, - currState->vaddr, sizeof(uint64_t), - currState->isFetch, currState->isWrite, - TlbEntry::DomainType::Client, - toLookupLevel(currState->longDesc.lookupLevel +1)); + currState->fault = testWalk( + next_desc_addr, sizeof(uint64_t), TlbEntry::DomainType::Client, + toLookupLevel(currState->longDesc.lookupLevel +1)); if (currState->fault) { if (!currState->timing) { @@ -2096,6 +2086,15 @@ TableWalker::pendingChange() } } +Fault +TableWalker::testWalk(Addr pa, Addr size, TlbEntry::DomainType domain, + LookupLevel lookup_level) +{ + return tlb->testWalk(pa, size, currState->vaddr, currState->isSecure, + currState->mode, domain, lookup_level); +} + + uint8_t TableWalker::pageSizeNtoStatBin(uint8_t N) { diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh index b960c320b..743b8aa93 100644 --- a/src/arch/arm/table_walker.hh +++ b/src/arch/arm/table_walker.hh @@ -966,6 +966,9 @@ class TableWalker : public MemObject void pendingChange(); static uint8_t pageSizeNtoStatBin(uint8_t N); + + 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 bdcb91fac..1bce0f798 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -75,7 +75,7 @@ TLB::TLB(const ArmTLBParams *p) : BaseTLB(p), table(new TlbEntry[p->size]), size(p->size), isStage2(p->is_stage2), stage2Req(false), _attr(0), directToStage2(false), tableWalker(p->walker), stage2Tlb(NULL), - stage2Mmu(NULL), rangeMRU(1), + stage2Mmu(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) @@ -576,19 +576,6 @@ TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode, return NoFault; } -Fault -TLB::trickBoxCheck(RequestPtr req, Mode mode, TlbEntry::DomainType domain) -{ - return NoFault; -} - -Fault -TLB::walkTrickBoxCheck(Addr pa, bool is_secure, Addr va, Addr sz, bool is_exec, - bool is_write, TlbEntry::DomainType domain, LookupLevel lookup_level) -{ - return NoFault; -} - Fault TLB::checkPermissions(TlbEntry *te, RequestPtr req, Mode mode) { @@ -1038,7 +1025,7 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, isStage2); setAttr(temp_te.attributes); - return trickBoxCheck(req, mode, TlbEntry::DomainType::NoAccess); + return testTranslation(req, mode, TlbEntry::DomainType::NoAccess); } DPRINTF(TLBVerbose, "Translating %s=%#x context=%d\n", @@ -1091,9 +1078,8 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode, } // Check for a trickbox generated address fault - if (fault == NoFault) { - fault = trickBoxCheck(req, mode, te->domain); - } + if (fault == NoFault) + fault = testTranslation(req, mode, te->domain); } // Generate Illegal Inst Set State fault if IL bit is set in CPSR @@ -1419,6 +1405,41 @@ TLB::getResultTe(TlbEntry **te, RequestPtr req, ThreadContext *tc, Mode mode, return fault; } +void +TLB::setTestInterface(SimObject *_ti) +{ + if (!_ti) { + test = nullptr; + } else { + TlbTestInterface *ti(dynamic_cast(_ti)); + fatal_if(!ti, "%s is not a valid ARM TLB tester\n", _ti->name()); + test = ti; + } +} + +Fault +TLB::testTranslation(RequestPtr req, Mode mode, TlbEntry::DomainType domain) +{ + if (!test) { + return NoFault; + } else { + return test->translationCheck(req, isPriv, mode, domain); + } +} + +Fault +TLB::testWalk(Addr pa, Addr size, Addr va, bool is_secure, Mode mode, + TlbEntry::DomainType domain, LookupLevel lookup_level) +{ + if (!test) { + return NoFault; + } else { + return test->walkCheck(pa, size, va, is_secure, isPriv, mode, + domain, lookup_level); + } +} + + ArmISA::TLB * ArmTLBParams::create() { diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh index 1f9ec01ec..298c603b9 100644 --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@ -61,6 +61,43 @@ namespace ArmISA { class TableWalker; class Stage2LookUp; class Stage2MMU; +class TLB; + +class TlbTestInterface +{ + public: + TlbTestInterface() {} + virtual ~TlbTestInterface() {} + + /** + * Check if a TLB translation should be forced to fail. + * + * @param req Request requiring a translation. + * @param is_priv Access from a privileged mode (i.e., not EL0) + * @param mode Access type + * @param domain Domain type + */ + virtual Fault translationCheck(RequestPtr req, bool is_priv, + BaseTLB::Mode mode, + TlbEntry::DomainType domain) = 0; + + /** + * Check if a page table walker access should be forced to fail. + * + * @param pa Physical address the walker is accessing + * @param size Walker access size + * @param va Virtual address that initiated the walk + * @param is_secure Access from secure state + * @param is_priv Access from a privileged mode (i.e., not EL0) + * @param mode Access type + * @param domain Domain type + * @param lookup_level Page table walker level + */ + virtual Fault walkCheck(Addr pa, Addr size, Addr va, bool is_secure, + Addr is_priv, BaseTLB::Mode mode, + TlbEntry::DomainType domain, + LookupLevel lookup_level) = 0; +}; class TLB : public BaseTLB { @@ -105,6 +142,8 @@ class TLB : public BaseTLB TLB *stage2Tlb; Stage2MMU *stage2Mmu; + TlbTestInterface *test; + // Access Stats mutable Stats::Scalar instHits; mutable Stats::Scalar instMisses; @@ -160,6 +199,8 @@ class TLB : public BaseTLB /// setup all the back pointers void init() override; + void setTestInterface(SimObject *ti); + TableWalker *getTableWalker() { return tableWalker; } void setMMU(Stage2MMU *m, MasterID master_id); @@ -224,10 +265,6 @@ class TLB : public BaseTLB */ void flushMva(Addr mva, bool secure_lookup, bool hyp, uint8_t target_el); - Fault trickBoxCheck(RequestPtr req, Mode mode, TlbEntry::DomainType domain); - Fault walkTrickBoxCheck(Addr pa, bool is_secure, Addr va, Addr sz, bool is_exec, - bool is_write, TlbEntry::DomainType domain, LookupLevel lookup_level); - void printTlb() const; void demapPage(Addr vaddr, uint64_t asn) override @@ -356,6 +393,13 @@ private: 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(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); }; } // namespace ArmISA -- 2.30.2