tc = _tc;
mode = _mode;
timing = _isTiming;
+ // fetch these now in case they change during the walk
+ status = tc->readMiscReg(MISCREG_STATUS);
+ pmode = walker->tlb->getMemPriv(tc, mode);
+ satp = tc->readMiscReg(MISCREG_SATP);
+ assert(satp.mode == AddrXlateMode::SV39);
}
void
if (pte.r || pte.x) {
// step 5: leaf PTE
doEndWalk = true;
- fault = walker->tlb->checkPermissions(tc, entry.vaddr, mode, pte);
+ fault = walker->tlb->checkPermissions(status, pmode,
+ entry.vaddr, mode, pte);
// step 6
if (fault == NoFault) {
void
Walker::WalkerState::setupWalk(Addr vaddr)
{
- vaddr &= ((static_cast<Addr>(1) << VADDR_BITS) - 1);
-
- SATP satp = tc->readMiscReg(MISCREG_SATP);
- assert(satp.mode == AddrXlateMode::SV39);
+ vaddr &= (static_cast<Addr>(1) << VADDR_BITS) - 1;
Addr shift = PageShift + LEVEL_BITS * 2;
Addr idx = (vaddr >> shift) & LEVEL_MASK;
* permissions violations, so we'll need the return value as
* well.
*/
- bool delayedResponse;
- Fault fault = walker->tlb->doTranslate(req, tc, NULL, mode,
- delayedResponse);
- assert(!delayedResponse);
+ Addr vaddr = req->getVaddr();
+ vaddr &= (static_cast<Addr>(1) << VADDR_BITS) - 1;
+ Addr paddr = walker->tlb->translateWithTLB(vaddr, satp.asid, mode);
+ req->setPaddr(paddr);
// Let the CPU continue.
- translation->finish(fault, req, tc, mode);
+ translation->finish(NoFault, req, tc, mode);
} else {
// There was a fault during the walk. Let the CPU know.
translation->finish(timingFault, req, tc, mode);
Fault timingFault;
TLB::Translation * translation;
BaseTLB::Mode mode;
+ SATP satp;
+ STATUS status;
+ PrivilegeMode pmode;
bool functional;
bool timing;
bool retrying;
}
Fault
-TLB::checkPermissions(ThreadContext *tc, Addr vaddr, Mode mode, PTESv39 pte)
+TLB::checkPermissions(STATUS status, PrivilegeMode pmode, Addr vaddr,
+ Mode mode, PTESv39 pte)
{
Fault fault = NoFault;
if (fault == NoFault) {
// check pte.u
- STATUS status = tc->readMiscReg(MISCREG_STATUS);
- PrivilegeMode pmode = getMemPriv(tc, mode);
if (pmode == PrivilegeMode::PRV_U && !pte.u) {
DPRINTF(TLB, "PTE is not user accessible, raising PF\n");
fault = createPagefault(vaddr, mode);
return std::make_shared<AddressFault>(vaddr, code);
}
+Addr
+TLB::translateWithTLB(Addr vaddr, uint16_t asid, Mode mode)
+{
+ TlbEntry *e = lookup(vaddr, asid, mode, false);
+ assert(e != nullptr);
+ return e->paddr << PageShift | (vaddr & mask(e->logBytes));
+}
+
Fault
TLB::doTranslate(const RequestPtr &req, ThreadContext *tc,
Translation *translation, Mode mode, bool &delayed)
assert(e != nullptr);
}
- Fault fault = checkPermissions(tc, vaddr, mode, e->pte);
+ STATUS status = tc->readMiscReg(MISCREG_STATUS);
+ PrivilegeMode pmode = getMemPriv(tc, mode);
+ Fault fault = checkPermissions(status, pmode, vaddr, mode, e->pte);
if (fault != NoFault) {
// if we want to write and it isn't writable, do a page table walk
// again to update the dirty flag.
void flushAll() override;
void demapPage(Addr vaddr, uint64_t asn) override;
- Fault checkPermissions(ThreadContext *tc, Addr vaddr,
+ Fault checkPermissions(STATUS status, PrivilegeMode pmode, Addr vaddr,
Mode mode, PTESv39 pte);
Fault createPagefault(Addr vaddr, Mode mode);
void regStats() override;
- Fault doTranslate(const RequestPtr &req, ThreadContext *tc,
- Translation *translation, Mode mode, bool &delayed);
+ Addr translateWithTLB(Addr vaddr, uint16_t asid, Mode mode);
Fault translateAtomic(const RequestPtr &req,
ThreadContext *tc, Mode mode) override;
Fault translate(const RequestPtr &req, ThreadContext *tc,
Translation *translation, Mode mode, bool &delayed);
+ Fault doTranslate(const RequestPtr &req, ThreadContext *tc,
+ Translation *translation, Mode mode, bool &delayed);
};
}