44#include "debug/IPR.hh"
45#include "debug/TLB.hh"
61 :
BaseTLB(
p), size(
p.size), usedEntries(0), lastReplaced(0),
62 cacheState(0), cacheValid(false)
66 fatal(
"SPARC T1 TLB registers don't support more than 64 TLB entries");
93 if (!
t->pte.locked()) {
110 va &= ~(
PTE.size()-1);
113 "TLB: Inserting Entry; va=%#x pa=%#x pid=%d cid=%d r=%d entryid=%d\n",
114 va,
PTE.paddr(), partition_id, context_id, (
int)real, entry);
118 if (
tlb[
x].range.real == real &&
126 DPRINTF(
TLB,
"TLB: Conflicting entry %#X , deleting it\n",
x);
139 assert(entry < size && entry >= 0);
140 new_entry = &
tlb[entry];
151 goto insertAllLocked;
152 }
while (
tlb[
x].pte.locked());
167 if (new_entry->
valid)
178 new_entry->
used =
true;;
179 new_entry->
valid =
true;
189 new_entry->
used =
true;
203 DPRINTF(
TLB,
"TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n",
204 va, partition_id, context_id, real);
221 DPRINTF(
TLB,
"TLB: Valid entry found pa: %#x size: %#x\n",
t->pte.paddr(),
226 if (!
t->used && update_used) {
243 for (
int x = 0;
x <
size;
x++) {
245 DPRINTFN(
"%4d: %#2x:%#2x %c %#4x %#8x %#8x %#16x\n",
259 DPRINTF(IPR,
"TLB: Demapping Page va=%#x pid=%#d cid=%d r=%d\n",
260 va, partition_id, context_id, real);
274 DPRINTF(IPR,
"TLB: Demapped page\n");
275 i->second->valid =
false;
276 if (
i->second->used) {
277 i->second->used =
false;
288 DPRINTF(IPR,
"TLB: Demapping Context pid=%#d cid=%d\n",
289 partition_id, context_id);
291 for (
int x = 0;
x <
size;
x++) {
292 if (
tlb[
x].range.contextId == context_id &&
310 DPRINTF(
TLB,
"TLB: Demapping All pid=%#d\n", partition_id);
312 for (
int x = 0;
x <
size;
x++) {
313 if (
tlb[
x].valid && !
tlb[
x].pte.locked() &&
332 for (
int x = 0;
x <
size;
x++) {
345 panic(
"entry: %d\n", entry);
347 assert(entry <
size);
348 if (
tlb[entry].valid)
351 return (uint64_t)-1ll;
357 assert(entry <
size);
359 if (!
tlb[entry].valid)
360 return (uint64_t)-1ll;
364 tag |= (uint64_t)
tlb[entry].range.partitionId << 61;
366 tag |= (uint64_t)~
tlb[entry].pte._size() << 56;
400 DPRINTF(
TLB,
"TLB: Writing Tag Access: va: %#X ctx: %#X value: %#X\n",
410 DPRINTF(
TLB,
"TLB: Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n",
411 a, (
int)write, ct, ft, asi);
426 DPRINTF(
TLB,
"TLB: ITB Request to translate va=%#x size=%d\n",
427 vaddr, req->getSize());
446 bool addr_mask =
bits(tlbdata,3,3);
447 bool lsu_im =
bits(tlbdata,4,4);
449 int part_id =
bits(tlbdata,15,8);
450 int tl =
bits(tlbdata,18,16);
451 int pri_context =
bits(tlbdata,47,32);
457 DPRINTF(
TLB,
"TLB: priv:%d hpriv:%d red:%d lsuim:%d part_id: %#X\n",
467 context = pri_context;
481 return std::make_shared<MemAddressNotAligned>();
489 return std::make_shared<InstructionAccessException>();
500 if (
e == NULL || !
e->valid) {
503 return std::make_shared<InstructionRealTranslationMiss>();
506 return std::make_shared<FastInstructionAccessMMUMiss>();
508 return std::make_shared<FastInstructionAccessMMUMiss>(
514 if (!
priv &&
e->pte.priv()) {
517 return std::make_shared<InstructionAccessException>();
525 req->setPaddr(
e->pte.translate(
vaddr));
541 asi = (
ASI)req->getArchFlags();
542 bool implicit =
false;
546 DPRINTF(
TLB,
"TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
558 if (
hpriv && implicit) {
572 ce_va < vaddr + size && ce_va + ce->range.size >
vaddr &&
573 (!write ||
ce->pte.writable())) {
574 req->setPaddr(
ce->pte.translate(
vaddr));
575 if (
ce->pte.sideffect() || (
ce->pte.paddr() >> 39) & 1) {
587 ce_va < vaddr + size && ce_va + ce->range.size >
vaddr &&
588 (!write ||
ce->pte.writable())) {
589 req->setPaddr(
ce->pte.translate(
vaddr));
590 if (
ce->pte.sideffect() || (
ce->pte.paddr() >> 39) & 1) {
603 bool addr_mask =
bits(tlbdata,3,3);
604 bool lsu_dm =
bits(tlbdata,5,5);
606 int part_id =
bits(tlbdata,15,8);
607 int tl =
bits(tlbdata,18,16);
608 int pri_context =
bits(tlbdata,47,32);
609 int sec_context =
bits(tlbdata,63,48);
617 DPRINTF(
TLB,
"TLB: priv:%d hpriv:%d red:%d lsudm:%d part_id: %#X\n",
628 context = pri_context;
635 return std::make_shared<PrivilegedAction>();
640 return std::make_shared<DataAccessException>();
644 context = pri_context;
647 context = sec_context;
654 context = pri_context;
658 if (!implicit && asi !=
ASI_P && asi !=
ASI_S) {
660 panic(
"Little Endian ASIs not supported\n");
663 panic(
"Partial Store ASIs not supported\n");
666 panic(
"Cmt ASI registers not implmented\n");
669 goto handleIntRegAccess;
671 goto handleMmuRegAccess;
673 goto handleScratchRegAccess;
675 goto handleQueueRegAccess;
677 goto handleSparcErrorRegAccess;
681 panic(
"Accessing ASI %#X. Should we?\n", asi);
687 return std::make_shared<MemAddressNotAligned>();
695 return std::make_shared<DataAccessException>();
710 if (
e == NULL || !
e->valid) {
712 DPRINTF(
TLB,
"TLB: DTB Failed to find matching TLB entry\n");
714 return std::make_shared<DataRealTranslationMiss>();
717 return std::make_shared<FastDataAccessMMUMiss>();
719 return std::make_shared<FastDataAccessMMUMiss>(
725 if (!
priv &&
e->pte.priv()) {
728 return std::make_shared<DataAccessException>();
731 if (write && !
e->pte.writable()) {
734 return std::make_shared<FastDataAccessProtection>();
740 return std::make_shared<DataAccessException>();
746 return std::make_shared<DataAccessException>();
749 if (
e->pte.sideffect() || (
e->pte.paddr() >> 39) & 1)
768 req->setPaddr(
e->pte.translate(
vaddr));
777 return std::make_shared<DataAccessException>();
779 return std::make_shared<PrivilegedAction>();
785 return std::make_shared<DataAccessException>();
791handleScratchRegAccess:
794 return std::make_shared<DataAccessException>();
801 return std::make_shared<PrivilegedAction>();
805 return std::make_shared<DataAccessException>();
809handleSparcErrorRegAccess:
813 return std::make_shared<DataAccessException>();
815 return std::make_shared<PrivilegedAction>();
822 DPRINTF(
TLB,
"TLB: DTB Translating local access\n");
823 req->setLocalAccessor(
824 [
this,write](ThreadContext *tc,
PacketPtr pkt) -> Cycles
829 req->setPaddr(req->getVaddr());
863 bool addr_mask =
bits(tlbdata,3,3);
864 bool data_real = !
bits(tlbdata,5,5);
865 bool inst_real = !
bits(tlbdata,4,4);
866 bool ctx_zero =
bits(tlbdata,18,16) > 0;
867 int part_id =
bits(tlbdata,15,8);
868 int pri_context =
bits(tlbdata,47,32);
880 req->setPaddr(
vaddr);
889 return std::make_shared<InstructionAccessException>();
891 return std::make_shared<DataAccessException>();
894 tbe =
lookup(
vaddr, part_id, real, ctx_zero ? 0 : pri_context,
false);
910 for (
int x = 0;
x < 4;
x++) {
911 ttetag =
betoh(
mem.read<uint64_t>(tsbs[
x]));
912 if (ttetag.
valid() && ttetag.
va() == va_tag) {
913 uint64_t entry =
mem.read<uint64_t>(tsbs[
x]) +
sizeof(uint64_t);
916 DPRINTF(
TLB,
"Virtual(%#x)->Physical(%#x) found in TTE\n",
925 return std::make_shared<InstructionRealTranslationMiss>();
927 return std::make_shared<FastInstructionAccessMMUMiss>();
929 return std::make_shared<FastInstructionAccessMMUMiss>(
vaddr);
932 return std::make_shared<DataRealTranslationMiss>();
934 return std::make_shared<FastDataAccessMMUMiss>();
936 return std::make_shared<FastDataAccessMMUMiss>(
vaddr);
962 DPRINTF(IPR,
"Memory Mapped IPR Read: asi=%#X a=%#x\n",
963 (uint32_t)pkt->
req->getArchFlags(), pkt->
getAddr());
1037 pkt->
setBE((uint64_t)0);
1056 goto doMmuReadError;
1078 goto doMmuReadError;
1133 panic(
"need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
1145 ASI asi = (
ASI)pkt->
req->getArchFlags();
1151 int entry_insert = -1;
1158 DPRINTF(IPR,
"Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n",
1159 (uint32_t)asi,
va,
data);
1177 goto doMmuWriteError;
1235 inform(
"Ignoring write to SPARC ERROR regsiter\n");
1250 goto doMmuWriteError;
1254 entry_insert =
bits(
va, 8,3);
1257 assert(entry_insert != -1 ||
mbits(
va,10,9) ==
va);
1259 va_insert =
mbits(ta_insert, 63,13);
1260 ct_insert =
mbits(ta_insert, 12,0);
1262 real_insert =
bits(
va, 9,9);
1265 itb->
insert(va_insert, part_insert, ct_insert, real_insert,
1269 entry_insert =
bits(
va, 8,3);
1272 assert(entry_insert != -1 ||
mbits(
va,10,9) ==
va);
1274 va_insert =
mbits(ta_insert, 63,13);
1275 ct_insert =
mbits(ta_insert, 12,0);
1277 real_insert =
bits(
va, 9,9);
1280 insert(va_insert, part_insert, ct_insert, real_insert, pte,
1314 panic(
"Invalid type for IMMU demap\n");
1329 goto doMmuWriteError;
1363 panic(
"Invalid type for IMMU demap\n");
1381 getCpuPtr()->postInterrupt(0,
bits(
data, 5, 0), 0);
1385 panic(
"need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
1421 uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config)
1434 uint64_t ptr =
mbits(tsb,63,13);
1435 bool split =
bits(tsb,12,12);
1436 int tsb_size =
bits(tsb,3,0);
1437 int page_size = (
ps ==
Ps0) ?
bits(config, 2,0) :
bits(config,10,8);
1439 if (
ps ==
Ps1 && split)
1440 ptr |= 1ULL << (13 + tsb_size);
1441 ptr |= (
tag_access >> (9 + page_size * 3)) &
mask(12+tsb_size, 4);
1456 free_list.push_back(entry -
tlb);
1470 for (
int x = 0;
x <
size;
x++) {
1482 if (oldSize !=
size)
1483 panic(
"Don't support unserializing different sized TLBs\n");
1490 for (
int idx : free_list)
1503 for (
int x = 0;
x <
size;
x++) {
BaseInterrupts * getInterruptController(ThreadID tid)
void clearInterrupt(ThreadID tid, int int_num, int index)
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode)=0
Cycles is a wrapper class for representing cycle counts, i.e.
bool translate(Addr vaddr, Addr &paddr)
Translate function.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void setBE(T v)
Set the value in the data pointer to v as big endian.
T getBE() const
Get the data in the packet byte swapped from big endian to host endian.
RequestPtr req
A pointer to the original request.
void makeAtomicResponse()
This object is a proxy for a port or other object which implements the functional response protocol,...
EmulationPageTable * pTable
@ STRICT_ORDER
The request is required to be strictly ordered by CPU models and is non-speculative.
@ UNCACHEABLE
The request is to an uncacheable address.
uint64_t get_vec(int int_num)
Addr translate(Addr vaddr) const
void populate(uint64_t e, EntryType t=sun4u)
uint64_t TagRead(int entry)
Given an entry id, read that tlb entries' tag.
void demapPage(Addr va, int partition_id, bool real, int context_id)
Remve all entries that match a certain partition id, (contextid), and va).
void GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Cycles doMmuRegWrite(ThreadContext *tc, Packet *pkt)
uint64_t MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb, uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config)
void writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi)
std::list< TlbEntry * > freeList
void flushAll() override
Remove all entries from the TLB.
void demapContext(int partition_id, int context_id)
Remove all entries that match a given context/partition id.
void translateTiming(const RequestPtr &req, ThreadContext *tc, BaseMMU::Translation *translation, BaseMMU::Mode mode) override
uint64_t TteRead(int entry)
Give an entry id, read that tlb entries' tte.
Fault finalizePhysical(const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) const override
Do post-translation physical address finalization.
Fault translateAtomic(const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) override
TlbEntry * lookup(Addr va, int partition_id, bool real, int context_id=0, bool update_used=true)
lookup an entry in the TLB based on the partition id, and real bit if real is true or the partition i...
Fault translateInst(const RequestPtr &req, ThreadContext *tc)
Fault translateData(const RequestPtr &req, ThreadContext *tc, bool write)
void insert(Addr vpn, int partition_id, int context_id, bool real, const PageTableEntry &PTE, int entry=-1)
Insert a PTE into the TLB.
bool validVirtualAddress(Addr va, bool am)
Checks if the virtual address provided is a valid one.
void demapAll(int partition_id)
Remove all non-locked entries from the tlb that match partition id.
void serialize(CheckpointOut &cp) const override
Serialize an object.
Fault translateFunctional(const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) override
void writeTagAccess(Addr va, int context)
Cycles doMmuRegRead(ThreadContext *tc, Packet *pkt)
iterator insert(TlbRange &r, TlbEntry *d)
iterator find(const TlbRange &r)
Addr cacheLineSize() const
Get the cache line size of the system.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
virtual System * getSystemPtr()=0
virtual BaseCPU * getCpuPtr()=0
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
virtual BaseMMU * getMMUPtr()=0
virtual Process * getProcessPtr()=0
constexpr int findMsbSet(uint64_t val)
Returns the bit position of the MSB that is set in the input.
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 T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
constexpr uint64_t szext(uint64_t val)
Sign-extend an N-bit value to 64 bits.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal(...)
This implements a cprintf based fatal() function.
#define UNSERIALIZE_CONTAINER(member)
#define SERIALIZE_CONTAINER(member)
@ MISCREG_SCRATCHPAD_R0
Scratchpad regiscers.
@ MISCREG_MMU_P_CONTEXT
MMU Internal Registers.
@ MISCREG_QUEUE_CPU_MONDO_HEAD
bool asiIsNucleus(ASI asi)
bool asiIsAsIfUser(ASI asi)
bool asiIsUnPriv(ASI asi)
bool asiIsPrimary(ASI asi)
bool asiIsPartialStore(ASI asi)
bool asiIsLittle(ASI asi)
bool asiIsInterrupt(ASI asi)
@ ASI_DMMU_TSB_PS1_PTR_REG
@ ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1
@ ASI_IMMU_CTXT_ZERO_CONFIG
@ ASI_DMMU_TSB_PS0_PTR_REG
@ ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0
@ ASI_IMMU_CTXT_NONZERO_CONFIG
@ ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1
@ ASI_ITLB_DATA_ACCESS_REG
@ ASI_DTLB_DATA_ACCESS_REG
@ ASI_IMMU_TSB_PS0_PTR_REG
@ ASI_DMMU_CTXT_ZERO_CONFIG
@ ASI_SPARC_ERROR_STATUS_REG
@ ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0
@ ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0
@ ASI_IMMU_TSB_PS1_PTR_REG
@ ASI_DMMU_CTXT_NONZERO_CONFIG
@ ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0
@ ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1
@ ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1
bool asiIsNoFault(ASI asi)
bool asiIsScratchPad(ASI asi)
bool asiIsSparcError(ASI asi)
const Addr StartVAddrHole
bool asiIsSecondary(ASI asi)
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
std::shared_ptr< FaultBase > Fault
std::shared_ptr< Request > RequestPtr
static void ignore(const char *expr)
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
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.
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
void unserialize(CheckpointIn &cp)
void serialize(CheckpointOut &cp) const