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);
476 bool force_virt =
false;
515 tc,
mode, req->getArchFlags());
518 SATP satp = (misa.rvh && memaccess.
virt) ?
524 fault =
pma->checkVAddrAlignment(req,
mode);
527 satp.mode == AddrXlateMode::BARE) {
535 if (misa.rvh && memaccess.
virt) {
537 if (hgatp.mode == AddrXlateMode::BARE) {
560 if (!delayed && fault ==
NoFault &&
bits(req->getPaddr(), 63)) {
568 fault = std::make_shared<AddressFault>(req->getVaddr(), code);
571 if (!delayed && fault ==
NoFault) {
575 fault =
pmp->pmpCheck(req,
mode, pmode, tc);
578 if (!delayed && fault ==
NoFault) {
590 assert(req->getSize() > 0);
591 if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
592 return std::make_shared<GenericPageTableFault>(req->getVaddr());
604 if (!
p->pTable->translate(
vaddr, paddr))
605 return std::make_shared<GenericPageTableFault>(req->getVaddr());
607 req->setPaddr(paddr);
618 return translate(req, tc,
nullptr,
mode, delayed);
627 Fault fault = translate(req, tc, translation,
mode, delayed);
635TLB::translateFunctional(
const RequestPtr &req, ThreadContext *tc,
638 const Addr vaddr = getValidAddr(req->getVaddr(), tc, mode);
642 MMU *mmu =
static_cast<MMU *
>(tc->getMMUPtr());
644 MemAccessInfo memaccess = getMemAccessInfo(
645 tc, mode, req->getArchFlags());
646 PrivilegeMode pmode = memaccess.priv;
647 MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA);
648 SATP satp = tc->readMiscReg(MISCREG_SATP);
649 if (misa.rvs && pmode != PrivilegeMode::PRV_M &&
650 satp.mode != AddrXlateMode::BARE) {
651 Walker *walker = mmu->getDataWalker();
653 Fault fault = walker->startFunctional(
654 tc, paddr, logBytes, mode);
655 if (fault != NoFault)
658 Addr masked_addr = vaddr & mask(logBytes);
659 paddr |= masked_addr;
663 Process *process = tc->getProcessPtr();
664 const auto *pte = process->pTable->lookup(vaddr);
666 if (!pte && mode != BaseMMU::Execute) {
668 if (process->fixupFault(vaddr)) {
670 pte = process->pTable->lookup(vaddr);
675 return std::make_shared<GenericPageTableFault>(req->getVaddr());
677 paddr = pte->paddr | process->pTable->pageOffset(vaddr);
680 DPRINTF(TLB,
"Translated (functional) %#x -> %#x.\n", vaddr, paddr);
681 req->setPaddr(paddr);
686TLB::finalizePhysical(
const RequestPtr &req,
687 ThreadContext *tc, BaseMMU::Mode mode)
const
693TLB::serialize(CheckpointOut &cp)
const
696 uint32_t _size = size - freeList.size();
701 for (uint32_t x = 0;
x < size;
x++) {
702 if (tlb[x].trieHandle != NULL)
703 tlb[
x].serializeSection(cp,
csprintf(
"Entry%d", _count++));
708TLB::unserialize(CheckpointIn &cp)
714 fatal(
"TLB size less than the one in checkpoint!");
719 for (uint32_t x = 0;
x < _size;
x++) {
720 TlbEntry *newEntry = freeList.front();
721 freeList.pop_front();
723 newEntry->unserializeSection(cp,
csprintf(
"Entry%d", x));
727 newEntry->trieHandle = trie.insert(key,
728 TlbEntryTrie::MaxBits - newEntry->logBytes + PageShift, newEntry);
741 "Total TLB (read and write) hits", readHits + writeHits),
743 "Total TLB (read and write) misses", readMisses + writeMisses),
745 "Total TLB (read and write) accesses",
746 readAccesses + writeAccesses)
753 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 BaseISA * getIsaPtr() const =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)