2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
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.
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.
29 * Authors: Nathan Binkert
39 #include "arch/mips/faults.hh"
40 #include "arch/mips/pagetable.hh"
41 #include "arch/mips/pra_constants.hh"
42 #include "arch/mips/tlb.hh"
43 #include "arch/mips/utility.hh"
44 #include "base/inifile.hh"
45 #include "base/str.hh"
46 #include "base/trace.hh"
47 #include "cpu/thread_context.hh"
48 #include "debug/MipsPRA.hh"
49 #include "debug/TLB.hh"
50 #include "mem/page_table.hh"
51 #include "params/MipsTLB.hh"
52 #include "sim/process.hh"
55 using namespace MipsISA
;
57 ///////////////////////////////////////////////////////////////////////
62 static inline mode_type
63 getOperatingMode(MiscReg Stat
)
65 if ((Stat
& 0x10000006) != 0 || (Stat
& 0x18) ==0) {
67 } else if ((Stat
& 0x18) == 0x8) {
68 return mode_supervisor
;
69 } else if ((Stat
& 0x18) == 0x10) {
77 TLB::TLB(const Params
*p
)
78 : BaseTLB(p
), size(p
->size
), nlu(0)
80 table
= new PTE
[size
];
81 memset(table
, 0, sizeof(PTE
[size
]));
91 // look up an entry in the TLB
93 TLB::lookup(Addr vpn
, uint8_t asn
) const
95 // assume not found...
97 PageTable::const_iterator i
= lookupTable
.find(vpn
);
98 if (i
!= lookupTable
.end()) {
99 while (i
->first
== vpn
) {
100 int index
= i
->second
;
101 PTE
*pte
= &table
[index
];
103 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
104 Addr Mask
= pte
->Mask
;
105 Addr InvMask
= ~Mask
;
107 if (((vpn
& InvMask
) == (VPN
& InvMask
)) &&
108 (pte
->G
|| (asn
== pte
->asid
))) {
109 // We have a VPN + ASID Match
117 DPRINTF(TLB
, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn
, (int)asn
,
118 retval
? "hit" : "miss", retval
? retval
->PFN1
: 0);
123 TLB::getEntry(unsigned Index
) const
125 // Make sure that Index is valid
127 return &table
[Index
];
131 TLB::probeEntry(Addr vpn
, uint8_t asn
) const
133 // assume not found...
135 PageTable::const_iterator i
= lookupTable
.find(vpn
);
136 if (i
!= lookupTable
.end()) {
137 while (i
->first
== vpn
) {
138 int index
= i
->second
;
139 PTE
*pte
= &table
[index
];
141 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
142 Addr Mask
= pte
->Mask
;
143 Addr InvMask
= ~Mask
;
145 if (((vpn
& InvMask
) == (VPN
& InvMask
)) &&
146 (pte
->G
|| (asn
== pte
->asid
))) {
147 // We have a VPN + ASID Match
154 DPRINTF(MipsPRA
,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn
,asn
,Ind
);
159 TLB::checkCacheability(RequestPtr
&req
)
161 Addr VAddrUncacheable
= 0xA0000000;
162 // In MIPS, cacheability is controlled by certain bits of the virtual
163 // address or by the TLB entry
164 if ((req
->getVaddr() & VAddrUncacheable
) == VAddrUncacheable
) {
165 // mark request as uncacheable
166 req
->setFlags(Request::UNCACHEABLE
);
172 TLB::insertAt(PTE
&pte
, unsigned Index
, int _smallPages
)
174 smallPages
= _smallPages
;
176 warn("Attempted to write at index (%d) beyond TLB size (%d)",
180 DPRINTF(TLB
, "TLB[%d]: %x %x %x %x\n",
181 Index
, pte
.Mask
<< 11,
182 ((pte
.VPN
<< 11) | pte
.asid
),
183 ((pte
.PFN0
<< 6) | (pte
.C0
<< 3) |
184 (pte
.D0
<< 2) | (pte
.V0
<<1) | pte
.G
),
185 ((pte
.PFN1
<<6) | (pte
.C1
<< 3) |
186 (pte
.D1
<< 2) | (pte
.V1
<<1) | pte
.G
));
187 if (table
[Index
].V0
== true || table
[Index
].V1
== true) {
188 // Previous entry is valid
189 PageTable::iterator i
= lookupTable
.find(table
[Index
].VPN
);
190 lookupTable
.erase(i
);
193 // Update fast lookup table
194 lookupTable
.insert(make_pair(table
[Index
].VPN
, Index
));
198 // insert a new TLB entry
200 TLB::insert(Addr addr
, PTE
&pte
)
202 fatal("TLB Insert not yet implemented\n");
208 DPRINTF(TLB
, "flushAll\n");
209 memset(table
, 0, sizeof(PTE
[size
]));
215 TLB::serialize(ostream
&os
)
217 SERIALIZE_SCALAR(size
);
218 SERIALIZE_SCALAR(nlu
);
220 for (int i
= 0; i
< size
; i
++) {
221 nameOut(os
, csprintf("%s.PTE%d", name(), i
));
222 table
[i
].serialize(os
);
227 TLB::unserialize(Checkpoint
*cp
, const string
§ion
)
229 UNSERIALIZE_SCALAR(size
);
230 UNSERIALIZE_SCALAR(nlu
);
232 for (int i
= 0; i
< size
; i
++) {
233 table
[i
].unserialize(cp
, csprintf("%s.PTE%d", section
, i
));
234 if (table
[i
].V0
|| table
[i
].V1
) {
235 lookupTable
.insert(make_pair(table
[i
].VPN
, i
));
244 .name(name() + ".read_hits")
245 .desc("DTB read hits")
249 .name(name() + ".read_misses")
250 .desc("DTB read misses")
255 .name(name() + ".read_accesses")
256 .desc("DTB read accesses")
260 .name(name() + ".write_hits")
261 .desc("DTB write hits")
265 .name(name() + ".write_misses")
266 .desc("DTB write misses")
271 .name(name() + ".write_accesses")
272 .desc("DTB write accesses")
276 .name(name() + ".hits")
281 .name(name() + ".misses")
286 .name(name() + ".accesses")
287 .desc("DTB accesses")
290 hits
= read_hits
+ write_hits
;
291 misses
= read_misses
+ write_misses
;
292 accesses
= read_accesses
+ write_accesses
;
296 TLB::translateInst(RequestPtr req
, ThreadContext
*tc
)
299 panic("translateInst not implemented in MIPS.\n");
301 Process
* p
= tc
->getProcessPtr();
303 Fault fault
= p
->pTable
->translate(req
);
304 if (fault
!= NoFault
)
311 TLB::translateData(RequestPtr req
, ThreadContext
*tc
, bool write
)
314 panic("translateData not implemented in MIPS.\n");
316 Process
* p
= tc
->getProcessPtr();
318 Fault fault
= p
->pTable
->translate(req
);
319 if (fault
!= NoFault
)
326 TLB::translateAtomic(RequestPtr req
, ThreadContext
*tc
, Mode mode
)
329 return translateInst(req
, tc
);
331 return translateData(req
, tc
, mode
== Write
);
335 TLB::translateTiming(RequestPtr req
, ThreadContext
*tc
,
336 Translation
*translation
, Mode mode
)
339 translation
->finish(translateAtomic(req
, tc
, mode
), req
, tc
, mode
);
344 TLB::index(bool advance
)
346 PTE
*pte
= &table
[nlu
];
355 MipsTLBParams::create()
357 return new TLB(this);