2 * Copyright 2007 MIPS Technologies, Inc. All Rights Reserved
4 * This software is part of the M5 simulator.
6 * THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING
7 * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING
8 * TO THESE TERMS AND CONDITIONS.
10 * Permission is granted to use, copy, create derivative works and
11 * distribute this software and such derivative works for any purpose,
12 * so long as (1) the copyright notice above, this grant of permission,
13 * and the disclaimer below appear in all copies and derivative works
14 * made, (2) the copyright notice above is augmented as appropriate to
15 * reflect the addition of any new copyrightable work in a derivative
16 * work (e.g., Copyright \eN) <Publication Year> Copyright Owner), and (3)
17 * the name of MIPS Technologies, Inc. (\e$(B!H\e(BMIPS\e$(B!I\e(B) is not used in any
18 * advertising or publicity pertaining to the use or distribution of
19 * this software without specific, written prior authorization.
21 * THIS SOFTWARE IS PROVIDED \e$(B!H\e(BAS IS.\e$(B!I\e(B MIPS MAKES NO WARRANTIES AND
22 * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR
23 * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
25 * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE.
26 * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT,
27 * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF
28 * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT,
29 * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY
30 * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR
31 * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE
32 * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE.
34 * Authors: Jaidev P. Patwardhan
41 #include "arch/mips/pra_constants.hh"
42 #include "arch/mips/pagetable.hh"
43 #include "arch/mips/tlb.hh"
44 #include "arch/mips/faults.hh"
45 #include "arch/mips/utility.hh"
46 #include "base/inifile.hh"
47 #include "base/str.hh"
48 #include "base/trace.hh"
49 #include "cpu/thread_context.hh"
50 #include "params/MipsDTB.hh"
51 #include "params/MipsITB.hh"
52 #include "params/MipsTLB.hh"
53 #include "params/MipsUTB.hh"
57 using namespace MipsISA
;
59 ///////////////////////////////////////////////////////////////////////
64 #define MODE2MASK(X) (1 << (X))
66 TLB::TLB(const Params
*p
)
67 : SimObject(p
), size(p
->size
), nlu(0)
69 table
= new MipsISA::PTE
[size
];
70 memset(table
, 0, sizeof(MipsISA::PTE
[size
]));
80 // look up an entry in the TLB
82 TLB::lookup(Addr vpn
, uint8_t asn
) const
84 // assume not found...
85 MipsISA::PTE
*retval
= NULL
;
86 PageTable::const_iterator i
= lookupTable
.find(vpn
);
87 if (i
!= lookupTable
.end()) {
88 while (i
->first
== vpn
) {
89 int index
= i
->second
;
90 MipsISA::PTE
*pte
= &table
[index
];
92 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
93 Addr Mask
= pte
->Mask
;
96 // warn("Valid: %d - %d\n",pte->V0,pte->V1);
97 if(((vpn
& InvMask
) == (VPN
& InvMask
)) && (pte
->G
|| (asn
== pte
->asid
)))
98 { // We have a VPN + ASID Match
106 DPRINTF(TLB
, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn
, (int)asn
,
107 retval
? "hit" : "miss", retval
? retval
->PFN1
: 0);
111 MipsISA::PTE
* TLB::getEntry(unsigned Index
) const
113 // Make sure that Index is valid
115 return &table
[Index
];
118 int TLB::probeEntry(Addr vpn
,uint8_t asn
) const
120 // assume not found...
121 MipsISA::PTE
*retval
= NULL
;
123 PageTable::const_iterator i
= lookupTable
.find(vpn
);
124 if (i
!= lookupTable
.end()) {
125 while (i
->first
== vpn
) {
126 int index
= i
->second
;
127 MipsISA::PTE
*pte
= &table
[index
];
129 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
130 Addr Mask
= pte
->Mask
;
131 Addr InvMask
= ~Mask
;
133 if(((vpn
& InvMask
) == (VPN
& InvMask
)) && (pte
->G
|| (asn
== pte
->asid
)))
134 { // We have a VPN + ASID Match
143 DPRINTF(MipsPRA
,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn
,asn
,Ind
);
147 TLB::checkCacheability(RequestPtr
&req
)
149 Addr VAddrUncacheable
= 0xA0000000;
150 // In MIPS, cacheability is controlled by certain bits of the virtual address
151 // or by the TLB entry
152 if((req
->getVaddr() & VAddrUncacheable
) == VAddrUncacheable
) {
153 // mark request as uncacheable
154 req
->setFlags(req
->getFlags() | UNCACHEABLE
);
158 void TLB::insertAt(MipsISA::PTE
&pte
, unsigned Index
, int _smallPages
)
160 smallPages
=_smallPages
;
162 warn("Attempted to write at index (%d) beyond TLB size (%d)",Index
,size
);
165 DPRINTF(TLB
,"TLB[%d]: %x %x %x %x\n",Index
,pte
.Mask
<<11,((pte
.VPN
<< 11) | pte
.asid
),((pte
.PFN0
<<6) | (pte
.C0
<< 3) | (pte
.D0
<< 2) | (pte
.V0
<<1) | pte
.G
),
166 ((pte
.PFN1
<<6) | (pte
.C1
<< 3) | (pte
.D1
<< 2) | (pte
.V1
<<1) | pte
.G
));
167 if(table
[Index
].V0
== true || table
[Index
].V1
== true){ // Previous entry is valid
168 PageTable::iterator i
= lookupTable
.find(table
[Index
].VPN
);
169 lookupTable
.erase(i
);
172 // Update fast lookup table
173 lookupTable
.insert(make_pair(table
[Index
].VPN
, Index
));
174 // int TestIndex=probeEntry(pte.VPN,pte.asid);
175 // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask);
180 // insert a new TLB entry
182 TLB::insert(Addr addr
, MipsISA::PTE
&pte
)
184 fatal("TLB Insert not yet implemented\n");
187 /* MipsISA::VAddr vaddr = addr;
188 if (table[nlu].valid) {
189 Addr oldvpn = table[nlu].tag;
190 PageTable::iterator i = lookupTable.find(oldvpn);
192 if (i == lookupTable.end())
193 panic("TLB entry not found in lookupTable");
196 while ((index = i->second) != nlu) {
197 if (table[index].tag != oldvpn)
198 panic("TLB entry not found in lookupTable");
203 DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
205 lookupTable.erase(i);
208 DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
211 table[nlu].tag = vaddr.vpn();
212 table[nlu].valid = true;
214 lookupTable.insert(make_pair(vaddr.vpn(), nlu));
222 DPRINTF(TLB
, "flushAll\n");
223 memset(table
, 0, sizeof(MipsISA::PTE
[size
]));
229 TLB::serialize(ostream
&os
)
231 SERIALIZE_SCALAR(size
);
232 SERIALIZE_SCALAR(nlu
);
234 for (int i
= 0; i
< size
; i
++) {
235 nameOut(os
, csprintf("%s.PTE%d", name(), i
));
236 table
[i
].serialize(os
);
241 TLB::unserialize(Checkpoint
*cp
, const string
§ion
)
243 UNSERIALIZE_SCALAR(size
);
244 UNSERIALIZE_SCALAR(nlu
);
246 for (int i
= 0; i
< size
; i
++) {
247 table
[i
].unserialize(cp
, csprintf("%s.PTE%d", section
, i
));
248 if (table
[i
].V0
|| table
[i
].V1
) {
249 lookupTable
.insert(make_pair(table
[i
].VPN
, i
));
258 .name(name() + ".read_hits")
259 .desc("DTB read hits")
263 .name(name() + ".read_misses")
264 .desc("DTB read misses")
269 .name(name() + ".read_accesses")
270 .desc("DTB read accesses")
274 .name(name() + ".write_hits")
275 .desc("DTB write hits")
279 .name(name() + ".write_misses")
280 .desc("DTB write misses")
285 .name(name() + ".write_accesses")
286 .desc("DTB write accesses")
290 .name(name() + ".hits")
295 .name(name() + ".misses")
300 .name(name() + ".invalids")
301 .desc("DTB access violations")
305 .name(name() + ".accesses")
306 .desc("DTB accesses")
309 hits
= read_hits
+ write_hits
;
310 misses
= read_misses
+ write_misses
;
311 accesses
= read_accesses
+ write_accesses
;
315 ITB::translate(RequestPtr
&req
, ThreadContext
*tc
)
317 if(MipsISA::IsKSeg0(req
->getVaddr()))
319 // Address will not be translated through TLB, set response, and go!
320 req
->setPaddr(MipsISA::KSeg02Phys(req
->getVaddr()));
321 if(MipsISA::getOperatingMode(tc
->readMiscReg(MipsISA::Status
)) != mode_kernel
|| req
->isMisaligned())
323 AddressErrorFault
*Flt
= new AddressErrorFault();
324 /* BadVAddr must be set */
325 Flt
->BadVAddr
= req
->getVaddr();
329 else if(MipsISA::IsKSeg1(req
->getVaddr()))
331 // Address will not be translated through TLB, set response, and go!
332 req
->setPaddr(MipsISA::KSeg02Phys(req
->getVaddr()));
336 /* This is an optimization - smallPages is updated every time a TLB operation is performed
337 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
341 VPN
=((req
->getVaddr() >> 11));
343 VPN
=((req
->getVaddr() >> 11) & 0xFFFFFFFC);
345 uint8_t Asid
= req
->getAsid();
346 if(req
->isMisaligned()){ // Unaligned address!
347 AddressErrorFault
*Flt
= new AddressErrorFault();
348 /* BadVAddr must be set */
349 Flt
->BadVAddr
= req
->getVaddr();
352 MipsISA::PTE
*pte
= lookup(VPN
,Asid
);
354 {// Ok, found something
355 /* Check for valid bits */
358 if((((req
->getVaddr()) >> pte
->AddrShiftAmount
) & 1) ==0){
370 ItbInvalidFault
*Flt
= new ItbInvalidFault();
371 /* EntryHi VPN, ASID fields must be set */
372 Flt
->EntryHi_Asid
= Asid
;
373 Flt
->EntryHi_VPN2
= (VPN
>>2);
374 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
376 /* BadVAddr must be set */
377 Flt
->BadVAddr
= req
->getVaddr();
379 /* Context must be set */
380 Flt
->Context_BadVPN2
= (VPN
>> 2);
384 {// Ok, this is really a match, set paddr
392 PAddr
>>= (pte
->AddrShiftAmount
-12);
393 PAddr
<<= pte
->AddrShiftAmount
;
394 PAddr
|= ((req
->getVaddr()) & pte
->OffsetMask
);
395 req
->setPaddr(PAddr
);
401 { // Didn't find any match, return a TLB Refill Exception
403 ItbRefillFault
*Flt
=new ItbRefillFault();
404 /* EntryHi VPN, ASID fields must be set */
405 Flt
->EntryHi_Asid
= Asid
;
406 Flt
->EntryHi_VPN2
= (VPN
>>2);
407 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
410 /* BadVAddr must be set */
411 Flt
->BadVAddr
= req
->getVaddr();
413 /* Context must be set */
414 Flt
->Context_BadVPN2
= (VPN
>> 2);
418 return checkCacheability(req
);
422 DTB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
)
424 if(MipsISA::IsKSeg0(req
->getVaddr()))
426 // Address will not be translated through TLB, set response, and go!
427 req
->setPaddr(MipsISA::KSeg02Phys(req
->getVaddr()));
428 if(MipsISA::getOperatingMode(tc
->readMiscReg(MipsISA::Status
)) != mode_kernel
|| req
->isMisaligned())
430 StoreAddressErrorFault
*Flt
= new StoreAddressErrorFault();
431 /* BadVAddr must be set */
432 Flt
->BadVAddr
= req
->getVaddr();
437 else if(MipsISA::IsKSeg1(req
->getVaddr()))
439 // Address will not be translated through TLB, set response, and go!
440 req
->setPaddr(MipsISA::KSeg02Phys(req
->getVaddr()));
444 /* This is an optimization - smallPages is updated every time a TLB operation is performed
445 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
447 Addr VPN
=((req
->getVaddr() >> 11) & 0xFFFFFFFC);
449 VPN
=((req
->getVaddr() >> 11));
451 uint8_t Asid
= req
->getAsid();
452 MipsISA::PTE
*pte
= lookup(VPN
,Asid
);
453 if(req
->isMisaligned()){ // Unaligned address!
454 StoreAddressErrorFault
*Flt
= new StoreAddressErrorFault();
455 /* BadVAddr must be set */
456 Flt
->BadVAddr
= req
->getVaddr();
460 {// Ok, found something
461 /* Check for valid bits */
465 if(((((req
->getVaddr()) >> pte
->AddrShiftAmount
) & 1)) ==0){
481 DtbInvalidFault
*Flt
= new DtbInvalidFault();
482 /* EntryHi VPN, ASID fields must be set */
483 Flt
->EntryHi_Asid
= Asid
;
484 Flt
->EntryHi_VPN2
= (VPN
>>2);
485 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
488 /* BadVAddr must be set */
489 Flt
->BadVAddr
= req
->getVaddr();
491 /* Context must be set */
492 Flt
->Context_BadVPN2
= (VPN
>> 2);
497 {// Ok, this is really a match, set paddr
501 TLBModifiedFault
*Flt
= new TLBModifiedFault();
502 /* EntryHi VPN, ASID fields must be set */
503 Flt
->EntryHi_Asid
= Asid
;
504 Flt
->EntryHi_VPN2
= (VPN
>>2);
505 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
508 /* BadVAddr must be set */
509 Flt
->BadVAddr
= req
->getVaddr();
511 /* Context must be set */
512 Flt
->Context_BadVPN2
= (VPN
>> 2);
522 PAddr
>>= (pte
->AddrShiftAmount
-12);
523 PAddr
<<= pte
->AddrShiftAmount
;
524 PAddr
|= ((req
->getVaddr()) & pte
->OffsetMask
);
525 req
->setPaddr(PAddr
);
529 { // Didn't find any match, return a TLB Refill Exception
531 DtbRefillFault
*Flt
=new DtbRefillFault();
532 /* EntryHi VPN, ASID fields must be set */
533 Flt
->EntryHi_Asid
= Asid
;
534 Flt
->EntryHi_VPN2
= (VPN
>>2);
535 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
538 /* BadVAddr must be set */
539 Flt
->BadVAddr
= req
->getVaddr();
541 /* Context must be set */
542 Flt
->Context_BadVPN2
= (VPN
>> 2);
546 return checkCacheability(req
);
549 ///////////////////////////////////////////////////////////////////////
553 ITB::ITB(const Params
*p
)
561 // /* hits - causes failure for some reason
562 // .name(name() + ".hits")
563 // .desc("ITB hits");
565 // .name(name() + ".misses")
566 // .desc("ITB misses");
568 // .name(name() + ".acv")
571 // .name(name() + ".accesses")
572 // .desc("ITB accesses");
574 // accesses = hits + misses + invalids; */
579 ///////////////////////////////////////////////////////////////////////
583 DTB::DTB(const Params
*p
)
587 ///////////////////////////////////////////////////////////////////////
591 UTB::UTB(const Params
*p
)
598 TLB::index(bool advance
)
600 MipsISA::PTE
*pte
= &table
[nlu
];
609 MipsITBParams::create()
611 return new MipsISA::ITB(this);
615 MipsDTBParams::create()
617 return new MipsISA::DTB(this);
621 MipsUTBParams::create()
623 return new MipsISA::UTB(this);