50#include "debug/TLB.hh"
51#include "debug/TLBVerbose.hh"
53#include "params/RiscvTLB.hh"
76 assert(
bits(vpn, 63, 48) == 0);
77 return (
static_cast<Addr>(
asid) << 48) | vpn;
81 BaseTLB(
p), size(
p.size),
tlb(size),
82 lruSeq(0), stats(this), pma(
p.pma_checker),
85 for (
size_t x = 0;
x < size;
x++) {
86 tlb[
x].trieHandle = NULL;
87 freeList.push_back(&
tlb[
x]);
107 for (
size_t i = 1;
i <
size;
i++) {
120 DPRINTF(TLBVerbose,
"lookup(vpn=%#x, asid=%#x, key=%#x): "
121 "%s ppn=%#x (%#x) %s\n",
123 entry ? entry->
paddr : 0, entry ? entry->
size() : 0,
124 hidden ?
"hidden" :
"");
131 stats.writeAccesses++;
133 stats.readAccesses++;
155 DPRINTF(
TLB,
"insert(vpn=%#x, asid=%#x, key=%#x): "
156 "vaddr=%#x paddr=%#x pte=%#x size=%#x\n",
164 newEntry->
pte = entry.
pte;
166 assert(newEntry->
asid == entry.
asid);
212 remove(entry -
tlb.data());
216 for (
size_t i = 0;
i < size;
i++) {
217 if (tlb[i].trieHandle) {
219 if ((vaddr == 0 || (vaddr & mask) == tlb[i].vaddr) &&
220 (asid == 0 || tlb[i].asid == asid))
232 for (
size_t i = 0;
i < size;
i++) {
233 if (tlb[i].trieHandle)
241 DPRINTF(
TLB,
"remove(vpn=%#x, asid=%#x): ppn=%#x pte=%#x size=%#x\n",
245 assert(
tlb[idx].trieHandle);
246 trie.remove(
tlb[idx].trieHandle);
247 tlb[idx].trieHandle = NULL;
262 bool gpf = stage ==
GSTAGE;
263 bool virt = mem_access.
virt;
274 if (mem_access.
hlvx) {
276 pf =
true;
DPRINTF(
TLB,
"HLVX with no exec perm, raising PF\n");
281 DPRINTF(TLBVerbose,
"MXR bit on, load from exec page success\n");
284 pf =
true;
DPRINTF(
TLB,
"PTE has no read perm, raising PF\n");
288 pf =
true;
DPRINTF(
TLB,
"PTE has no write perm, raising PF\n");
291 pf =
true;
DPRINTF(
TLB,
"PTE has no exec perm, raising PF\n");
297 pf =
true;
DPRINTF(
TLB,
"PTE not user accessible, raising PF\n");
301 pf =
true;
DPRINTF(
TLB,
"PTE only user accessible, raising PF\n");
310 Addr gvaddr,
bool gpf,
bool virt)
326 if (gpf) { assert(virt); }
327 return std::make_shared<AddressFault>(
vaddr, code, gvaddr, virt);
335 assert(
e !=
nullptr);
351 SATP satp = (misa.rvh && memaccess.
virt) ?
364 if (translation !=
nullptr) {
379 assert(
e !=
nullptr);
389 if (translation !=
nullptr || fault !=
NoFault) {
401 if (memaccess.
virt) {
418 DPRINTF(
TLB,
"Dirty bit not set, repeating PT walk\n");
419 fault =
walker->start(tc, translation, req,
mode);
422 if (translation !=
nullptr) {
452 DPRINTF(TLBVerbose,
"translate(vaddr=%#x, vpn=%#x, asid=%#x): %#x\n",
453 vaddr, vpn, satp.asid, paddr);
454 req->setPaddr(paddr);
472 bool force_virt =
false;
511 tc,
mode, req->getArchFlags());
514 SATP satp = (misa.rvh && memaccess.
virt) ?
520 fault =
pma->checkVAddrAlignment(req,
mode);
523 satp.mode == AddrXlateMode::BARE) {
531 if (misa.rvh && memaccess.
virt) {
533 if (hgatp.mode == AddrXlateMode::BARE) {
556 if (!delayed && fault ==
NoFault &&
bits(req->getPaddr(), 63)) {
564 fault = std::make_shared<AddressFault>(req->getVaddr(), code);
567 if (!delayed && fault ==
NoFault) {
571 fault =
pmp->pmpCheck(req,
mode, pmode, tc);
574 if (!delayed && fault ==
NoFault) {
586 assert(req->getSize() > 0);
587 if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
588 return std::make_shared<GenericPageTableFault>(req->getVaddr());
600 if (!
p->pTable->translate(
vaddr, paddr))
601 return std::make_shared<GenericPageTableFault>(req->getVaddr());
603 req->setPaddr(paddr);
614 return translate(req, tc,
nullptr,
mode, delayed);
623 Fault fault = translate(req, tc, translation,
mode, delayed);
631TLB::translateFunctional(
const RequestPtr &req, ThreadContext *tc,
634 const Addr vaddr = getValidAddr(req->getVaddr(), tc, mode);
638 MMU *mmu =
static_cast<MMU *
>(tc->getMMUPtr());
640 MemAccessInfo memaccess = getMemAccessInfo(
641 tc, mode, req->getArchFlags());
642 PrivilegeMode pmode = memaccess.priv;
643 MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA);
644 SATP satp = tc->readMiscReg(MISCREG_SATP);
645 if (misa.rvs && pmode != PrivilegeMode::PRV_M &&
646 satp.mode != AddrXlateMode::BARE) {
647 Walker *walker = mmu->getDataWalker();
649 Fault fault = walker->startFunctional(
650 tc, paddr, logBytes, mode);
651 if (fault != NoFault)
654 Addr masked_addr = vaddr & mask(logBytes);
655 paddr |= masked_addr;
659 Process *process = tc->getProcessPtr();
660 const auto *pte = process->pTable->lookup(vaddr);
662 if (!pte && mode != BaseMMU::Execute) {
664 if (process->fixupFault(vaddr)) {
666 pte = process->pTable->lookup(vaddr);
671 return std::make_shared<GenericPageTableFault>(req->getVaddr());
673 paddr = pte->paddr | process->pTable->pageOffset(vaddr);
676 DPRINTF(TLB,
"Translated (functional) %#x -> %#x.\n", vaddr, paddr);
677 req->setPaddr(paddr);
682TLB::finalizePhysical(
const RequestPtr &req,
683 ThreadContext *tc, BaseMMU::Mode mode)
const
689TLB::serialize(CheckpointOut &cp)
const
692 uint32_t _size = size - freeList.size();
697 for (uint32_t x = 0;
x < size;
x++) {
698 if (tlb[x].trieHandle != NULL)
699 tlb[
x].serializeSection(cp,
csprintf(
"Entry%d", _count++));
704TLB::unserialize(CheckpointIn &cp)
710 fatal(
"TLB size less than the one in checkpoint!");
715 for (uint32_t x = 0;
x < _size;
x++) {
716 TlbEntry *newEntry = freeList.front();
717 freeList.pop_front();
719 newEntry->unserializeSection(cp,
csprintf(
"Entry%d", x));
723 newEntry->trieHandle = trie.insert(key,
724 TlbEntryTrie::MaxBits - newEntry->logBytes + PageShift, newEntry);
737 "Total TLB (read and write) hits", readHits + writeHits),
739 "Total TLB (read and write) misses", readMisses + writeMisses),
741 "Total TLB (read and write) accesses",
742 readAccesses + writeAccesses)
749 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 checkPermissions(ThreadContext *tc, MemAccessInfo mem_access, Addr vaddr, BaseMMU::Mode mode, PTESv39 pte, Addr gvaddr=0x0, XlateStage stage=XlateStage::FIRST_STAGE)
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
MemAccessInfo getMemAccessInfo(ThreadContext *tc, BaseMMU::Mode mode, const Request::ArchFlagsType arch_flags)
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 createPagefault(Addr vaddr, BaseMMU::Mode mode, Addr gvaddr=0x0, bool gpf=false, bool virt=false)
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.
#define fatal(...)
This implements a cprintf based fatal() function.
Declaration of IniFile object.
Addr getVPNFromVAddr(Addr vaddr, Addr mode)
bool virtualizationEnabled(ExecContext *xc)
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)