49#include "debug/TLB.hh"
50#include "debug/TLBVerbose.hh"
52#include "params/RiscvTLB.hh"
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++) {
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" :
"");
130 stats.writeAccesses++;
132 stats.readAccesses++;
154 DPRINTF(
TLB,
"insert(vpn=%#x, asid=%#x, key=%#x): "
155 "vaddr=%#x paddr=%#x pte=%#x size=%#x\n",
163 newEntry->
pte = entry.
pte;
165 assert(newEntry->
asid == entry.
asid);
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) &&
219 (asid == 0 || tlb[i].asid == asid))
231 for (
size_t i = 0;
i < size;
i++) {
232 if (tlb[i].trieHandle)
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;
257 DPRINTF(
TLB,
"PTE has no read perm, raising PF\n");
261 DPRINTF(
TLB,
"PTE has no write perm, raising PF\n");
265 DPRINTF(
TLB,
"PTE has no exec perm, raising PF\n");
272 DPRINTF(
TLB,
"PTE is not user accessible, raising PF\n");
277 DPRINTF(
TLB,
"PTE is only user accessible, raising PF\n");
295 return std::make_shared<AddressFault>(
vaddr, code);
303 assert(
e !=
nullptr);
321 if (translation !=
nullptr || fault !=
NoFault) {
327 assert(
e !=
nullptr);
337 DPRINTF(
TLB,
"Dirty bit not set, repeating PT walk\n");
338 fault =
walker->start(tc, translation, req,
mode);
339 if (translation !=
nullptr || fault !=
NoFault) {
349 DPRINTF(TLBVerbose,
"translate(vaddr=%#x, vpn=%#x, asid=%#x): %#x\n",
350 vaddr, vpn, satp.asid, paddr);
351 req->setPaddr(paddr);
379 fault =
pma->checkVAddrAlignment(req,
mode);
382 satp.mode == AddrXlateMode::BARE) {
397 if (!delayed && fault ==
NoFault) {
401 fault =
pmp->pmpCheck(req,
mode, pmode, tc);
404 if (!delayed && fault ==
NoFault) {
416 assert(req->getSize() > 0);
417 if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
418 return std::make_shared<GenericPageTableFault>(req->getVaddr());
430 if (!
p->pTable->translate(
vaddr, paddr))
431 return std::make_shared<GenericPageTableFault>(req->getVaddr());
433 req->setPaddr(paddr);
444 return translate(req, tc,
nullptr,
mode, delayed);
453 Fault fault = translate(req, tc, translation,
mode, delayed);
461TLB::translateFunctional(
const RequestPtr &req, ThreadContext *tc,
464 const Addr vaddr = getValidAddr(req->getVaddr(), tc, mode);
468 MMU *mmu =
static_cast<MMU *
>(tc->getMMUPtr());
470 PrivilegeMode pmode = mmu->getMemPriv(tc, mode);
471 MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA);
472 SATP satp = tc->readMiscReg(MISCREG_SATP);
473 if (misa.rvs && pmode != PrivilegeMode::PRV_M &&
474 satp.mode != AddrXlateMode::BARE) {
475 Walker *walker = mmu->getDataWalker();
477 Fault fault = walker->startFunctional(
478 tc, paddr, logBytes, mode);
479 if (fault != NoFault)
482 Addr masked_addr = vaddr & mask(logBytes);
483 paddr |= masked_addr;
487 Process *process = tc->getProcessPtr();
488 const auto *pte = process->pTable->lookup(vaddr);
490 if (!pte && mode != BaseMMU::Execute) {
492 if (process->fixupFault(vaddr)) {
494 pte = process->pTable->lookup(vaddr);
499 return std::make_shared<GenericPageTableFault>(req->getVaddr());
501 paddr = pte->paddr | process->pTable->pageOffset(vaddr);
504 DPRINTF(TLB,
"Translated (functional) %#x -> %#x.\n", vaddr, paddr);
505 req->setPaddr(paddr);
510TLB::finalizePhysical(
const RequestPtr &req,
511 ThreadContext *tc, BaseMMU::Mode mode)
const
517TLB::serialize(CheckpointOut &cp)
const
520 uint32_t _size = size - freeList.size();
525 for (uint32_t x = 0;
x < size;
x++) {
526 if (tlb[x].trieHandle != NULL)
527 tlb[
x].serializeSection(cp,
csprintf(
"Entry%d", _count++));
532TLB::unserialize(CheckpointIn &cp)
538 fatal(
"TLB size less than the one in checkpoint!");
543 for (uint32_t x = 0;
x < _size;
x++) {
544 TlbEntry *newEntry = freeList.front();
545 freeList.pop_front();
547 newEntry->unserializeSection(cp,
csprintf(
"Entry%d", x));
551 newEntry->trieHandle = trie.insert(key,
552 TlbEntryTrie::MaxBits - newEntry->logBytes + PageShift, newEntry);
565 "Total TLB (read and write) hits", readHits + writeHits),
567 "Total TLB (read and write) misses", readMisses + writeMisses),
569 "Total TLB (read and write) accesses",
570 readAccesses + writeAccesses)
577 return &
walker->getPort(
"port");
void translateTiming(const RequestPtr &req, ThreadContext *tc, BaseMMU::Translation *translation, BaseMMU::Mode mode) override
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.
@ PHYSICAL
The virtual address is also the physical address.
Fault createPagefault(Addr vaddr, BaseMMU::Mode mode)
Addr hiddenTranslateWithTLB(Addr vaddr, uint16_t asid, Addr xmode, BaseMMU::Mode mode)
gem5::RiscvISA::TLB::TlbStats stats
TlbEntry * insert(Addr vpn, const TlbEntry &entry)
Insert an entry into the TLB.
std::vector< TlbEntry > tlb
Fault translateAtomic(const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) override
PrivilegeMode getMemPriv(ThreadContext *tc, BaseMMU::Mode mode)
TlbEntry * lookup(Addr vpn, uint16_t asid, BaseMMU::Mode mode, bool hidden)
Perform the tlb lookup.
Addr getValidAddr(Addr vaddr, ThreadContext *tc, BaseMMU::Mode mode)
Fault doTranslate(const RequestPtr &req, ThreadContext *tc, BaseMMU::Translation *translation, BaseMMU::Mode mode, bool &delayed)
Fault translate(const RequestPtr &req, ThreadContext *tc, BaseMMU::Translation *translation, BaseMMU::Mode mode, bool &delayed)
Fault checkPermissions(STATUS status, PrivilegeMode pmode, Addr vaddr, BaseMMU::Mode mode, PTESv39 pte)
void demapPage(Addr vaddr, uint64_t asn) override
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.
std::vector< TlbEntry > tlb
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
static const unsigned MaxBits
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
constexpr uint64_t sext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
#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
TlbStats(statistics::Group *parent)