tlb.cc (5891:73084c6bb183) tlb.cc (5894:8091ac99341a)
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Nathan Binkert
30 * Steve Reinhardt
31 * Jaidev Patwardhan
32 */
33
34#include <string>
35#include <vector>
36
37#include "arch/mips/pra_constants.hh"
38#include "arch/mips/pagetable.hh"
39#include "arch/mips/tlb.hh"
40#include "arch/mips/faults.hh"
41#include "arch/mips/utility.hh"
42#include "base/inifile.hh"
43#include "base/str.hh"
44#include "base/trace.hh"
45#include "cpu/thread_context.hh"
46#include "sim/process.hh"
47#include "mem/page_table.hh"
48#include "params/MipsDTB.hh"
49#include "params/MipsITB.hh"
50#include "params/MipsTLB.hh"
51#include "params/MipsUTB.hh"
52
53
54using namespace std;
55using namespace MipsISA;
56
57///////////////////////////////////////////////////////////////////////
58//
59// MIPS TLB
60//
61
62#define MODE2MASK(X) (1 << (X))
63
64TLB::TLB(const Params *p)
65 : BaseTLB(p), size(p->size), nlu(0)
66{
67 table = new MipsISA::PTE[size];
68 memset(table, 0, sizeof(MipsISA::PTE[size]));
69 smallPages=0;
70}
71
72TLB::~TLB()
73{
74 if (table)
75 delete [] table;
76}
77
78// look up an entry in the TLB
79MipsISA::PTE *
80TLB::lookup(Addr vpn, uint8_t asn) const
81{
82 // assume not found...
83 MipsISA::PTE *retval = NULL;
84 PageTable::const_iterator i = lookupTable.find(vpn);
85 if (i != lookupTable.end()) {
86 while (i->first == vpn) {
87 int index = i->second;
88 MipsISA::PTE *pte = &table[index];
89
90 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
91 Addr Mask = pte->Mask;
92 Addr InvMask = ~Mask;
93 Addr VPN = pte->VPN;
94 // warn("Valid: %d - %d\n",pte->V0,pte->V1);
95 if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
96 { // We have a VPN + ASID Match
97 retval = pte;
98 break;
99 }
100 ++i;
101 }
102 }
103
104 DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
105 retval ? "hit" : "miss", retval ? retval->PFN1 : 0);
106 return retval;
107}
108
109MipsISA::PTE* TLB::getEntry(unsigned Index) const
110{
111 // Make sure that Index is valid
112 assert(Index<size);
113 return &table[Index];
114}
115
116int TLB::probeEntry(Addr vpn,uint8_t asn) const
117{
118 // assume not found...
119 MipsISA::PTE *retval = NULL;
120 int Ind=-1;
121 PageTable::const_iterator i = lookupTable.find(vpn);
122 if (i != lookupTable.end()) {
123 while (i->first == vpn) {
124 int index = i->second;
125 MipsISA::PTE *pte = &table[index];
126
127 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
128 Addr Mask = pte->Mask;
129 Addr InvMask = ~Mask;
130 Addr VPN = pte->VPN;
131 if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
132 { // We have a VPN + ASID Match
133 retval = pte;
134 Ind = index;
135 break;
136 }
137
138 ++i;
139 }
140 }
141 DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
142 return Ind;
143}
144Fault inline
145TLB::checkCacheability(RequestPtr &req)
146{
147 Addr VAddrUncacheable = 0xA0000000;
148 // In MIPS, cacheability is controlled by certain bits of the virtual address
149 // or by the TLB entry
150 if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
151 // mark request as uncacheable
152 req->setFlags(Request::UNCACHEABLE);
153 }
154 return NoFault;
155}
156void TLB::insertAt(MipsISA::PTE &pte, unsigned Index, int _smallPages)
157{
158 smallPages=_smallPages;
159 if(Index > size){
160 warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size);
161 } else {
162 // Update TLB
163 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),
164 ((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
165 if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid
166 PageTable::iterator i = lookupTable.find(table[Index].VPN);
167 lookupTable.erase(i);
168 }
169 table[Index]=pte;
170 // Update fast lookup table
171 lookupTable.insert(make_pair(table[Index].VPN, Index));
172 // int TestIndex=probeEntry(pte.VPN,pte.asid);
173 // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask);
174 }
175
176}
177
178// insert a new TLB entry
179void
180TLB::insert(Addr addr, MipsISA::PTE &pte)
181{
182 fatal("TLB Insert not yet implemented\n");
183
184
185 /* MipsISA::VAddr vaddr = addr;
186 if (table[nlu].valid) {
187 Addr oldvpn = table[nlu].tag;
188 PageTable::iterator i = lookupTable.find(oldvpn);
189
190 if (i == lookupTable.end())
191 panic("TLB entry not found in lookupTable");
192
193 int index;
194 while ((index = i->second) != nlu) {
195 if (table[index].tag != oldvpn)
196 panic("TLB entry not found in lookupTable");
197
198 ++i;
199 }
200
201 DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
202
203 lookupTable.erase(i);
204 }
205
206 DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
207
208 table[nlu] = pte;
209 table[nlu].tag = vaddr.vpn();
210 table[nlu].valid = true;
211
212 lookupTable.insert(make_pair(vaddr.vpn(), nlu));
213 nextnlu();
214 */
215}
216
217void
218TLB::flushAll()
219{
220 DPRINTF(TLB, "flushAll\n");
221 memset(table, 0, sizeof(MipsISA::PTE[size]));
222 lookupTable.clear();
223 nlu = 0;
224}
225
226void
227TLB::serialize(ostream &os)
228{
229 SERIALIZE_SCALAR(size);
230 SERIALIZE_SCALAR(nlu);
231
232 for (int i = 0; i < size; i++) {
233 nameOut(os, csprintf("%s.PTE%d", name(), i));
234 table[i].serialize(os);
235 }
236}
237
238void
239TLB::unserialize(Checkpoint *cp, const string &section)
240{
241 UNSERIALIZE_SCALAR(size);
242 UNSERIALIZE_SCALAR(nlu);
243
244 for (int i = 0; i < size; i++) {
245 table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
246 if (table[i].V0 || table[i].V1) {
247 lookupTable.insert(make_pair(table[i].VPN, i));
248 }
249 }
250}
251
252void
253TLB::regStats()
254{
255 read_hits
256 .name(name() + ".read_hits")
257 .desc("DTB read hits")
258 ;
259
260 read_misses
261 .name(name() + ".read_misses")
262 .desc("DTB read misses")
263 ;
264
265
266 read_accesses
267 .name(name() + ".read_accesses")
268 .desc("DTB read accesses")
269 ;
270
271 write_hits
272 .name(name() + ".write_hits")
273 .desc("DTB write hits")
274 ;
275
276 write_misses
277 .name(name() + ".write_misses")
278 .desc("DTB write misses")
279 ;
280
281
282 write_accesses
283 .name(name() + ".write_accesses")
284 .desc("DTB write accesses")
285 ;
286
287 hits
288 .name(name() + ".hits")
289 .desc("DTB hits")
290 ;
291
292 misses
293 .name(name() + ".misses")
294 .desc("DTB misses")
295 ;
296
297 invalids
298 .name(name() + ".invalids")
299 .desc("DTB access violations")
300 ;
301
302 accesses
303 .name(name() + ".accesses")
304 .desc("DTB accesses")
305 ;
306
307 hits = read_hits + write_hits;
308 misses = read_misses + write_misses;
309 accesses = read_accesses + write_accesses;
310}
311
312Fault
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Nathan Binkert
30 * Steve Reinhardt
31 * Jaidev Patwardhan
32 */
33
34#include <string>
35#include <vector>
36
37#include "arch/mips/pra_constants.hh"
38#include "arch/mips/pagetable.hh"
39#include "arch/mips/tlb.hh"
40#include "arch/mips/faults.hh"
41#include "arch/mips/utility.hh"
42#include "base/inifile.hh"
43#include "base/str.hh"
44#include "base/trace.hh"
45#include "cpu/thread_context.hh"
46#include "sim/process.hh"
47#include "mem/page_table.hh"
48#include "params/MipsDTB.hh"
49#include "params/MipsITB.hh"
50#include "params/MipsTLB.hh"
51#include "params/MipsUTB.hh"
52
53
54using namespace std;
55using namespace MipsISA;
56
57///////////////////////////////////////////////////////////////////////
58//
59// MIPS TLB
60//
61
62#define MODE2MASK(X) (1 << (X))
63
64TLB::TLB(const Params *p)
65 : BaseTLB(p), size(p->size), nlu(0)
66{
67 table = new MipsISA::PTE[size];
68 memset(table, 0, sizeof(MipsISA::PTE[size]));
69 smallPages=0;
70}
71
72TLB::~TLB()
73{
74 if (table)
75 delete [] table;
76}
77
78// look up an entry in the TLB
79MipsISA::PTE *
80TLB::lookup(Addr vpn, uint8_t asn) const
81{
82 // assume not found...
83 MipsISA::PTE *retval = NULL;
84 PageTable::const_iterator i = lookupTable.find(vpn);
85 if (i != lookupTable.end()) {
86 while (i->first == vpn) {
87 int index = i->second;
88 MipsISA::PTE *pte = &table[index];
89
90 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
91 Addr Mask = pte->Mask;
92 Addr InvMask = ~Mask;
93 Addr VPN = pte->VPN;
94 // warn("Valid: %d - %d\n",pte->V0,pte->V1);
95 if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
96 { // We have a VPN + ASID Match
97 retval = pte;
98 break;
99 }
100 ++i;
101 }
102 }
103
104 DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
105 retval ? "hit" : "miss", retval ? retval->PFN1 : 0);
106 return retval;
107}
108
109MipsISA::PTE* TLB::getEntry(unsigned Index) const
110{
111 // Make sure that Index is valid
112 assert(Index<size);
113 return &table[Index];
114}
115
116int TLB::probeEntry(Addr vpn,uint8_t asn) const
117{
118 // assume not found...
119 MipsISA::PTE *retval = NULL;
120 int Ind=-1;
121 PageTable::const_iterator i = lookupTable.find(vpn);
122 if (i != lookupTable.end()) {
123 while (i->first == vpn) {
124 int index = i->second;
125 MipsISA::PTE *pte = &table[index];
126
127 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
128 Addr Mask = pte->Mask;
129 Addr InvMask = ~Mask;
130 Addr VPN = pte->VPN;
131 if(((vpn & InvMask) == (VPN & InvMask)) && (pte->G || (asn == pte->asid)))
132 { // We have a VPN + ASID Match
133 retval = pte;
134 Ind = index;
135 break;
136 }
137
138 ++i;
139 }
140 }
141 DPRINTF(MipsPRA,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
142 return Ind;
143}
144Fault inline
145TLB::checkCacheability(RequestPtr &req)
146{
147 Addr VAddrUncacheable = 0xA0000000;
148 // In MIPS, cacheability is controlled by certain bits of the virtual address
149 // or by the TLB entry
150 if((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
151 // mark request as uncacheable
152 req->setFlags(Request::UNCACHEABLE);
153 }
154 return NoFault;
155}
156void TLB::insertAt(MipsISA::PTE &pte, unsigned Index, int _smallPages)
157{
158 smallPages=_smallPages;
159 if(Index > size){
160 warn("Attempted to write at index (%d) beyond TLB size (%d)",Index,size);
161 } else {
162 // Update TLB
163 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),
164 ((pte.PFN1 <<6) | (pte.C1 << 3) | (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
165 if(table[Index].V0 == true || table[Index].V1 == true){ // Previous entry is valid
166 PageTable::iterator i = lookupTable.find(table[Index].VPN);
167 lookupTable.erase(i);
168 }
169 table[Index]=pte;
170 // Update fast lookup table
171 lookupTable.insert(make_pair(table[Index].VPN, Index));
172 // int TestIndex=probeEntry(pte.VPN,pte.asid);
173 // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask);
174 }
175
176}
177
178// insert a new TLB entry
179void
180TLB::insert(Addr addr, MipsISA::PTE &pte)
181{
182 fatal("TLB Insert not yet implemented\n");
183
184
185 /* MipsISA::VAddr vaddr = addr;
186 if (table[nlu].valid) {
187 Addr oldvpn = table[nlu].tag;
188 PageTable::iterator i = lookupTable.find(oldvpn);
189
190 if (i == lookupTable.end())
191 panic("TLB entry not found in lookupTable");
192
193 int index;
194 while ((index = i->second) != nlu) {
195 if (table[index].tag != oldvpn)
196 panic("TLB entry not found in lookupTable");
197
198 ++i;
199 }
200
201 DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
202
203 lookupTable.erase(i);
204 }
205
206 DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
207
208 table[nlu] = pte;
209 table[nlu].tag = vaddr.vpn();
210 table[nlu].valid = true;
211
212 lookupTable.insert(make_pair(vaddr.vpn(), nlu));
213 nextnlu();
214 */
215}
216
217void
218TLB::flushAll()
219{
220 DPRINTF(TLB, "flushAll\n");
221 memset(table, 0, sizeof(MipsISA::PTE[size]));
222 lookupTable.clear();
223 nlu = 0;
224}
225
226void
227TLB::serialize(ostream &os)
228{
229 SERIALIZE_SCALAR(size);
230 SERIALIZE_SCALAR(nlu);
231
232 for (int i = 0; i < size; i++) {
233 nameOut(os, csprintf("%s.PTE%d", name(), i));
234 table[i].serialize(os);
235 }
236}
237
238void
239TLB::unserialize(Checkpoint *cp, const string &section)
240{
241 UNSERIALIZE_SCALAR(size);
242 UNSERIALIZE_SCALAR(nlu);
243
244 for (int i = 0; i < size; i++) {
245 table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
246 if (table[i].V0 || table[i].V1) {
247 lookupTable.insert(make_pair(table[i].VPN, i));
248 }
249 }
250}
251
252void
253TLB::regStats()
254{
255 read_hits
256 .name(name() + ".read_hits")
257 .desc("DTB read hits")
258 ;
259
260 read_misses
261 .name(name() + ".read_misses")
262 .desc("DTB read misses")
263 ;
264
265
266 read_accesses
267 .name(name() + ".read_accesses")
268 .desc("DTB read accesses")
269 ;
270
271 write_hits
272 .name(name() + ".write_hits")
273 .desc("DTB write hits")
274 ;
275
276 write_misses
277 .name(name() + ".write_misses")
278 .desc("DTB write misses")
279 ;
280
281
282 write_accesses
283 .name(name() + ".write_accesses")
284 .desc("DTB write accesses")
285 ;
286
287 hits
288 .name(name() + ".hits")
289 .desc("DTB hits")
290 ;
291
292 misses
293 .name(name() + ".misses")
294 .desc("DTB misses")
295 ;
296
297 invalids
298 .name(name() + ".invalids")
299 .desc("DTB access violations")
300 ;
301
302 accesses
303 .name(name() + ".accesses")
304 .desc("DTB accesses")
305 ;
306
307 hits = read_hits + write_hits;
308 misses = read_misses + write_misses;
309 accesses = read_accesses + write_accesses;
310}
311
312Fault
313ITB::translateAtomic(RequestPtr &req, ThreadContext *tc)
313ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
314{
315#if !FULL_SYSTEM
316 Process * p = tc->getProcessPtr();
317
318 Fault fault = p->pTable->translate(req);
319 if(fault != NoFault)
320 return fault;
321
322 return NoFault;
323#else
324 if(MipsISA::IsKSeg0(req->getVaddr()))
325 {
326 // Address will not be translated through TLB, set response, and go!
327 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
328 if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
329 {
330 AddressErrorFault *Flt = new AddressErrorFault();
331 /* BadVAddr must be set */
332 Flt->BadVAddr = req->getVaddr();
333 return Flt;
334 }
335 }
336 else if(MipsISA::IsKSeg1(req->getVaddr()))
337 {
338 // Address will not be translated through TLB, set response, and go!
339 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
340 }
341 else
342 {
343 /* This is an optimization - smallPages is updated every time a TLB operation is performed
344 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
345 do a TLB lookup */
346 Addr VPN;
347 if(smallPages==1){
348 VPN=((req->getVaddr() >> 11));
349 } else {
350 VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
351 }
352 uint8_t Asid = req->getAsid();
353 if(req->isMisaligned()){ // Unaligned address!
354 AddressErrorFault *Flt = new AddressErrorFault();
355 /* BadVAddr must be set */
356 Flt->BadVAddr = req->getVaddr();
357 return Flt;
358 }
359 MipsISA::PTE *pte = lookup(VPN,Asid);
360 if(pte != NULL)
361 {// Ok, found something
362 /* Check for valid bits */
363 int EvenOdd;
364 bool Valid;
365 if((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) ==0){
366 // Check even bits
367 Valid = pte->V0;
368 EvenOdd = 0;
369 } else {
370 // Check odd bits
371 Valid = pte->V1;
372 EvenOdd = 1;
373 }
374
375 if(Valid == false)
376 {//Invalid entry
377 ItbInvalidFault *Flt = new ItbInvalidFault();
378 /* EntryHi VPN, ASID fields must be set */
379 Flt->EntryHi_Asid = Asid;
380 Flt->EntryHi_VPN2 = (VPN>>2);
381 Flt->EntryHi_VPN2X = (VPN & 0x3);
382
383 /* BadVAddr must be set */
384 Flt->BadVAddr = req->getVaddr();
385
386 /* Context must be set */
387 Flt->Context_BadVPN2 = (VPN >> 2);
388 return Flt;
389 }
390 else
391 {// Ok, this is really a match, set paddr
392 // hits++;
393 Addr PAddr;
394 if(EvenOdd == 0){
395 PAddr = pte->PFN0;
396 }else{
397 PAddr = pte->PFN1;
398 }
399 PAddr >>= (pte->AddrShiftAmount-12);
400 PAddr <<= pte->AddrShiftAmount;
401 PAddr |= ((req->getVaddr()) & pte->OffsetMask);
402 req->setPaddr(PAddr);
403
404
405 }
406 }
407 else
408 { // Didn't find any match, return a TLB Refill Exception
409 // misses++;
410 ItbRefillFault *Flt=new ItbRefillFault();
411 /* EntryHi VPN, ASID fields must be set */
412 Flt->EntryHi_Asid = Asid;
413 Flt->EntryHi_VPN2 = (VPN>>2);
414 Flt->EntryHi_VPN2X = (VPN & 0x3);
415
416
417 /* BadVAddr must be set */
418 Flt->BadVAddr = req->getVaddr();
419
420 /* Context must be set */
421 Flt->Context_BadVPN2 = (VPN >> 2);
422 return Flt;
423 }
424 }
425 return checkCacheability(req);
426#endif
427}
428
314{
315#if !FULL_SYSTEM
316 Process * p = tc->getProcessPtr();
317
318 Fault fault = p->pTable->translate(req);
319 if(fault != NoFault)
320 return fault;
321
322 return NoFault;
323#else
324 if(MipsISA::IsKSeg0(req->getVaddr()))
325 {
326 // Address will not be translated through TLB, set response, and go!
327 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
328 if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
329 {
330 AddressErrorFault *Flt = new AddressErrorFault();
331 /* BadVAddr must be set */
332 Flt->BadVAddr = req->getVaddr();
333 return Flt;
334 }
335 }
336 else if(MipsISA::IsKSeg1(req->getVaddr()))
337 {
338 // Address will not be translated through TLB, set response, and go!
339 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
340 }
341 else
342 {
343 /* This is an optimization - smallPages is updated every time a TLB operation is performed
344 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
345 do a TLB lookup */
346 Addr VPN;
347 if(smallPages==1){
348 VPN=((req->getVaddr() >> 11));
349 } else {
350 VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
351 }
352 uint8_t Asid = req->getAsid();
353 if(req->isMisaligned()){ // Unaligned address!
354 AddressErrorFault *Flt = new AddressErrorFault();
355 /* BadVAddr must be set */
356 Flt->BadVAddr = req->getVaddr();
357 return Flt;
358 }
359 MipsISA::PTE *pte = lookup(VPN,Asid);
360 if(pte != NULL)
361 {// Ok, found something
362 /* Check for valid bits */
363 int EvenOdd;
364 bool Valid;
365 if((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) ==0){
366 // Check even bits
367 Valid = pte->V0;
368 EvenOdd = 0;
369 } else {
370 // Check odd bits
371 Valid = pte->V1;
372 EvenOdd = 1;
373 }
374
375 if(Valid == false)
376 {//Invalid entry
377 ItbInvalidFault *Flt = new ItbInvalidFault();
378 /* EntryHi VPN, ASID fields must be set */
379 Flt->EntryHi_Asid = Asid;
380 Flt->EntryHi_VPN2 = (VPN>>2);
381 Flt->EntryHi_VPN2X = (VPN & 0x3);
382
383 /* BadVAddr must be set */
384 Flt->BadVAddr = req->getVaddr();
385
386 /* Context must be set */
387 Flt->Context_BadVPN2 = (VPN >> 2);
388 return Flt;
389 }
390 else
391 {// Ok, this is really a match, set paddr
392 // hits++;
393 Addr PAddr;
394 if(EvenOdd == 0){
395 PAddr = pte->PFN0;
396 }else{
397 PAddr = pte->PFN1;
398 }
399 PAddr >>= (pte->AddrShiftAmount-12);
400 PAddr <<= pte->AddrShiftAmount;
401 PAddr |= ((req->getVaddr()) & pte->OffsetMask);
402 req->setPaddr(PAddr);
403
404
405 }
406 }
407 else
408 { // Didn't find any match, return a TLB Refill Exception
409 // misses++;
410 ItbRefillFault *Flt=new ItbRefillFault();
411 /* EntryHi VPN, ASID fields must be set */
412 Flt->EntryHi_Asid = Asid;
413 Flt->EntryHi_VPN2 = (VPN>>2);
414 Flt->EntryHi_VPN2X = (VPN & 0x3);
415
416
417 /* BadVAddr must be set */
418 Flt->BadVAddr = req->getVaddr();
419
420 /* Context must be set */
421 Flt->Context_BadVPN2 = (VPN >> 2);
422 return Flt;
423 }
424 }
425 return checkCacheability(req);
426#endif
427}
428
429void
430ITB::translateTiming(RequestPtr req, ThreadContext *tc,
431 Translation *translation)
432{
433 assert(translation);
434 translation->finish(translateAtomic(req, tc), req, tc, false);
435}
436
429Fault
437Fault
430DTB::translateAtomic(RequestPtr &req, ThreadContext *tc, bool write)
438DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
431{
432#if !FULL_SYSTEM
433 Process * p = tc->getProcessPtr();
434
435 Fault fault = p->pTable->translate(req);
436 if(fault != NoFault)
437 return fault;
438
439 return NoFault;
440#else
441 if(MipsISA::IsKSeg0(req->getVaddr()))
442 {
443 // Address will not be translated through TLB, set response, and go!
444 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
445 if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
446 {
447 StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
448 /* BadVAddr must be set */
449 Flt->BadVAddr = req->getVaddr();
450
451 return Flt;
452 }
453 }
454 else if(MipsISA::IsKSeg1(req->getVaddr()))
455 {
456 // Address will not be translated through TLB, set response, and go!
457 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
458 }
459 else
460 {
461 /* This is an optimization - smallPages is updated every time a TLB operation is performed
462 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
463 do a TLB lookup */
464 Addr VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
465 if(smallPages==1){
466 VPN=((req->getVaddr() >> 11));
467 }
468 uint8_t Asid = req->getAsid();
469 MipsISA::PTE *pte = lookup(VPN,Asid);
470 if(req->isMisaligned()){ // Unaligned address!
471 StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
472 /* BadVAddr must be set */
473 Flt->BadVAddr = req->getVaddr();
474 return Flt;
475 }
476 if(pte != NULL)
477 {// Ok, found something
478 /* Check for valid bits */
479 int EvenOdd;
480 bool Valid;
481 bool Dirty;
482 if(((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) ==0){
483 // Check even bits
484 Valid = pte->V0;
485 Dirty = pte->D0;
486 EvenOdd = 0;
487
488 } else {
489 // Check odd bits
490 Valid = pte->V1;
491 Dirty = pte->D1;
492 EvenOdd = 1;
493 }
494
495 if(Valid == false)
496 {//Invalid entry
497 // invalids++;
498 DtbInvalidFault *Flt = new DtbInvalidFault();
499 /* EntryHi VPN, ASID fields must be set */
500 Flt->EntryHi_Asid = Asid;
501 Flt->EntryHi_VPN2 = (VPN>>2);
502 Flt->EntryHi_VPN2X = (VPN & 0x3);
503
504
505 /* BadVAddr must be set */
506 Flt->BadVAddr = req->getVaddr();
507
508 /* Context must be set */
509 Flt->Context_BadVPN2 = (VPN >> 2);
510
511 return Flt;
512 }
513 else
514 {// Ok, this is really a match, set paddr
515 // hits++;
516 if(!Dirty)
517 {
518 TLBModifiedFault *Flt = new TLBModifiedFault();
519 /* EntryHi VPN, ASID fields must be set */
520 Flt->EntryHi_Asid = Asid;
521 Flt->EntryHi_VPN2 = (VPN>>2);
522 Flt->EntryHi_VPN2X = (VPN & 0x3);
523
524
525 /* BadVAddr must be set */
526 Flt->BadVAddr = req->getVaddr();
527
528 /* Context must be set */
529 Flt->Context_BadVPN2 = (VPN >> 2);
530 return Flt;
531
532 }
533 Addr PAddr;
534 if(EvenOdd == 0){
535 PAddr = pte->PFN0;
536 }else{
537 PAddr = pte->PFN1;
538 }
539 PAddr >>= (pte->AddrShiftAmount-12);
540 PAddr <<= pte->AddrShiftAmount;
541 PAddr |= ((req->getVaddr()) & pte->OffsetMask);
542 req->setPaddr(PAddr);
543 }
544 }
545 else
546 { // Didn't find any match, return a TLB Refill Exception
547 // misses++;
548 DtbRefillFault *Flt=new DtbRefillFault();
549 /* EntryHi VPN, ASID fields must be set */
550 Flt->EntryHi_Asid = Asid;
551 Flt->EntryHi_VPN2 = (VPN>>2);
552 Flt->EntryHi_VPN2X = (VPN & 0x3);
553
554
555 /* BadVAddr must be set */
556 Flt->BadVAddr = req->getVaddr();
557
558 /* Context must be set */
559 Flt->Context_BadVPN2 = (VPN >> 2);
560 return Flt;
561 }
562 }
563 return checkCacheability(req);
564#endif
565}
566
439{
440#if !FULL_SYSTEM
441 Process * p = tc->getProcessPtr();
442
443 Fault fault = p->pTable->translate(req);
444 if(fault != NoFault)
445 return fault;
446
447 return NoFault;
448#else
449 if(MipsISA::IsKSeg0(req->getVaddr()))
450 {
451 // Address will not be translated through TLB, set response, and go!
452 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
453 if(MipsISA::getOperatingMode(tc->readMiscReg(MipsISA::Status)) != mode_kernel || req->isMisaligned())
454 {
455 StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
456 /* BadVAddr must be set */
457 Flt->BadVAddr = req->getVaddr();
458
459 return Flt;
460 }
461 }
462 else if(MipsISA::IsKSeg1(req->getVaddr()))
463 {
464 // Address will not be translated through TLB, set response, and go!
465 req->setPaddr(MipsISA::KSeg02Phys(req->getVaddr()));
466 }
467 else
468 {
469 /* This is an optimization - smallPages is updated every time a TLB operation is performed
470 That way, we don't need to look at Config3 _ SP and PageGrain _ ESP every time we
471 do a TLB lookup */
472 Addr VPN=((req->getVaddr() >> 11) & 0xFFFFFFFC);
473 if(smallPages==1){
474 VPN=((req->getVaddr() >> 11));
475 }
476 uint8_t Asid = req->getAsid();
477 MipsISA::PTE *pte = lookup(VPN,Asid);
478 if(req->isMisaligned()){ // Unaligned address!
479 StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
480 /* BadVAddr must be set */
481 Flt->BadVAddr = req->getVaddr();
482 return Flt;
483 }
484 if(pte != NULL)
485 {// Ok, found something
486 /* Check for valid bits */
487 int EvenOdd;
488 bool Valid;
489 bool Dirty;
490 if(((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) ==0){
491 // Check even bits
492 Valid = pte->V0;
493 Dirty = pte->D0;
494 EvenOdd = 0;
495
496 } else {
497 // Check odd bits
498 Valid = pte->V1;
499 Dirty = pte->D1;
500 EvenOdd = 1;
501 }
502
503 if(Valid == false)
504 {//Invalid entry
505 // invalids++;
506 DtbInvalidFault *Flt = new DtbInvalidFault();
507 /* EntryHi VPN, ASID fields must be set */
508 Flt->EntryHi_Asid = Asid;
509 Flt->EntryHi_VPN2 = (VPN>>2);
510 Flt->EntryHi_VPN2X = (VPN & 0x3);
511
512
513 /* BadVAddr must be set */
514 Flt->BadVAddr = req->getVaddr();
515
516 /* Context must be set */
517 Flt->Context_BadVPN2 = (VPN >> 2);
518
519 return Flt;
520 }
521 else
522 {// Ok, this is really a match, set paddr
523 // hits++;
524 if(!Dirty)
525 {
526 TLBModifiedFault *Flt = new TLBModifiedFault();
527 /* EntryHi VPN, ASID fields must be set */
528 Flt->EntryHi_Asid = Asid;
529 Flt->EntryHi_VPN2 = (VPN>>2);
530 Flt->EntryHi_VPN2X = (VPN & 0x3);
531
532
533 /* BadVAddr must be set */
534 Flt->BadVAddr = req->getVaddr();
535
536 /* Context must be set */
537 Flt->Context_BadVPN2 = (VPN >> 2);
538 return Flt;
539
540 }
541 Addr PAddr;
542 if(EvenOdd == 0){
543 PAddr = pte->PFN0;
544 }else{
545 PAddr = pte->PFN1;
546 }
547 PAddr >>= (pte->AddrShiftAmount-12);
548 PAddr <<= pte->AddrShiftAmount;
549 PAddr |= ((req->getVaddr()) & pte->OffsetMask);
550 req->setPaddr(PAddr);
551 }
552 }
553 else
554 { // Didn't find any match, return a TLB Refill Exception
555 // misses++;
556 DtbRefillFault *Flt=new DtbRefillFault();
557 /* EntryHi VPN, ASID fields must be set */
558 Flt->EntryHi_Asid = Asid;
559 Flt->EntryHi_VPN2 = (VPN>>2);
560 Flt->EntryHi_VPN2X = (VPN & 0x3);
561
562
563 /* BadVAddr must be set */
564 Flt->BadVAddr = req->getVaddr();
565
566 /* Context must be set */
567 Flt->Context_BadVPN2 = (VPN >> 2);
568 return Flt;
569 }
570 }
571 return checkCacheability(req);
572#endif
573}
574
575void
576DTB::translateTiming(RequestPtr req, ThreadContext *tc,
577 Translation *translation, bool write)
578{
579 assert(translation);
580 translation->finish(translateAtomic(req, tc, write), req, tc, write);
581}
582
567///////////////////////////////////////////////////////////////////////
568//
569// Mips ITB
570//
571ITB::ITB(const Params *p)
572 : TLB(p)
573{}
574
575
576// void
577// ITB::regStats()
578// {
579// /* hits - causes failure for some reason
580// .name(name() + ".hits")
581// .desc("ITB hits");
582// misses
583// .name(name() + ".misses")
584// .desc("ITB misses");
585// acv
586// .name(name() + ".acv")
587// .desc("ITB acv");
588// accesses
589// .name(name() + ".accesses")
590// .desc("ITB accesses");
591
592// accesses = hits + misses + invalids; */
593// }
594
595
596
597///////////////////////////////////////////////////////////////////////
598//
599// Mips DTB
600//
601DTB::DTB(const Params *p)
602 : TLB(p)
603{}
604
605///////////////////////////////////////////////////////////////////////
606//
607// Mips UTB
608//
609UTB::UTB(const Params *p)
610 : ITB(p), DTB(p)
611{}
612
613
614
615MipsISA::PTE &
616TLB::index(bool advance)
617{
618 MipsISA::PTE *pte = &table[nlu];
619
620 if (advance)
621 nextnlu();
622
623 return *pte;
624}
625
626MipsISA::ITB *
627MipsITBParams::create()
628{
629 return new MipsISA::ITB(this);
630}
631
632MipsISA::DTB *
633MipsDTBParams::create()
634{
635 return new MipsISA::DTB(this);
636}
637
638MipsISA::UTB *
639MipsUTBParams::create()
640{
641 return new MipsISA::UTB(this);
642}
583///////////////////////////////////////////////////////////////////////
584//
585// Mips ITB
586//
587ITB::ITB(const Params *p)
588 : TLB(p)
589{}
590
591
592// void
593// ITB::regStats()
594// {
595// /* hits - causes failure for some reason
596// .name(name() + ".hits")
597// .desc("ITB hits");
598// misses
599// .name(name() + ".misses")
600// .desc("ITB misses");
601// acv
602// .name(name() + ".acv")
603// .desc("ITB acv");
604// accesses
605// .name(name() + ".accesses")
606// .desc("ITB accesses");
607
608// accesses = hits + misses + invalids; */
609// }
610
611
612
613///////////////////////////////////////////////////////////////////////
614//
615// Mips DTB
616//
617DTB::DTB(const Params *p)
618 : TLB(p)
619{}
620
621///////////////////////////////////////////////////////////////////////
622//
623// Mips UTB
624//
625UTB::UTB(const Params *p)
626 : ITB(p), DTB(p)
627{}
628
629
630
631MipsISA::PTE &
632TLB::index(bool advance)
633{
634 MipsISA::PTE *pte = &table[nlu];
635
636 if (advance)
637 nextnlu();
638
639 return *pte;
640}
641
642MipsISA::ITB *
643MipsITBParams::create()
644{
645 return new MipsISA::ITB(this);
646}
647
648MipsISA::DTB *
649MipsDTBParams::create()
650{
651 return new MipsISA::DTB(this);
652}
653
654MipsISA::UTB *
655MipsUTBParams::create()
656{
657 return new MipsISA::UTB(this);
658}