42 #include "debug/IPR.hh"
43 #include "debug/TLB.hh"
55 cacheState(0), cacheValid(false)
59 fatal(
"SPARC T1 TLB registers don't support more than 64 TLB entries");
104 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);
117 for (x = 0; x <
size; x++) {
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());
161 new_entry = &
tlb[size-1];
167 if (new_entry->
valid)
177 new_entry->
pte = PTE;
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);
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",
401 va, context,
mbits(va, 63,13) |
mbits(context,12,0));
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",
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",
458 priv, hpriv, red, lsu_im, part_id);
467 context = pri_context;
470 if ( hpriv || red ) {
481 return std::make_shared<MemAddressNotAligned>();
489 return std::make_shared<InstructionAccessException>();
493 e =
lookup(vaddr, part_id,
true);
497 e =
lookup(vaddr, part_id,
false, context);
500 if (e == NULL || !e->
valid) {
503 return std::make_shared<InstructionRealTranslationMiss>();
506 return std::make_shared<FastInstructionAccessMMUMiss>();
508 return std::make_shared<FastInstructionAccessMMUMiss>(
517 return std::make_shared<InstructionAccessException>();
542 bool implicit =
false;
544 bool unaligned = vaddr & (size - 1);
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 &&
587 ce_va < vaddr + size && ce_va + ce->range.size > vaddr &&
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",
618 priv, hpriv, red, lsu_dm, part_id);
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");
669 panic(
"Partial Store ASIs not supported\n");
672 panic(
"Cmt ASI registers not implmented\n");
675 goto handleIntRegAccess;
677 goto handleMmuRegAccess;
679 goto handleScratchRegAccess;
681 goto handleQueueRegAccess;
683 goto handleSparcErrorRegAccess;
687 panic(
"Accessing ASI %#X. Should we?\n", asi);
693 return std::make_shared<MemAddressNotAligned>();
701 return std::make_shared<DataAccessException>();
704 if ((!lsu_dm && !hpriv && !red) ||
asiIsReal(asi)) {
714 e =
lookup(vaddr, part_id, real, context);
716 if (e == NULL || !e->
valid) {
718 DPRINTF(
TLB,
"TLB: DTB Failed to find matching TLB entry\n");
720 return std::make_shared<DataRealTranslationMiss>();
723 return std::make_shared<FastDataAccessMMUMiss>();
725 return std::make_shared<FastDataAccessMMUMiss>(
734 return std::make_shared<DataAccessException>();
740 return std::make_shared<FastDataAccessProtection>();
746 return std::make_shared<DataAccessException>();
752 return std::make_shared<DataAccessException>();
783 return std::make_shared<DataAccessException>();
785 return std::make_shared<PrivilegedAction>();
791 return std::make_shared<DataAccessException>();
797 handleScratchRegAccess:
798 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
800 return std::make_shared<DataAccessException>();
804 handleQueueRegAccess:
805 if (!priv && !hpriv) {
807 return std::make_shared<PrivilegedAction>();
809 if ((!hpriv && vaddr & 0xF) || vaddr > 0x3f8 || vaddr < 0x3c0) {
811 return std::make_shared<DataAccessException>();
815 handleSparcErrorRegAccess:
819 return std::make_shared<DataAccessException>();
821 return std::make_shared<PrivilegedAction>();
828 DPRINTF(
TLB,
"TLB: DTB Translating MM IPR access\n");
854 panic(
"Not implemented\n");
871 DPRINTF(IPR,
"Memory Mapped IPR Read: asi=%#X a=%#x\n",
911 pkt->
set(itb->c0_tsb_ps0);
915 pkt->
set(itb->c0_tsb_ps1);
919 pkt->
set(itb->c0_config);
935 pkt->
set(itb->cx_tsb_ps0);
939 pkt->
set(itb->cx_tsb_ps1);
943 pkt->
set(itb->cx_config);
946 pkt->
set((uint64_t)0);
955 temp = itb->tag_access;
956 pkt->
set(
bits(temp,63,22) |
bits(temp,12,0) << 48);
962 pkt->
set(itb->tag_access);
972 pkt->
set(
bits(temp,63,22) |
bits(temp,12,0) << 48);
1026 tc->
getCpuPtr()->getInterruptController(0));
1034 tc->
getCpuPtr()->getInterruptController(0));
1042 panic(
"need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
1052 uint64_t
data = pkt->
get<uint64_t>();
1060 int entry_insert = -1;
1067 DPRINTF(IPR,
"Memory Mapped IPR Write: asi=%#X a=%#x d=%#X\n",
1068 (uint32_t)asi, va, data);
1086 goto doMmuWriteError;
1090 assert(
mbits(data,13,6) == data);
1092 (va >> 4) - 0x3c, data);
1144 inform(
"Ignoring write to SPARC ERROR regsiter\n");
1156 sext<59>(
bits(data, 59,0));
1160 goto doMmuWriteError;
1164 entry_insert =
bits(va, 8,3);
1166 assert(entry_insert != -1 ||
mbits(va,10,9) == va);
1168 va_insert =
mbits(ta_insert, 63,13);
1169 ct_insert =
mbits(ta_insert, 12,0);
1171 real_insert =
bits(va, 9,9);
1174 tc->
getITBPtr()->insert(va_insert, part_insert, ct_insert, real_insert,
1178 entry_insert =
bits(va, 8,3);
1180 assert(entry_insert != -1 ||
mbits(va,10,9) == va);
1182 va_insert =
mbits(ta_insert, 63,13);
1183 ct_insert =
mbits(ta_insert, 12,0);
1185 real_insert =
bits(va, 9,9);
1187 PageTableEntry::sun4u);
1188 insert(va_insert, part_insert, ct_insert, real_insert, pte,
1195 switch (
bits(va,5,4)) {
1209 switch (
bits(va,7,6)) {
1213 bits(va,9,9), ctx_id);
1217 tc->
getITBPtr()->demapContext(part_id, ctx_id);
1223 panic(
"Invalid type for IMMU demap\n");
1232 sext<59>(
bits(data, 59,0));
1239 goto doMmuWriteError;
1246 switch (
bits(va,5,4)) {
1260 switch (
bits(va,7,6)) {
1273 panic(
"Invalid type for IMMU demap\n");
1282 tc->
getCpuPtr()->getInterruptController(0));
1291 postInterrupt(0,
bits(data, 5, 0), 0);
1295 panic(
"need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
1331 uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config)
1336 if (
bits(tag_access, 12,0) == 0) {
1344 uint64_t ptr =
mbits(tsb,63,13);
1345 bool split =
bits(tsb,12,12);
1346 int tsb_size =
bits(tsb,3,0);
1347 int page_size = (ps ==
Ps0) ?
bits(config, 2,0) :
bits(config,10,8);
1349 if (ps ==
Ps1 && split)
1350 ptr |=
ULL(1) << (13 + tsb_size);
1351 ptr |= (tag_access >> (9 + page_size * 3)) &
mask(12+tsb_size, 4);
1366 free_list.push_back(entry -
tlb);
1379 for (
int x = 0;
x <
size;
x++) {
1392 if (oldSize !=
size)
1393 panic(
"Don't support unserializing different sized TLBs\n");
1400 for (
int idx : free_list)
1413 for (
int x = 0;
x <
size;
x++) {
1426 SparcTLBParams::create()
Addr translate(Addr vaddr) const
void demapContext(int partition_id, int context_id)
Remove all entries that match a given context/partition id.
static void ignore(const char *expr)
bool asiIsSparcError(ASI asi)
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
void writeSfsr(bool write, ContextType ct, bool se, FaultTypes ft, int asi)
virtual System * getSystemPtr()=0
decltype(nullptr) constexpr NoFault
Cycles is a wrapper class for representing cycle counts, i.e.
iterator insert(TlbRange &r, TlbEntry *d)
Fault translateInst(RequestPtr req, ThreadContext *tc)
void unserialize(CheckpointIn &cp)
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
virtual MiscReg readMiscRegNoEffect(int misc_reg) const =0
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
virtual void setMiscReg(int misc_reg, const MiscReg &val)=0
bool validVirtualAddress(Addr va, bool am)
Checks if the virtual address provided is a valid one.
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)
virtual BaseCPU * getCpuPtr()=0
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...
ThreadContext is the external interface to all thread state for anything outside of the CPU...
Cycles doMmuRegRead(ThreadContext *tc, Packet *pkt)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void populate(uint64_t e, EntryType t=sun4u)
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_CONTAINER(member)
Cycles doMmuRegWrite(ThreadContext *tc, Packet *pkt)
std::list< TlbEntry * > freeList
std::string csprintf(const char *format, const Args &...args)
void demapPage(Addr va, int partition_id, bool real, int context_id)
Remve all entries that match a certain partition id, (contextid), and va).
const Addr StartVAddrHole
void makeAtomicResponse()
uint64_t get_vec(int int_num)
void serialize(CheckpointOut &cp) const
void flushAll() override
Remove all entries from the TLB.
The request is to an uncacheable address.
std::vector< ThreadContext * > threadContexts
const RequestPtr req
A pointer to the original request.
Fault finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
bool asiIsPrimary(ASI asi)
#define UNSERIALIZE_CONTAINER(member)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
#define ULL(N)
uint64_t constant
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
void writeTagAccess(Addr va, int context)
bool asiIsScratchPad(ASI asi)
#define SERIALIZE_SCALAR(scalar)
ArchFlagsType getArchFlags() const
Accessor function for architecture-specific flags.
Fault translateData(RequestPtr req, ThreadContext *tc, bool write)
virtual MiscReg readMiscReg(int misc_reg)=0
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 asiIsNoFault(ASI asi)
void GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs)
std::ostream CheckpointOut
uint64_t TagRead(int entry)
Given an entry id, read that tlb entries' tag.
void serialize(CheckpointOut &cp) const override
Serialize an object.
bool asiIsUnPriv(ASI asi)
iterator find(const TlbRange &r)
uint64_t TteRead(int entry)
Give an entry id, read that tlb entries' tte.
The request is required to be strictly ordered by CPU models and is non-speculative.
int findMsbSet(uint64_t val)
Returns the bit position of the MSB that is set in the input.
bool asiIsInterrupt(ASI asi)
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
bool asiIsAsIfUser(ASI asi)
bool asiIsLittle(ASI asi)
Fault translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode)
Stub function for compilation support with CheckerCPU.
T mbits(T val, int first, int last)
Mask off the given bits in place like bits() but without shifting.
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
This request is to a memory mapped register.
void demapAll(int partition_id)
Remove all non-locked entries from the tlb that match partition id.
Scoped checkpoint section helper class.
void setPaddr(Addr paddr)
Set just the physical address.
bool asiIsNucleus(ASI asi)
bool asiIsSecondary(ASI asi)
virtual void finish(const Fault &fault, RequestPtr req, ThreadContext *tc, Mode mode)=0
void setFlags(Flags flags)
Note that unlike other accessors, this function sets specific flags (ORs them in); it does not assign...
std::shared_ptr< FaultBase > Fault
virtual TheISA::TLB * getITBPtr()=0
bool asiIsPartialStore(ASI asi)
void translateTiming(RequestPtr req, ThreadContext *tc, Translation *translation, Mode mode)