2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * Copyright (c) 2007-2008 The Florida State University
5 * Copyright (c) 2009 The University of Edinburgh
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer;
12 * redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution;
15 * neither the name of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * Authors: Nathan Binkert
41 #include "arch/power/faults.hh"
42 #include "arch/power/pagetable.hh"
43 #include "arch/power/tlb.hh"
44 #include "arch/power/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 "mem/page_table.hh"
50 #include "params/PowerTLB.hh"
51 #include "sim/process.hh"
55 using namespace PowerISA
;
57 ///////////////////////////////////////////////////////////////////////
62 #define MODE2MASK(X) (1 << (X))
64 TLB::TLB(const Params
*p
)
65 : BaseTLB(p
), size(p
->size
), nlu(0)
67 table
= new PowerISA::PTE
[size
];
68 memset(table
, 0, sizeof(PowerISA::PTE
[size
]));
78 // look up an entry in the TLB
80 TLB::lookup(Addr vpn
, uint8_t asn
) const
82 // assume not found...
83 PowerISA::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 PowerISA::PTE
*pte
= &table
[index
];
89 Addr Mask
= pte
->Mask
;
92 if (((vpn
& InvMask
) == (VPN
& InvMask
))
93 && (pte
->G
|| (asn
== pte
->asid
))) {
95 // We have a VPN + ASID Match
103 DPRINTF(TLB
, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn
, (int)asn
,
104 retval
? "hit" : "miss", retval
? retval
->PFN1
: 0);
109 TLB::getEntry(unsigned Index
) const
111 // Make sure that Index is valid
113 return &table
[Index
];
117 TLB::probeEntry(Addr vpn
,uint8_t asn
) const
119 // assume not found...
120 PowerISA::PTE
*retval
= NULL
;
122 PageTable::const_iterator i
= lookupTable
.find(vpn
);
123 if (i
!= lookupTable
.end()) {
124 while (i
->first
== vpn
) {
125 int index
= i
->second
;
126 PowerISA::PTE
*pte
= &table
[index
];
127 Addr Mask
= pte
->Mask
;
128 Addr InvMask
= ~Mask
;
130 if (((vpn
& InvMask
) == (VPN
& InvMask
))
131 && (pte
->G
|| (asn
== pte
->asid
))) {
133 // We have a VPN + ASID Match
142 DPRINTF(Power
, "VPN: %x, asid: %d, Result of TLBP: %d\n", vpn
, asn
, Ind
);
147 TLB::checkCacheability(RequestPtr
&req
)
149 Addr VAddrUncacheable
= 0xA0000000;
150 if ((req
->getVaddr() & VAddrUncacheable
) == VAddrUncacheable
) {
152 // mark request as uncacheable
153 req
->setFlags(Request::UNCACHEABLE
);
159 TLB::insertAt(PowerISA::PTE
&pte
, unsigned Index
, int _smallPages
)
161 smallPages
=_smallPages
;
163 warn("Attempted to write at index (%d) beyond TLB size (%d)",
168 if (table
[Index
].V0
== true || table
[Index
].V1
== true) {
170 // Previous entry is valid
171 PageTable::iterator i
= lookupTable
.find(table
[Index
].VPN
);
172 lookupTable
.erase(i
);
176 // Update fast lookup table
177 lookupTable
.insert(make_pair(table
[Index
].VPN
, Index
));
181 // insert a new TLB entry
183 TLB::insert(Addr addr
, PowerISA::PTE
&pte
)
185 fatal("TLB Insert not yet implemented\n");
191 DPRINTF(TLB
, "flushAll\n");
192 memset(table
, 0, sizeof(PowerISA::PTE
[size
]));
198 TLB::serialize(ostream
&os
)
200 SERIALIZE_SCALAR(size
);
201 SERIALIZE_SCALAR(nlu
);
203 for (int i
= 0; i
< size
; i
++) {
204 nameOut(os
, csprintf("%s.PTE%d", name(), i
));
205 table
[i
].serialize(os
);
210 TLB::unserialize(Checkpoint
*cp
, const string
§ion
)
212 UNSERIALIZE_SCALAR(size
);
213 UNSERIALIZE_SCALAR(nlu
);
215 for (int i
= 0; i
< size
; i
++) {
216 table
[i
].unserialize(cp
, csprintf("%s.PTE%d", section
, i
));
217 if (table
[i
].V0
|| table
[i
].V1
) {
218 lookupTable
.insert(make_pair(table
[i
].VPN
, i
));
227 .name(name() + ".read_hits")
228 .desc("DTB read hits")
232 .name(name() + ".read_misses")
233 .desc("DTB read misses")
238 .name(name() + ".read_accesses")
239 .desc("DTB read accesses")
243 .name(name() + ".write_hits")
244 .desc("DTB write hits")
248 .name(name() + ".write_misses")
249 .desc("DTB write misses")
254 .name(name() + ".write_accesses")
255 .desc("DTB write accesses")
259 .name(name() + ".hits")
264 .name(name() + ".misses")
269 .name(name() + ".invalids")
270 .desc("DTB access violations")
274 .name(name() + ".accesses")
275 .desc("DTB accesses")
278 hits
= read_hits
+ write_hits
;
279 misses
= read_misses
+ write_misses
;
280 accesses
= read_accesses
+ write_accesses
;
284 TLB::translateInst(RequestPtr req
, ThreadContext
*tc
)
286 // Instruction accesses must be word-aligned
287 if (req
->getVaddr() & 0x3) {
288 DPRINTF(TLB
, "Alignment Fault on %#x, size = %d\n", req
->getVaddr(),
290 return new AlignmentFault();
293 Process
* p
= tc
->getProcessPtr();
295 Fault fault
= p
->pTable
->translate(req
);
296 if (fault
!= NoFault
)
303 TLB::translateData(RequestPtr req
, ThreadContext
*tc
, bool write
)
305 Process
* p
= tc
->getProcessPtr();
307 Fault fault
= p
->pTable
->translate(req
);
308 if (fault
!= NoFault
)
315 TLB::translateAtomic(RequestPtr req
, ThreadContext
*tc
, Mode mode
)
319 return translateInst(req
, tc
);
321 return translateData(req
, tc
, mode
== Write
);
323 fatal("translate atomic not yet implemented\n");
328 TLB::translateTiming(RequestPtr req
, ThreadContext
*tc
,
329 Translation
*translation
, Mode mode
)
332 translation
->finish(translateAtomic(req
, tc
, mode
), req
, tc
, mode
);
336 TLB::index(bool advance
)
338 PowerISA::PTE
*pte
= &table
[nlu
];
347 PowerTLBParams::create()
349 return new PowerISA::TLB(this);