diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/arm/table_walker.cc | 22 | ||||
-rw-r--r-- | src/arch/arm/table_walker.hh | 3 |
2 files changed, 22 insertions, 3 deletions
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc index bfa5ba7bb..ff4e67554 100644 --- a/src/arch/arm/table_walker.cc +++ b/src/arch/arm/table_walker.cc @@ -134,6 +134,7 @@ TableWalker::WalkerState::WalkerState() : sctlr(0), scr(0), cpsr(0), tcr(0), htcr(0), hcr(0), vtcr(0), isWrite(false), isFetch(false), isSecure(false), + isUncacheable(false), secureLookup(false), rwTable(false), userTable(false), xnTable(false), pxnTable(false), hpd(false), stage2Req(false), stage2Tran(nullptr), timing(false), functional(false), @@ -574,10 +575,12 @@ TableWalker::processWalkLPAE() ttbr = currState->tc->readMiscReg(MISCREG_VTTBR); tsz = sext<4>(currState->vtcr.t0sz); start_lookup_level = currState->vtcr.sl0 ? L1 : L2; + currState->isUncacheable = currState->vtcr.irgn0 == 0; } else if (currState->isHyp) { DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n"); ttbr = currState->tc->readMiscReg(MISCREG_HTTBR); tsz = currState->htcr.t0sz; + currState->isUncacheable = currState->htcr.irgn0 == 0; } else { assert(longDescFormatInUse(currState->tc)); @@ -622,6 +625,7 @@ TableWalker::processWalkLPAE() ttbr = currState->tc->readMiscReg(snsBankedIndex( MISCREG_TTBR0, currState->tc, !currState->isSecure)); tsz = currState->ttbcr.t0sz; + currState->isUncacheable = currState->ttbcr.irgn0 == 0; if (ttbr0_max < (1ULL << 30)) // Upper limit < 1 GB start_lookup_level = L2; } else if (currState->vaddr >= ttbr1_min) { @@ -646,7 +650,9 @@ TableWalker::processWalkLPAE() ttbr = currState->tc->readMiscReg(snsBankedIndex( MISCREG_TTBR1, currState->tc, !currState->isSecure)); tsz = currState->ttbcr.t1sz; - if (ttbr1_min >= (1ULL << 31) + (1ULL << 30)) // Lower limit >= 3 GB + currState->isUncacheable = currState->ttbcr.irgn1 == 0; + // Lower limit >= 3 GB + if (ttbr1_min >= (1ULL << 31) + (1ULL << 30)) start_lookup_level = L2; } else { // Out of boundaries -> translation fault @@ -699,7 +705,7 @@ TableWalker::processWalkLPAE() return f; } - if (currState->sctlr.c == 0) { + if (currState->sctlr.c == 0 || currState->isUncacheable) { flag.set(Request::UNCACHEABLE); } @@ -781,6 +787,7 @@ TableWalker::processWalkAArch64() panic_if(start_lookup_level == MAX_LOOKUP_LEVELS, "Cannot discern lookup level from vtcr.{sl0,tg0}"); ps = currState->vtcr.ps; + currState->isUncacheable = currState->vtcr.irgn0 == 0; } else { switch (bits(currState->vaddr, 63,48)) { case 0: @@ -789,6 +796,7 @@ TableWalker::processWalkAArch64() tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz); tg = GrainMap_tg0[currState->tcr.tg0]; currState->hpd = currState->tcr.hpd0; + currState->isUncacheable = currState->tcr.irgn0 == 0; if (bits(currState->vaddr, 63, tsz) != 0x0 || currState->tcr.epd0) fault = true; @@ -799,6 +807,7 @@ TableWalker::processWalkAArch64() tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz); tg = GrainMap_tg1[currState->tcr.tg1]; currState->hpd = currState->tcr.hpd1; + currState->isUncacheable = currState->tcr.irgn1 == 0; if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) || currState->tcr.epd1) fault = true; @@ -819,6 +828,7 @@ TableWalker::processWalkAArch64() tg = GrainMap_tg0[currState->tcr.tg0]; currState->hpd = currState->hcr.e2h ? currState->tcr.hpd0 : currState->tcr.hpd; + currState->isUncacheable = currState->tcr.irgn0 == 0; break; case 0xffff: @@ -827,6 +837,7 @@ TableWalker::processWalkAArch64() tsz = adjustTableSizeAArch64(64 - currState->tcr.t1sz); tg = GrainMap_tg1[currState->tcr.tg1]; currState->hpd = currState->tcr.hpd1; + currState->isUncacheable = currState->tcr.irgn1 == 0; if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) || currState->tcr.epd1 || !currState->hcr.e2h) fault = true; @@ -846,6 +857,7 @@ TableWalker::processWalkAArch64() tsz = adjustTableSizeAArch64(64 - currState->tcr.t0sz); tg = GrainMap_tg0[currState->tcr.tg0]; currState->hpd = currState->tcr.hpd; + currState->isUncacheable = currState->tcr.irgn0 == 0; break; default: // invalid addr if top two bytes are not all 0s @@ -994,7 +1006,7 @@ TableWalker::processWalkAArch64() } Request::Flags flag = Request::PT_WALK; - if (currState->sctlr.c == 0) { + if (currState->sctlr.c == 0 || currState->isUncacheable) { flag.set(Request::UNCACHEABLE); } @@ -1701,6 +1713,10 @@ TableWalker::doLongDescriptor() if (currState->secureLookup) flag.set(Request::SECURE); + if (currState->sctlr.c == 0 || currState->isUncacheable) { + flag.set(Request::UNCACHEABLE); + } + LookupLevel L = currState->longDesc.lookupLevel = (LookupLevel) (currState->longDesc.lookupLevel + 1); Event *event = NULL; diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh index 2fc45ceaf..da85c0c54 100644 --- a/src/arch/arm/table_walker.hh +++ b/src/arch/arm/table_walker.hh @@ -756,6 +756,9 @@ class TableWalker : public ClockedObject /** 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; |