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 "sim/process.hh"
51 #include "mem/page_table.hh"
52 #include "params/MipsDTB.hh"
53 #include "params/MipsITB.hh"
54 #include "params/MipsTLB.hh"
55 #include "params/MipsUTB.hh"
59 using namespace MipsISA
;
61 ///////////////////////////////////////////////////////////////////////
66 #define MODE2MASK(X) (1 << (X))
68 TLB::TLB(const Params
*p
)
69 : SimObject(p
), size(p
->size
), nlu(0)
71 table
= new MipsISA::PTE
[size
];
72 memset(table
, 0, sizeof(MipsISA::PTE
[size
]));
82 // look up an entry in the TLB
84 TLB::lookup(Addr vpn
, uint8_t asn
) const
86 // assume not found...
87 MipsISA::PTE
*retval
= NULL
;
88 PageTable::const_iterator i
= lookupTable
.find(vpn
);
89 if (i
!= lookupTable
.end()) {
90 while (i
->first
== vpn
) {
91 int index
= i
->second
;
92 MipsISA::PTE
*pte
= &table
[index
];
94 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
95 Addr Mask
= pte
->Mask
;
98 // warn("Valid: %d - %d\n",pte->V0,pte->V1);
99 if(((vpn
& InvMask
) == (VPN
& InvMask
)) && (pte
->G
|| (asn
== pte
->asid
)))
100 { // We have a VPN + ASID Match
108 DPRINTF(TLB
, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn
, (int)asn
,
109 retval
? "hit" : "miss", retval
? retval
->PFN1
: 0);
113 MipsISA::PTE
* TLB::getEntry(unsigned Index
) const
115 // Make sure that Index is valid
117 return &table
[Index
];
120 int TLB::probeEntry(Addr vpn
,uint8_t asn
) const
122 // assume not found...
123 MipsISA::PTE
*retval
= NULL
;
125 PageTable::const_iterator i
= lookupTable
.find(vpn
);
126 if (i
!= lookupTable
.end()) {
127 while (i
->first
== vpn
) {
128 int index
= i
->second
;
129 MipsISA::PTE
*pte
= &table
[index
];
131 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
132 Addr Mask
= pte
->Mask
;
133 Addr InvMask
= ~Mask
;
135 if(((vpn
& InvMask
) == (VPN
& InvMask
)) && (pte
->G
|| (asn
== pte
->asid
)))
136 { // We have a VPN + ASID Match
145 DPRINTF(MipsPRA
,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn
,asn
,Ind
);
149 TLB::checkCacheability(RequestPtr
&req
)
151 Addr VAddrUncacheable
= 0xA0000000;
152 // In MIPS, cacheability is controlled by certain bits of the virtual address
153 // or by the TLB entry
154 if((req
->getVaddr() & VAddrUncacheable
) == VAddrUncacheable
) {
155 // mark request as uncacheable
156 req
->setFlags(req
->getFlags() | UNCACHEABLE
);
160 void TLB::insertAt(MipsISA::PTE
&pte
, unsigned Index
, int _smallPages
)
162 smallPages
=_smallPages
;
164 warn("Attempted to write at index (%d) beyond TLB size (%d)",Index
,size
);
167 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
),
168 ((pte
.PFN1
<<6) | (pte
.C1
<< 3) | (pte
.D1
<< 2) | (pte
.V1
<<1) | pte
.G
));
169 if(table
[Index
].V0
== true || table
[Index
].V1
== true){ // Previous entry is valid
170 PageTable::iterator i
= lookupTable
.find(table
[Index
].VPN
);
171 lookupTable
.erase(i
);
174 // Update fast lookup table
175 lookupTable
.insert(make_pair(table
[Index
].VPN
, Index
));
176 // int TestIndex=probeEntry(pte.VPN,pte.asid);
177 // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask);
182 // insert a new TLB entry
184 TLB::insert(Addr addr
, MipsISA::PTE
&pte
)
186 fatal("TLB Insert not yet implemented\n");
189 /* MipsISA::VAddr vaddr = addr;
190 if (table[nlu].valid) {
191 Addr oldvpn = table[nlu].tag;
192 PageTable::iterator i = lookupTable.find(oldvpn);
194 if (i == lookupTable.end())
195 panic("TLB entry not found in lookupTable");
198 while ((index = i->second) != nlu) {
199 if (table[index].tag != oldvpn)
200 panic("TLB entry not found in lookupTable");
205 DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
207 lookupTable.erase(i);
210 DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
213 table[nlu].tag = vaddr.vpn();
214 table[nlu].valid = true;
216 lookupTable.insert(make_pair(vaddr.vpn(), nlu));
224 DPRINTF(TLB
, "flushAll\n");
225 memset(table
, 0, sizeof(MipsISA::PTE
[size
]));
231 TLB::serialize(ostream
&os
)
233 SERIALIZE_SCALAR(size
);
234 SERIALIZE_SCALAR(nlu
);
236 for (int i
= 0; i
< size
; i
++) {
237 nameOut(os
, csprintf("%s.PTE%d", name(), i
));
238 table
[i
].serialize(os
);
243 TLB::unserialize(Checkpoint
*cp
, const string
§ion
)
245 UNSERIALIZE_SCALAR(size
);
246 UNSERIALIZE_SCALAR(nlu
);
248 for (int i
= 0; i
< size
; i
++) {
249 table
[i
].unserialize(cp
, csprintf("%s.PTE%d", section
, i
));
250 if (table
[i
].V0
|| table
[i
].V1
) {
251 lookupTable
.insert(make_pair(table
[i
].VPN
, i
));
260 .name(name() + ".read_hits")
261 .desc("DTB read hits")
265 .name(name() + ".read_misses")
266 .desc("DTB read misses")
271 .name(name() + ".read_accesses")
272 .desc("DTB read accesses")
276 .name(name() + ".write_hits")
277 .desc("DTB write hits")
281 .name(name() + ".write_misses")
282 .desc("DTB write misses")
287 .name(name() + ".write_accesses")
288 .desc("DTB write accesses")
292 .name(name() + ".hits")
297 .name(name() + ".misses")
302 .name(name() + ".invalids")
303 .desc("DTB access violations")
307 .name(name() + ".accesses")
308 .desc("DTB accesses")
311 hits
= read_hits
+ write_hits
;
312 misses
= read_misses
+ write_misses
;
313 accesses
= read_accesses
+ write_accesses
;
317 ITB::translate(RequestPtr
&req
, ThreadContext
*tc
)
320 Process
* p
= tc
->getProcessPtr();
322 Fault fault
= p
->pTable
->translate(req
);
328 if(MipsISA::IsKSeg0(req
->getVaddr()))
330 // Address will not be translated through TLB, set response, and go!
331 req
->setPaddr(MipsISA::KSeg02Phys(req
->getVaddr()));
332 if(MipsISA::getOperatingMode(tc
->readMiscReg(MipsISA::Status
)) != mode_kernel
|| req
->isMisaligned())
334 AddressErrorFault
*Flt
= new AddressErrorFault();
335 /* BadVAddr must be set */
336 Flt
->BadVAddr
= req
->getVaddr();
340 else if(MipsISA::IsKSeg1(req
->getVaddr()))
342 // Address will not be translated through TLB, set response, and go!
343 req
->setPaddr(MipsISA::KSeg02Phys(req
->getVaddr()));
347 /* This is an optimization - smallPages is updated every time a TLB operation is performed
348 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
352 VPN
=((req
->getVaddr() >> 11));
354 VPN
=((req
->getVaddr() >> 11) & 0xFFFFFFFC);
356 uint8_t Asid
= req
->getAsid();
357 if(req
->isMisaligned()){ // Unaligned address!
358 AddressErrorFault
*Flt
= new AddressErrorFault();
359 /* BadVAddr must be set */
360 Flt
->BadVAddr
= req
->getVaddr();
363 MipsISA::PTE
*pte
= lookup(VPN
,Asid
);
365 {// Ok, found something
366 /* Check for valid bits */
369 if((((req
->getVaddr()) >> pte
->AddrShiftAmount
) & 1) ==0){
381 ItbInvalidFault
*Flt
= new ItbInvalidFault();
382 /* EntryHi VPN, ASID fields must be set */
383 Flt
->EntryHi_Asid
= Asid
;
384 Flt
->EntryHi_VPN2
= (VPN
>>2);
385 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
387 /* BadVAddr must be set */
388 Flt
->BadVAddr
= req
->getVaddr();
390 /* Context must be set */
391 Flt
->Context_BadVPN2
= (VPN
>> 2);
395 {// Ok, this is really a match, set paddr
403 PAddr
>>= (pte
->AddrShiftAmount
-12);
404 PAddr
<<= pte
->AddrShiftAmount
;
405 PAddr
|= ((req
->getVaddr()) & pte
->OffsetMask
);
406 req
->setPaddr(PAddr
);
412 { // Didn't find any match, return a TLB Refill Exception
414 ItbRefillFault
*Flt
=new ItbRefillFault();
415 /* EntryHi VPN, ASID fields must be set */
416 Flt
->EntryHi_Asid
= Asid
;
417 Flt
->EntryHi_VPN2
= (VPN
>>2);
418 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
421 /* BadVAddr must be set */
422 Flt
->BadVAddr
= req
->getVaddr();
424 /* Context must be set */
425 Flt
->Context_BadVPN2
= (VPN
>> 2);
429 return checkCacheability(req
);
434 DTB::translate(RequestPtr
&req
, ThreadContext
*tc
, bool write
)
437 Process
* p
= tc
->getProcessPtr();
439 Fault fault
= p
->pTable
->translate(req
);
445 if(MipsISA::IsKSeg0(req
->getVaddr()))
447 // Address will not be translated through TLB, set response, and go!
448 req
->setPaddr(MipsISA::KSeg02Phys(req
->getVaddr()));
449 if(MipsISA::getOperatingMode(tc
->readMiscReg(MipsISA::Status
)) != mode_kernel
|| req
->isMisaligned())
451 StoreAddressErrorFault
*Flt
= new StoreAddressErrorFault();
452 /* BadVAddr must be set */
453 Flt
->BadVAddr
= req
->getVaddr();
458 else if(MipsISA::IsKSeg1(req
->getVaddr()))
460 // Address will not be translated through TLB, set response, and go!
461 req
->setPaddr(MipsISA::KSeg02Phys(req
->getVaddr()));
465 /* This is an optimization - smallPages is updated every time a TLB operation is performed
466 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
468 Addr VPN
=((req
->getVaddr() >> 11) & 0xFFFFFFFC);
470 VPN
=((req
->getVaddr() >> 11));
472 uint8_t Asid
= req
->getAsid();
473 MipsISA::PTE
*pte
= lookup(VPN
,Asid
);
474 if(req
->isMisaligned()){ // Unaligned address!
475 StoreAddressErrorFault
*Flt
= new StoreAddressErrorFault();
476 /* BadVAddr must be set */
477 Flt
->BadVAddr
= req
->getVaddr();
481 {// Ok, found something
482 /* Check for valid bits */
486 if(((((req
->getVaddr()) >> pte
->AddrShiftAmount
) & 1)) ==0){
502 DtbInvalidFault
*Flt
= new DtbInvalidFault();
503 /* EntryHi VPN, ASID fields must be set */
504 Flt
->EntryHi_Asid
= Asid
;
505 Flt
->EntryHi_VPN2
= (VPN
>>2);
506 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
509 /* BadVAddr must be set */
510 Flt
->BadVAddr
= req
->getVaddr();
512 /* Context must be set */
513 Flt
->Context_BadVPN2
= (VPN
>> 2);
518 {// Ok, this is really a match, set paddr
522 TLBModifiedFault
*Flt
= new TLBModifiedFault();
523 /* EntryHi VPN, ASID fields must be set */
524 Flt
->EntryHi_Asid
= Asid
;
525 Flt
->EntryHi_VPN2
= (VPN
>>2);
526 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
529 /* BadVAddr must be set */
530 Flt
->BadVAddr
= req
->getVaddr();
532 /* Context must be set */
533 Flt
->Context_BadVPN2
= (VPN
>> 2);
543 PAddr
>>= (pte
->AddrShiftAmount
-12);
544 PAddr
<<= pte
->AddrShiftAmount
;
545 PAddr
|= ((req
->getVaddr()) & pte
->OffsetMask
);
546 req
->setPaddr(PAddr
);
550 { // Didn't find any match, return a TLB Refill Exception
552 DtbRefillFault
*Flt
=new DtbRefillFault();
553 /* EntryHi VPN, ASID fields must be set */
554 Flt
->EntryHi_Asid
= Asid
;
555 Flt
->EntryHi_VPN2
= (VPN
>>2);
556 Flt
->EntryHi_VPN2X
= (VPN
& 0x3);
559 /* BadVAddr must be set */
560 Flt
->BadVAddr
= req
->getVaddr();
562 /* Context must be set */
563 Flt
->Context_BadVPN2
= (VPN
>> 2);
567 return checkCacheability(req
);
571 ///////////////////////////////////////////////////////////////////////
575 ITB::ITB(const Params
*p
)
583 // /* hits - causes failure for some reason
584 // .name(name() + ".hits")
585 // .desc("ITB hits");
587 // .name(name() + ".misses")
588 // .desc("ITB misses");
590 // .name(name() + ".acv")
593 // .name(name() + ".accesses")
594 // .desc("ITB accesses");
596 // accesses = hits + misses + invalids; */
601 ///////////////////////////////////////////////////////////////////////
605 DTB::DTB(const Params
*p
)
609 ///////////////////////////////////////////////////////////////////////
613 UTB::UTB(const Params
*p
)
620 TLB::index(bool advance
)
622 MipsISA::PTE
*pte
= &table
[nlu
];
631 MipsITBParams::create()
633 return new MipsISA::ITB(this);
637 MipsDTBParams::create()
639 return new MipsISA::DTB(this);
643 MipsUTBParams::create()
645 return new MipsISA::UTB(this);