49#include "debug/TLB.hh"
50#include "debug/TLBVerbose.hh"
52#include "params/RiscvTLB.hh"
60using namespace RiscvISA;
75 assert(
bits(vpn, 63, 48) == 0);
76 return (
static_cast<Addr>(
asid) << 48) | vpn;
80 BaseTLB(
p), size(
p.size),
tlb(size),
81 lruSeq(0), stats(this), pma(
p.pma_checker),
84 for (
size_t x = 0;
x < size;
x++) {
85 tlb[
x].trieHandle = NULL;
86 freeList.push_back(&
tlb[
x]);
106 for (
size_t i = 1;
i < size;
i++) {
107 if (
tlb[
i].lruSeq <
tlb[lru].lruSeq)
119 DPRINTF(TLBVerbose,
"lookup(vpn=%#x, asid=%#x, key=%#x): "
120 "%s ppn=%#x (%#x) %s\n",
122 entry ? entry->
paddr : 0, entry ? entry->
size() : 0,
123 hidden ?
"hidden" :
"");
127 entry->
lruSeq = nextSeq();
129 if (
mode == BaseMMU::Write)
130 stats.writeAccesses++;
132 stats.readAccesses++;
135 if (
mode == BaseMMU::Write)
141 if (
mode == BaseMMU::Write)
154 DPRINTF(
TLB,
"insert(vpn=%#x, asid=%#x, key=%#x): "
155 "vaddr=%#x paddr=%#x pte=%#x size=%#x\n",
160 TlbEntry *newEntry = lookup(vpn, entry.
asid, BaseMMU::Read,
true);
163 newEntry->
pte = entry.
pte;
165 assert(newEntry->
asid == entry.
asid);
170 if (freeList.empty())
173 newEntry = freeList.front();
174 freeList.pop_front();
178 newEntry->
lruSeq = nextSeq();
180 key, TlbEntryTrie::MaxBits - entry.
logBytes + PageShift, newEntry
186TLB::demapPage(
Addr vaddr, uint64_t asid)
201 DPRINTF(
TLB,
"flush(vaddr=%#x, asid=%#x)\n", vaddr, asid);
202 if (vaddr == 0 && asid == 0) {
206 if (vaddr != 0 && asid != 0) {
209 TlbEntry *entry = lookup(vpn, asid, BaseMMU::Read,
true);
211 remove(entry -
tlb.data());
215 for (
size_t i = 0;
i < size;
i++) {
216 if (tlb[i].trieHandle) {
218 if ((vaddr == 0 || (vaddr & mask) == tlb[i].vaddr) &&
231 for (
size_t i = 0;
i < size;
i++) {
232 if (tlb[i].trieHandle)
238TLB::remove(
size_t idx)
240 DPRINTF(
TLB,
"remove(vpn=%#x, asid=%#x): ppn=%#x pte=%#x size=%#x\n",
244 assert(
tlb[idx].trieHandle);
245 trie.remove(
tlb[idx].trieHandle);
246 tlb[idx].trieHandle = NULL;
247 freeList.push_back(&
tlb[idx]);
238TLB::remove(
size_t idx) {
…}
256 if (
mode == BaseMMU::Read && !pte.r) {
257 DPRINTF(
TLB,
"PTE has no read perm, raising PF\n");
260 else if (
mode == BaseMMU::Write && !pte.w) {
261 DPRINTF(
TLB,
"PTE has no write perm, raising PF\n");
264 else if (
mode == BaseMMU::Execute && !pte.x) {
265 DPRINTF(
TLB,
"PTE has no exec perm, raising PF\n");
271 if (pmode == PrivilegeMode::PRV_U && !pte.u) {
272 DPRINTF(
TLB,
"PTE is not user accessible, raising PF\n");
275 else if (pmode == PrivilegeMode::PRV_S && pte.u &&
status.sum == 0) {
276 DPRINTF(
TLB,
"PTE is only user accessible, raising PF\n");
288 if (
mode == BaseMMU::Read)
289 code = ExceptionCode::LOAD_PAGE;
290 else if (
mode == BaseMMU::Write)
291 code = ExceptionCode::STORE_PAGE;
293 code = ExceptionCode::INST_PAGE;
294 return std::make_shared<AddressFault>(
vaddr, code);
298TLB::hiddenTranslateWithTLB(
Addr vaddr, uint16_t asid,
Addr xmode,
302 assert(
e !=
nullptr);
303 return e->paddr << PageShift | (
vaddr &
mask(
e->logBytes));
298TLB::hiddenTranslateWithTLB(
Addr vaddr, uint16_t asid,
Addr xmode, {
…}
319 Fault fault = walker->start(tc, translation, req,
mode);
320 if (translation !=
nullptr || fault !=
NoFault) {
325 e = lookup(vpn, satp.asid,
mode,
true);
326 assert(
e !=
nullptr);
335 if (
mode == BaseMMU::Write && !
e->pte.w) {
336 DPRINTF(
TLB,
"Dirty bit not set, repeating PT walk\n");
337 fault = walker->start(tc, translation, req,
mode);
338 if (translation !=
nullptr || fault !=
NoFault) {
348 DPRINTF(TLBVerbose,
"translate(vaddr=%#x, vpn=%#x, asid=%#x): %#x\n",
349 vaddr, vpn, satp.asid, paddr);
350 req->setPaddr(paddr);
360 if (
mode != BaseMMU::Execute &&
status.mprv == 1)
378 fault = pma->checkVAddrAlignment(req,
mode);
380 if (!misa.rvs || pmode == PrivilegeMode::PRV_M ||
381 satp.mode == AddrXlateMode::BARE) {
382 req->setFlags(Request::PHYSICAL);
386 if (req->getFlags() & Request::PHYSICAL) {
390 req->setPaddr(getValidAddr(req->getVaddr(), tc,
mode));
392 fault = doTranslate(req, tc, translation,
mode, delayed);
396 if (!delayed && fault ==
NoFault) {
400 fault = pmp->pmpCheck(req,
mode, pmode, tc);
403 if (!delayed && fault ==
NoFault) {
404 fault = pma->check(req,
mode);
415 assert(req->getSize() > 0);
416 if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
417 return std::make_shared<GenericPageTableFault>(req->getVaddr());
429 if (!p->pTable->translate(
vaddr, paddr))
430 return std::make_shared<GenericPageTableFault>(req->getVaddr());
432 req->setPaddr(paddr);
443 return translate(req, tc,
nullptr, mode, delayed);
452 Fault fault = translate(req, tc, translation, mode, delayed);
454 translation->
finish(fault, req, tc, mode);
460TLB::translateFunctional(
const RequestPtr &req, ThreadContext *tc,
463 const Addr vaddr = getValidAddr(req->getVaddr(), tc, mode);
467 MMU *mmu =
static_cast<MMU *
>(tc->getMMUPtr());
469 PrivilegeMode pmode = mmu->getMemPriv(tc, mode);
470 MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA);
471 SATP satp = tc->readMiscReg(MISCREG_SATP);
472 if (misa.rvs && pmode != PrivilegeMode::PRV_M &&
473 satp.mode != AddrXlateMode::BARE) {
474 Walker *walker = mmu->getDataWalker();
476 Fault fault = walker->startFunctional(
477 tc, paddr, logBytes, mode);
478 if (fault != NoFault)
481 Addr masked_addr = vaddr & mask(logBytes);
482 paddr |= masked_addr;
486 Process *process = tc->getProcessPtr();
487 const auto *pte = process->pTable->lookup(vaddr);
489 if (!pte && mode != BaseMMU::Execute) {
491 if (process->fixupFault(vaddr)) {
493 pte = process->pTable->lookup(vaddr);
498 return std::make_shared<GenericPageTableFault>(req->getVaddr());
500 paddr = pte->paddr | process->pTable->pageOffset(vaddr);
503 DPRINTF(TLB,
"Translated (functional) %#x -> %#x.\n", vaddr, paddr);
504 req->setPaddr(paddr);
509TLB::finalizePhysical(
const RequestPtr &req,
510 ThreadContext *tc, BaseMMU::Mode mode)
const
516TLB::serialize(CheckpointOut &cp)
const
519 uint32_t _size = size - freeList.size();
524 for (uint32_t x = 0;
x < size;
x++) {
525 if (tlb[x].trieHandle != NULL)
526 tlb[
x].serializeSection(cp,
csprintf(
"Entry%d", _count++));
531TLB::unserialize(CheckpointIn &cp)
537 fatal(
"TLB size less than the one in checkpoint!");
542 for (uint32_t x = 0;
x < _size;
x++) {
543 TlbEntry *newEntry = freeList.front();
544 freeList.pop_front();
546 newEntry->unserializeSection(cp,
csprintf(
"Entry%d", x));
550 newEntry->trieHandle = trie.insert(key,
551 TlbEntryTrie::MaxBits - newEntry->logBytes + PageShift, newEntry);
556 : statistics::
Group(parent),
557 ADD_STAT(readHits, statistics::units::Count::get(),
"read hits"),
558 ADD_STAT(readMisses, statistics::units::Count::get(),
"read misses"),
559 ADD_STAT(readAccesses, statistics::units::Count::get(),
"read accesses"),
560 ADD_STAT(writeHits, statistics::units::Count::get(),
"write hits"),
561 ADD_STAT(writeMisses, statistics::units::Count::get(),
"write misses"),
562 ADD_STAT(writeAccesses, statistics::units::Count::get(),
"write accesses"),
563 ADD_STAT(hits, statistics::units::Count::get(),
564 "Total TLB (read and write) hits", readHits + writeHits),
565 ADD_STAT(misses, statistics::units::Count::get(),
566 "Total TLB (read and write) misses", readMisses + writeMisses),
567 ADD_STAT(accesses, statistics::units::Count::get(),
568 "Total TLB (read and write) accesses",
569 readAccesses + writeAccesses)
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode)=0
virtual void markDelayed()=0
Signal that the translation has been delayed due to a hw page table walk.
Ports are used to interface objects to each other.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
virtual Process * getProcessPtr()=0
Port * getTableWalkerPort() override
Get the table walker port.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
#define fatal(...)
This implements a cprintf based fatal() function.
Declaration of IniFile object.
Addr getVPNFromVAddr(Addr vaddr, Addr mode)
Copyright (c) 2024 Arm Limited All rights reserved.
std::shared_ptr< FaultBase > Fault
static Addr buildKey(Addr vpn, uint16_t asid)
std::shared_ptr< Request > RequestPtr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
std::string csprintf(const char *format, const Args &...args)
constexpr decltype(nullptr) NoFault
Declarations of a non-full system Page Table.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
TlbEntryTrie::Handle trieHandle