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.
This commit is contained in:
parent
1ab75c3ee2
commit
8d8e926b04
4 changed files with 110 additions and 43 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<TlbTestInterface *>(_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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue