tlb.cc (11723:0596db108c53) tlb.cc (11962:43ce94c4d34c)
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 * Zhengxing Li
33 * Deyuan Guo
34 */
35
36#include "arch/riscv/tlb.hh"
37
38#include <string>
39#include <vector>
40
41#include "arch/riscv/faults.hh"
42#include "arch/riscv/pagetable.hh"
43#include "arch/riscv/pra_constants.hh"
44#include "arch/riscv/utility.hh"
45#include "base/inifile.hh"
46#include "base/str.hh"
47#include "base/trace.hh"
48#include "cpu/thread_context.hh"
49#include "debug/RiscvTLB.hh"
50#include "debug/TLB.hh"
51#include "mem/page_table.hh"
52#include "params/RiscvTLB.hh"
53#include "sim/full_system.hh"
54#include "sim/process.hh"
55
56using namespace std;
57using namespace RiscvISA;
58
59///////////////////////////////////////////////////////////////////////
60//
61// RISC-V TLB
62//
63
64TLB::TLB(const Params *p)
65 : BaseTLB(p), size(p->size), nlu(0)
66{
67 table = new PTE[size];
68 memset(table, 0, sizeof(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
79RiscvISA::PTE *
80TLB::lookup(Addr vpn, uint8_t asn) const
81{
82 // assume not found...
83 PTE *retval = nullptr;
84 PageTable::const_iterator i = lookupTable.find(vpn);
85 if (i != lookupTable.end()) {
86 while (i->first == vpn) {
87 int index = i->second;
88 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 if (((vpn & InvMask) == (VPN & InvMask)) &&
95 (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
109RiscvISA::PTE*
110TLB::getEntry(unsigned Index) const
111{
112 // Make sure that Index is valid
113 assert(Index<size);
114 return &table[Index];
115}
116
117int
118TLB::probeEntry(Addr vpn, uint8_t asn) const
119{
120 // assume not found...
121 int Ind = -1;
122 PageTable::const_iterator i = lookupTable.find(vpn);
123 if (i != lookupTable.end()) {
124 while (i->first == vpn) {
125 int index = i->second;
126 PTE *pte = &table[index];
127
128 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
129 Addr Mask = pte->Mask;
130 Addr InvMask = ~Mask;
131 Addr VPN = pte->VPN;
132 if (((vpn & InvMask) == (VPN & InvMask)) &&
133 (pte->G || (asn == pte->asid))) {
134 // We have a VPN + ASID Match
135 Ind = index;
136 break;
137 }
138 ++i;
139 }
140 }
141 DPRINTF(RiscvTLB,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
142 return Ind;
143}
144
145inline Fault
146TLB::checkCacheability(RequestPtr &req)
147{
148 Addr VAddrUncacheable = 0xA0000000;
149 // In MIPS, cacheability is controlled by certain bits of the virtual
150 // address or by the TLB entry
151 if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
152 // mark request as uncacheable
153 req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
154 }
155 return NoFault;
156}
157
158void
159TLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
160{
161 smallPages = _smallPages;
162 if (Index > size) {
163 warn("Attempted to write at index (%d) beyond TLB size (%d)",
164 Index, size);
165 } else {
166 // Update TLB
167 DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
168 Index, pte.Mask << 11,
169 ((pte.VPN << 11) | pte.asid),
170 ((pte.PFN0 << 6) | (pte.C0 << 3) |
171 (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
172 ((pte.PFN1 <<6) | (pte.C1 << 3) |
173 (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
174 if (table[Index].V0 || table[Index].V1) {
175 // Previous entry is valid
176 PageTable::iterator i = lookupTable.find(table[Index].VPN);
177 lookupTable.erase(i);
178 }
179 table[Index]=pte;
180 // Update fast lookup table
181 lookupTable.insert(make_pair(table[Index].VPN, Index));
182 }
183}
184
185// insert a new TLB entry
186void
187TLB::insert(Addr addr, PTE &pte)
188{
189 fatal("TLB Insert not yet implemented\n");
190}
191
192void
193TLB::flushAll()
194{
195 DPRINTF(TLB, "flushAll\n");
196 memset(table, 0, sizeof(PTE[size]));
197 lookupTable.clear();
198 nlu = 0;
199}
200
201void
202TLB::serialize(CheckpointOut &cp) const
203{
204 SERIALIZE_SCALAR(size);
205 SERIALIZE_SCALAR(nlu);
206
207 for (int i = 0; i < size; i++) {
208 ScopedCheckpointSection sec(cp, csprintf("PTE%d", i));
209 table[i].serialize(cp);
210 }
211}
212
213void
214TLB::unserialize(CheckpointIn &cp)
215{
216 UNSERIALIZE_SCALAR(size);
217 UNSERIALIZE_SCALAR(nlu);
218
219 for (int i = 0; i < size; i++) {
220 ScopedCheckpointSection sec(cp, csprintf("PTE%d", i));
221 table[i].unserialize(cp);
222 if (table[i].V0 || table[i].V1) {
223 lookupTable.insert(make_pair(table[i].VPN, i));
224 }
225 }
226}
227
228void
229TLB::regStats()
230{
231 BaseTLB::regStats();
232
233 read_hits
234 .name(name() + ".read_hits")
235 .desc("DTB read hits")
236 ;
237
238 read_misses
239 .name(name() + ".read_misses")
240 .desc("DTB read misses")
241 ;
242
243
244 read_accesses
245 .name(name() + ".read_accesses")
246 .desc("DTB read accesses")
247 ;
248
249 write_hits
250 .name(name() + ".write_hits")
251 .desc("DTB write hits")
252 ;
253
254 write_misses
255 .name(name() + ".write_misses")
256 .desc("DTB write misses")
257 ;
258
259
260 write_accesses
261 .name(name() + ".write_accesses")
262 .desc("DTB write accesses")
263 ;
264
265 hits
266 .name(name() + ".hits")
267 .desc("DTB hits")
268 ;
269
270 misses
271 .name(name() + ".misses")
272 .desc("DTB misses")
273 ;
274
275 accesses
276 .name(name() + ".accesses")
277 .desc("DTB accesses")
278 ;
279
280 hits = read_hits + write_hits;
281 misses = read_misses + write_misses;
282 accesses = read_accesses + write_accesses;
283}
284
285Fault
286TLB::translateInst(RequestPtr req, ThreadContext *tc)
287{
288 if (FullSystem)
289 panic("translateInst not implemented in RISC-V.\n");
290
291 Process * p = tc->getProcessPtr();
292
293 Fault fault = p->pTable->translate(req);
294 if (fault != NoFault)
295 return fault;
296
297 return NoFault;
298}
299
300Fault
301TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
302{
303 if (FullSystem)
304 panic("translateData not implemented in RISC-V.\n");
305
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 * Zhengxing Li
33 * Deyuan Guo
34 */
35
36#include "arch/riscv/tlb.hh"
37
38#include <string>
39#include <vector>
40
41#include "arch/riscv/faults.hh"
42#include "arch/riscv/pagetable.hh"
43#include "arch/riscv/pra_constants.hh"
44#include "arch/riscv/utility.hh"
45#include "base/inifile.hh"
46#include "base/str.hh"
47#include "base/trace.hh"
48#include "cpu/thread_context.hh"
49#include "debug/RiscvTLB.hh"
50#include "debug/TLB.hh"
51#include "mem/page_table.hh"
52#include "params/RiscvTLB.hh"
53#include "sim/full_system.hh"
54#include "sim/process.hh"
55
56using namespace std;
57using namespace RiscvISA;
58
59///////////////////////////////////////////////////////////////////////
60//
61// RISC-V TLB
62//
63
64TLB::TLB(const Params *p)
65 : BaseTLB(p), size(p->size), nlu(0)
66{
67 table = new PTE[size];
68 memset(table, 0, sizeof(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
79RiscvISA::PTE *
80TLB::lookup(Addr vpn, uint8_t asn) const
81{
82 // assume not found...
83 PTE *retval = nullptr;
84 PageTable::const_iterator i = lookupTable.find(vpn);
85 if (i != lookupTable.end()) {
86 while (i->first == vpn) {
87 int index = i->second;
88 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 if (((vpn & InvMask) == (VPN & InvMask)) &&
95 (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
109RiscvISA::PTE*
110TLB::getEntry(unsigned Index) const
111{
112 // Make sure that Index is valid
113 assert(Index<size);
114 return &table[Index];
115}
116
117int
118TLB::probeEntry(Addr vpn, uint8_t asn) const
119{
120 // assume not found...
121 int Ind = -1;
122 PageTable::const_iterator i = lookupTable.find(vpn);
123 if (i != lookupTable.end()) {
124 while (i->first == vpn) {
125 int index = i->second;
126 PTE *pte = &table[index];
127
128 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
129 Addr Mask = pte->Mask;
130 Addr InvMask = ~Mask;
131 Addr VPN = pte->VPN;
132 if (((vpn & InvMask) == (VPN & InvMask)) &&
133 (pte->G || (asn == pte->asid))) {
134 // We have a VPN + ASID Match
135 Ind = index;
136 break;
137 }
138 ++i;
139 }
140 }
141 DPRINTF(RiscvTLB,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
142 return Ind;
143}
144
145inline Fault
146TLB::checkCacheability(RequestPtr &req)
147{
148 Addr VAddrUncacheable = 0xA0000000;
149 // In MIPS, cacheability is controlled by certain bits of the virtual
150 // address or by the TLB entry
151 if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
152 // mark request as uncacheable
153 req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
154 }
155 return NoFault;
156}
157
158void
159TLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
160{
161 smallPages = _smallPages;
162 if (Index > size) {
163 warn("Attempted to write at index (%d) beyond TLB size (%d)",
164 Index, size);
165 } else {
166 // Update TLB
167 DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
168 Index, pte.Mask << 11,
169 ((pte.VPN << 11) | pte.asid),
170 ((pte.PFN0 << 6) | (pte.C0 << 3) |
171 (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
172 ((pte.PFN1 <<6) | (pte.C1 << 3) |
173 (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
174 if (table[Index].V0 || table[Index].V1) {
175 // Previous entry is valid
176 PageTable::iterator i = lookupTable.find(table[Index].VPN);
177 lookupTable.erase(i);
178 }
179 table[Index]=pte;
180 // Update fast lookup table
181 lookupTable.insert(make_pair(table[Index].VPN, Index));
182 }
183}
184
185// insert a new TLB entry
186void
187TLB::insert(Addr addr, PTE &pte)
188{
189 fatal("TLB Insert not yet implemented\n");
190}
191
192void
193TLB::flushAll()
194{
195 DPRINTF(TLB, "flushAll\n");
196 memset(table, 0, sizeof(PTE[size]));
197 lookupTable.clear();
198 nlu = 0;
199}
200
201void
202TLB::serialize(CheckpointOut &cp) const
203{
204 SERIALIZE_SCALAR(size);
205 SERIALIZE_SCALAR(nlu);
206
207 for (int i = 0; i < size; i++) {
208 ScopedCheckpointSection sec(cp, csprintf("PTE%d", i));
209 table[i].serialize(cp);
210 }
211}
212
213void
214TLB::unserialize(CheckpointIn &cp)
215{
216 UNSERIALIZE_SCALAR(size);
217 UNSERIALIZE_SCALAR(nlu);
218
219 for (int i = 0; i < size; i++) {
220 ScopedCheckpointSection sec(cp, csprintf("PTE%d", i));
221 table[i].unserialize(cp);
222 if (table[i].V0 || table[i].V1) {
223 lookupTable.insert(make_pair(table[i].VPN, i));
224 }
225 }
226}
227
228void
229TLB::regStats()
230{
231 BaseTLB::regStats();
232
233 read_hits
234 .name(name() + ".read_hits")
235 .desc("DTB read hits")
236 ;
237
238 read_misses
239 .name(name() + ".read_misses")
240 .desc("DTB read misses")
241 ;
242
243
244 read_accesses
245 .name(name() + ".read_accesses")
246 .desc("DTB read accesses")
247 ;
248
249 write_hits
250 .name(name() + ".write_hits")
251 .desc("DTB write hits")
252 ;
253
254 write_misses
255 .name(name() + ".write_misses")
256 .desc("DTB write misses")
257 ;
258
259
260 write_accesses
261 .name(name() + ".write_accesses")
262 .desc("DTB write accesses")
263 ;
264
265 hits
266 .name(name() + ".hits")
267 .desc("DTB hits")
268 ;
269
270 misses
271 .name(name() + ".misses")
272 .desc("DTB misses")
273 ;
274
275 accesses
276 .name(name() + ".accesses")
277 .desc("DTB accesses")
278 ;
279
280 hits = read_hits + write_hits;
281 misses = read_misses + write_misses;
282 accesses = read_accesses + write_accesses;
283}
284
285Fault
286TLB::translateInst(RequestPtr req, ThreadContext *tc)
287{
288 if (FullSystem)
289 panic("translateInst not implemented in RISC-V.\n");
290
291 Process * p = tc->getProcessPtr();
292
293 Fault fault = p->pTable->translate(req);
294 if (fault != NoFault)
295 return fault;
296
297 return NoFault;
298}
299
300Fault
301TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
302{
303 if (FullSystem)
304 panic("translateData not implemented in RISC-V.\n");
305
306 // In the O3 CPU model, sometimes a memory access will be speculatively
307 // executed along a branch that will end up not being taken where the
308 // address is invalid. In that case, return a fault rather than trying
309 // to translate it (which will cause a panic). Since RISC-V allows
310 // unaligned memory accesses, this should only happen if the request's
311 // length is long enough to wrap around from the end of the memory to the
312 // start.
313 assert(req->getSize() > 0);
314 if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
315 return make_shared<GenericPageTableFault>(req->getVaddr());
316
306 Process * p = tc->getProcessPtr();
307
308 Fault fault = p->pTable->translate(req);
309 if (fault != NoFault)
310 return fault;
311
312 return NoFault;
313}
314
315Fault
316TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
317{
318 if (mode == Execute)
319 return translateInst(req, tc);
320 else
321 return translateData(req, tc, mode == Write);
322}
323
324void
325TLB::translateTiming(RequestPtr req, ThreadContext *tc,
326 Translation *translation, Mode mode)
327{
328 assert(translation);
329 translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
330}
331
332Fault
333TLB::translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode)
334{
335 panic("Not implemented\n");
336 return NoFault;
337}
338
339Fault
340TLB::finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
341{
342 return NoFault;
343}
344
345
346RiscvISA::PTE &
347TLB::index(bool advance)
348{
349 PTE *pte = &table[nlu];
350
351 if (advance)
352 nextnlu();
353
354 return *pte;
355}
356
357RiscvISA::TLB *
358RiscvTLBParams::create()
359{
360 return new TLB(this);
361}
317 Process * p = tc->getProcessPtr();
318
319 Fault fault = p->pTable->translate(req);
320 if (fault != NoFault)
321 return fault;
322
323 return NoFault;
324}
325
326Fault
327TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode)
328{
329 if (mode == Execute)
330 return translateInst(req, tc);
331 else
332 return translateData(req, tc, mode == Write);
333}
334
335void
336TLB::translateTiming(RequestPtr req, ThreadContext *tc,
337 Translation *translation, Mode mode)
338{
339 assert(translation);
340 translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
341}
342
343Fault
344TLB::translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode)
345{
346 panic("Not implemented\n");
347 return NoFault;
348}
349
350Fault
351TLB::finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
352{
353 return NoFault;
354}
355
356
357RiscvISA::PTE &
358TLB::index(bool advance)
359{
360 PTE *pte = &table[nlu];
361
362 if (advance)
363 nextnlu();
364
365 return *pte;
366}
367
368RiscvISA::TLB *
369RiscvTLBParams::create()
370{
371 return new TLB(this);
372}