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
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met: redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Authors: Nathan Binkert
39 #include "arch/arm/pagetable.hh"
40 #include "arch/arm/tlb.hh"
41 #include "arch/arm/faults.hh"
42 #include "arch/arm/utility.hh"
43 #include "base/inifile.hh"
44 #include "base/str.hh"
45 #include "base/trace.hh"
46 #include "cpu/thread_context.hh"
47 #include "sim/process.hh"
48 #include "mem/page_table.hh"
49 #include "params/ArmDTB.hh"
50 #include "params/ArmITB.hh"
51 #include "params/ArmTLB.hh"
52 #include "params/ArmUTB.hh"
56 using namespace ArmISA
;
58 ///////////////////////////////////////////////////////////////////////
63 #define MODE2MASK(X) (1 << (X))
65 TLB::TLB(const Params
*p
)
66 : BaseTLB(p
), size(p
->size
), nlu(0)
68 table
= new ArmISA::PTE
[size
];
69 memset(table
, 0, sizeof(ArmISA::PTE
[size
]));
79 // look up an entry in the TLB
81 TLB::lookup(Addr vpn
, uint8_t asn
) const
83 // assume not found...
84 ArmISA::PTE
*retval
= NULL
;
85 PageTable::const_iterator i
= lookupTable
.find(vpn
);
86 if (i
!= lookupTable
.end()) {
87 while (i
->first
== vpn
) {
88 int index
= i
->second
;
89 ArmISA::PTE
*pte
= &table
[index
];
91 /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */
92 Addr Mask
= pte
->Mask
;
95 // warn("Valid: %d - %d\n",pte->V0,pte->V1);
96 if(((vpn
& InvMask
) == (VPN
& InvMask
)) && (pte
->G
|| (asn
== pte
->asid
)))
97 { // We have a VPN + ASID Match
105 DPRINTF(TLB
, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn
, (int)asn
,
106 retval
? "hit" : "miss", retval
? retval
->PFN1
: 0);
110 ArmISA::PTE
* TLB::getEntry(unsigned Index
) const
112 // Make sure that Index is valid
114 return &table
[Index
];
117 int TLB::probeEntry(Addr vpn
,uint8_t asn
) const
119 // assume not found...
120 ArmISA::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 ArmISA::PTE
*pte
= &table
[index
];
128 /* 1KB TLB Lookup code - from ARM ARM Volume III - Rev. 2.50 */
129 Addr Mask
= pte
->Mask
;
130 Addr InvMask
= ~Mask
;
132 if(((vpn
& InvMask
) == (VPN
& InvMask
)) && (pte
->G
|| (asn
== pte
->asid
)))
133 { // We have a VPN + ASID Match
142 DPRINTF(Arm
,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn
,asn
,Ind
);
146 TLB::checkCacheability(RequestPtr
&req
)
148 Addr VAddrUncacheable
= 0xA0000000;
149 // In ARM, cacheability is controlled by certain bits of the virtual address
150 // or by the TLB entry
151 if((req
->getVaddr() & VAddrUncacheable
) == VAddrUncacheable
) {
152 // mark request as uncacheable
153 req
->setFlags(req
->getFlags() | Request::UNCACHEABLE
);
157 void TLB::insertAt(ArmISA::PTE
&pte
, unsigned Index
, int _smallPages
)
159 smallPages
=_smallPages
;
161 warn("Attempted to write at index (%d) beyond TLB size (%d)",Index
,size
);
164 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
),
165 ((pte
.PFN1
<<6) | (pte
.C1
<< 3) | (pte
.D1
<< 2) | (pte
.V1
<<1) | pte
.G
));
166 if(table
[Index
].V0
== true || table
[Index
].V1
== true){ // Previous entry is valid
167 PageTable::iterator i
= lookupTable
.find(table
[Index
].VPN
);
168 lookupTable
.erase(i
);
171 // Update fast lookup table
172 lookupTable
.insert(make_pair(table
[Index
].VPN
, Index
));
173 // int TestIndex=probeEntry(pte.VPN,pte.asid);
174 // warn("Inserted at: %d, Found at: %d (%x)\n",Index,TestIndex,pte.Mask);
179 // insert a new TLB entry
181 TLB::insert(Addr addr
, ArmISA::PTE
&pte
)
183 fatal("TLB Insert not yet implemented\n");
189 DPRINTF(TLB
, "flushAll\n");
190 memset(table
, 0, sizeof(ArmISA::PTE
[size
]));
196 TLB::serialize(ostream
&os
)
198 SERIALIZE_SCALAR(size
);
199 SERIALIZE_SCALAR(nlu
);
201 for (int i
= 0; i
< size
; i
++) {
202 nameOut(os
, csprintf("%s.PTE%d", name(), i
));
203 table
[i
].serialize(os
);
208 TLB::unserialize(Checkpoint
*cp
, const string
§ion
)
210 UNSERIALIZE_SCALAR(size
);
211 UNSERIALIZE_SCALAR(nlu
);
213 for (int i
= 0; i
< size
; i
++) {
214 table
[i
].unserialize(cp
, csprintf("%s.PTE%d", section
, i
));
215 if (table
[i
].V0
|| table
[i
].V1
) {
216 lookupTable
.insert(make_pair(table
[i
].VPN
, i
));
225 .name(name() + ".read_hits")
226 .desc("DTB read hits")
230 .name(name() + ".read_misses")
231 .desc("DTB read misses")
236 .name(name() + ".read_accesses")
237 .desc("DTB read accesses")
241 .name(name() + ".write_hits")
242 .desc("DTB write hits")
246 .name(name() + ".write_misses")
247 .desc("DTB write misses")
252 .name(name() + ".write_accesses")
253 .desc("DTB write accesses")
257 .name(name() + ".hits")
262 .name(name() + ".misses")
267 .name(name() + ".invalids")
268 .desc("DTB access violations")
272 .name(name() + ".accesses")
273 .desc("DTB accesses")
276 hits
= read_hits
+ write_hits
;
277 misses
= read_misses
+ write_misses
;
278 accesses
= read_accesses
+ write_accesses
;
282 ITB::translateAtomic(RequestPtr req
, ThreadContext
*tc
)
285 Process
* p
= tc
->getProcessPtr();
287 Fault fault
= p
->pTable
->translate(req
);
293 fatal("ITB translate not yet implemented\n");
298 ITB::translateTiming(RequestPtr req
, ThreadContext
*tc
,
299 Translation
*translation
)
302 translation
->finish(translateAtomic(req
, tc
), req
, tc
, false);
307 DTB::translateAtomic(RequestPtr req
, ThreadContext
*tc
, bool write
)
310 Process
* p
= tc
->getProcessPtr();
312 Fault fault
= p
->pTable
->translate(req
);
318 fatal("DTB translate not yet implemented\n");
323 DTB::translateTiming(RequestPtr req
, ThreadContext
*tc
,
324 Translation
*translation
, bool write
)
327 translation
->finish(translateAtomic(req
, tc
, write
), req
, tc
, write
);
330 ///////////////////////////////////////////////////////////////////////
334 ITB::ITB(const Params
*p
)
339 ///////////////////////////////////////////////////////////////////////
343 DTB::DTB(const Params
*p
)
347 ///////////////////////////////////////////////////////////////////////
351 UTB::UTB(const Params
*p
)
356 TLB::index(bool advance
)
358 ArmISA::PTE
*pte
= &table
[nlu
];
367 ArmITBParams::create()
369 return new ArmISA::ITB(this);
373 ArmDTBParams::create()
375 return new ArmISA::DTB(this);
379 ArmUTBParams::create()
381 return new ArmISA::UTB(this);