gem5 v24.0.0.0
Loading...
Searching...
No Matches
tlb.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2013, 2016-2023 Arm Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2001-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41#include "arch/arm/tlb.hh"
42
43#include <memory>
44#include <string>
45#include <vector>
46
48#include "arch/arm/tlbi_op.hh"
49#include "arch/arm/utility.hh"
50#include "base/trace.hh"
51#include "cpu/thread_context.hh"
52#include "debug/TLB.hh"
53#include "debug/TLBVerbose.hh"
54#include "params/ArmTLB.hh"
55
56namespace gem5
57{
58
59using namespace ArmISA;
60
61TLB::TLB(const ArmTLBParams &p)
62 : BaseTLB(p), table(new TlbEntry[p.size]), size(p.size),
63 isStage2(p.is_stage2),
64 _walkCache(false),
65 tableWalker(nullptr),
66 stats(*this), rangeMRU(1), vmid(0)
67{
68 for (int lvl = LookupLevel::L0;
69 lvl < LookupLevel::Num_ArmLookupLevel; lvl++) {
70
71 auto it = std::find(
72 p.partial_levels.begin(),
73 p.partial_levels.end(),
74 lvl);
75
76 auto lookup_lvl = static_cast<LookupLevel>(lvl);
77
78 if (it != p.partial_levels.end()) {
79 // A partial entry from of the current LookupLevel can be
80 // cached within the TLB
81 partialLevels[lookup_lvl] = true;
82
83 // Make sure this is not the last level (complete translation)
84 if (lvl != LookupLevel::Num_ArmLookupLevel - 1) {
85 _walkCache = true;
86 }
87 } else {
88 partialLevels[lookup_lvl] = false;
89 }
90 }
91}
92
94{
95 delete[] table;
96}
97
98void
100{
101 tableWalker = table_walker;
102 tableWalker->setTlb(this);
103}
104
106TLB::match(const Lookup &lookup_data)
107{
108 // Vector of TLB entry candidates.
109 // Only one of them will be assigned to retval and will
110 // be returned to the MMU (in case of a hit)
111 // The vector has one entry per lookup level as it stores
112 // both complete and partial matches
114 LookupLevel::Num_ArmLookupLevel, {0, nullptr}};
115
116 int x = 0;
117 while (x < size) {
118 if (table[x].match(lookup_data)) {
119 const TlbEntry &entry = table[x];
120 hits[entry.lookupLevel] = std::make_pair(x, &entry);
121
122 // This is a complete translation, no need to loop further
123 if (!entry.partial)
124 break;
125 }
126 ++x;
127 }
128
129 // Loop over the list of TLB entries matching our translation
130 // request, starting from the highest lookup level (complete
131 // translation) and iterating backwards (using reverse iterators)
132 for (auto it = hits.rbegin(); it != hits.rend(); it++) {
133 const auto& [idx, entry] = *it;
134 if (!entry) {
135 // No match for the current LookupLevel
136 continue;
137 }
138
139 // Maintaining LRU array
140 // We only move the hit entry ahead when the position is higher
141 // than rangeMRU
142 if (idx > rangeMRU && !lookup_data.functional) {
143 TlbEntry tmp_entry = *entry;
144 for (int i = idx; i > 0; i--)
145 table[i] = table[i - 1];
146 table[0] = tmp_entry;
147 return &table[0];
148 } else {
149 return &table[idx];
150 }
151 }
152
153 return nullptr;
154}
155
157TLB::lookup(const Lookup &lookup_data)
158{
159 const auto mode = lookup_data.mode;
160
161 TlbEntry *retval = match(lookup_data);
162
163 DPRINTF(TLBVerbose, "Lookup %#x, asn %#x -> %s vmn 0x%x secure %d "
164 "ppn %#x size: %#x pa: %#x ap:%d ns:%d nstid:%d g:%d asid: %d "
165 "regime: %s\n",
166 lookup_data.va, lookup_data.asn, retval ? "hit" : "miss",
167 lookup_data.vmid, lookup_data.secure,
168 retval ? retval->pfn : 0, retval ? retval->size : 0,
169 retval ? retval->pAddr(lookup_data.va) : 0,
170 retval ? retval->ap : 0,
171 retval ? retval->ns : 0, retval ? retval->nstid : 0,
172 retval ? retval->global : 0, retval ? retval->asid : 0,
173 retval ? regimeToStr(retval->regime) : 0);
174
175 // Updating stats if this was not a functional lookup
176 if (!lookup_data.functional) {
177 if (!retval) {
178 if (mode == BaseMMU::Execute) {
180 } else if (mode == BaseMMU::Write) {
182 } else {
184 }
185 } else {
186 if (retval->partial) {
188 }
189
190 if (mode == BaseMMU::Execute) {
191 stats.instHits++;
192 } else if (mode == BaseMMU::Write) {
194 } else {
195 stats.readHits++;
196 }
197 }
198 }
199
200 return retval;
201}
202
204TLB::multiLookup(const Lookup &lookup_data)
205{
206 TlbEntry* te = lookup(lookup_data);
207
208 if (te) {
209 checkPromotion(te, lookup_data.mode);
210 } else {
211 if (auto tlb = static_cast<TLB*>(nextLevel())) {
212 te = tlb->multiLookup(lookup_data);
213 if (te && !lookup_data.functional &&
214 (!te->partial || partialLevels[te->lookupLevel])) {
215 // Insert entry only if this is not a functional
216 // lookup and if the translation is complete (unless this
217 // TLB caches partial translations)
218 insert(*te);
219 }
220 }
221 }
222
223 return te;
224}
225
226void
228{
229 TypeTLB acc_type = (mode == BaseMMU::Execute) ?
230 TypeTLB::instruction : TypeTLB::data;
231
232 // Hitting an instruction TLB entry on a data access or
233 // a data TLB entry on an instruction access:
234 // promoting the entry to unified
235 if (!(entry->type & acc_type))
236 entry->type = TypeTLB::unified;
237}
238
239// insert a new TLB entry
240void
242{
243 DPRINTF(TLB, "Inserting entry into TLB with pfn:%#x size:%#x vpn: %#x"
244 " asid:%d vmid:%d N:%d global:%d valid:%d nc:%d xn:%d"
245 " ap:%#x domain:%#x ns:%d nstid:%d, regime: %s\n", entry.pfn,
246 entry.size, entry.vpn, entry.asid, entry.vmid, entry.N,
247 entry.global, entry.valid, entry.nonCacheable, entry.xn,
248 entry.ap, static_cast<uint8_t>(entry.domain), entry.ns,
249 entry.nstid, regimeToStr(entry.regime));
250
251 if (table[size - 1].valid)
252 DPRINTF(TLB, " - Replacing Valid entry %#x, asn %d vmn %d ppn %#x "
253 "size: %#x ap:%d ns:%d nstid:%d g:%d regime: %s\n",
254 table[size-1].vpn << table[size-1].N, table[size-1].asid,
255 table[size-1].vmid, table[size-1].pfn << table[size-1].N,
256 table[size-1].size, table[size-1].ap, table[size-1].ns,
257 table[size-1].nstid, table[size-1].global,
258 regimeToStr(table[size-1].regime));
259
260 // inserting to MRU position and evicting the LRU one
261 for (int i = size - 1; i > 0; --i)
262 table[i] = table[i-1];
263 table[0] = entry;
264
265 stats.inserts++;
266 ppRefills->notify(1);
267}
268
269void
271{
272 // Insert a partial translation only if the TLB is configured
273 // as a walk cache
274 if (!entry.partial || partialLevels[entry.lookupLevel]) {
275 insert(entry);
276 }
277
278 if (auto next_level = static_cast<TLB*>(nextLevel())) {
279 next_level->multiInsert(entry);
280 }
281}
282
283void
285{
286 int x = 0;
287 TlbEntry *te;
288 DPRINTF(TLB, "Current TLB contents:\n");
289 while (x < size) {
290 te = &table[x];
291 if (te->valid)
292 DPRINTF(TLB, " * %s\n", te->print());
293 ++x;
294 }
295}
296
297void
299{
300 DPRINTF(TLB, "Flushing all TLB entries\n");
301 int x = 0;
302 TlbEntry *te;
303 while (x < size) {
304 te = &table[x];
305
306 if (te->valid) {
307 DPRINTF(TLB, " - %s\n", te->print());
308 te->valid = false;
310 }
311 ++x;
312 }
313
314 stats.flushTlb++;
315}
316
317void
318TLB::flush(const TLBIOp& tlbi_op)
319{
320 int x = 0;
321 TlbEntry *te;
322 while (x < size) {
323 te = &table[x];
324 if (tlbi_op.match(te, vmid)) {
325 DPRINTF(TLB, " - %s\n", te->print());
326 te->valid = false;
328 }
329 ++x;
330 }
331
332 stats.flushTlb++;
333}
334
335void
337{
338}
339
341 : statistics::Group(&parent), tlb(parent),
342 ADD_STAT(partialHits, statistics::units::Count::get(),
343 "partial translation hits"),
344 ADD_STAT(instHits, statistics::units::Count::get(), "Inst hits"),
345 ADD_STAT(instMisses, statistics::units::Count::get(), "Inst misses"),
346 ADD_STAT(readHits, statistics::units::Count::get(), "Read hits"),
347 ADD_STAT(readMisses, statistics::units::Count::get(), "Read misses"),
348 ADD_STAT(writeHits, statistics::units::Count::get(), "Write hits"),
349 ADD_STAT(writeMisses, statistics::units::Count::get(), "Write misses"),
350 ADD_STAT(inserts, statistics::units::Count::get(),
351 "Number of times an entry is inserted into the TLB"),
352 ADD_STAT(flushTlb, statistics::units::Count::get(),
353 "Number of times a TLB invalidation was requested"),
354 ADD_STAT(flushedEntries, statistics::units::Count::get(),
355 "Number of entries that have been flushed from TLB"),
356 ADD_STAT(readAccesses, statistics::units::Count::get(), "Read accesses",
357 readHits + readMisses),
358 ADD_STAT(writeAccesses, statistics::units::Count::get(), "Write accesses",
359 writeHits + writeMisses),
360 ADD_STAT(instAccesses, statistics::units::Count::get(), "Inst accesses",
361 instHits + instMisses),
362 ADD_STAT(hits, statistics::units::Count::get(),
363 "Total TLB (inst and data) hits",
364 readHits + writeHits + instHits),
365 ADD_STAT(misses, statistics::units::Count::get(),
366 "Total TLB (inst and data) misses",
367 readMisses + writeMisses + instMisses),
368 ADD_STAT(accesses, statistics::units::Count::get(),
369 "Total TLB (inst and data) accesses",
370 readAccesses + writeAccesses + instAccesses)
371{
372 // If this is a pure Data TLB, mark the instruction
373 // stats as nozero, so that they won't make it in
374 // into the final stats file
375 if (tlb.type() == TypeTLB::data) {
378
380 }
381
382 // If this is a pure Instruction TLB, mark the data
383 // stats as nozero, so that they won't make it in
384 // into the final stats file
385 if (tlb.type() & TypeTLB::instruction) {
390
393 }
394
396}
397
398void
403
404Port *
409
410} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
virtual bool match(TlbEntry *entry, vmid_t curr_vmid) const =0
int size
TLB Size.
Definition tlb.hh:108
void takeOverFrom(BaseTLB *otlb) override
Take over from an old tlb context.
Definition tlb.cc:336
TlbEntry * lookup(const Lookup &lookup_data)
Lookup an entry in the TLB.
Definition tlb.cc:157
TableWalker * tableWalker
Definition tlb.hh:125
void setTableWalker(TableWalker *table_walker)
Definition tlb.cc:99
TlbEntry * multiLookup(const Lookup &lookup_data)
Lookup an entry in the TLB and in the next levels by following the nextLevel pointer.
Definition tlb.cc:204
void flush(const TLBIOp &tlbi_op)
Flush TLB entries.
Definition tlb.cc:318
void regProbePoints() override
Register probe points for this object.
Definition tlb.cc:399
void printTlb() const
Definition tlb.cc:284
TLB(const Params &p)
Definition tlb.cc:61
virtual ~TLB()
Definition tlb.cc:93
Port * getTableWalkerPort() override
Get the table walker port.
Definition tlb.cc:405
probing::PMUUPtr ppRefills
PMU probe for TLB refills.
Definition tlb.hh:154
bool _walkCache
True if the TLB caches partial translations.
Definition tlb.hh:123
void insert(TlbEntry &pte)
Insert a PTE in the current TLB.
Definition tlb.cc:241
void multiInsert(TlbEntry &pte)
Insert a PTE in the current TLB and in the higher levels.
Definition tlb.cc:270
std::unordered_map< enums::ArmLookupLevel, bool > partialLevels
Hash map containing one entry per lookup level The TLB is caching partial translations from the key l...
Definition tlb.hh:118
vmid_t vmid
Definition tlb.hh:157
void checkPromotion(TlbEntry *entry, BaseMMU::Mode mode)
Check if the tlb entry passed as an argument needs to be "promoted" as a unified entry: this should h...
Definition tlb.cc:227
gem5::ArmISA::TLB::TlbStats stats
TlbEntry * match(const Lookup &lookup_data)
Helper function looking up for a matching TLB entry Does not update stats; see lookup method instead.
Definition tlb.cc:106
enums::ArmLookupLevel LookupLevel
Definition tlb.hh:162
TlbEntry * table
Definition tlb.hh:105
void flushAll() override
Reset the entire TLB.
Definition tlb.cc:298
TypeTLB type() const
Definition tlb.hh:125
BaseTLB * nextLevel() const
Definition tlb.hh:127
Ports are used to interface objects to each other.
Definition port.hh:62
ProbePointArg generates a point for the class of Arg.
Definition probe.hh:264
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Statistics container.
Definition group.hh:93
STL vector class.
Definition stl.hh:37
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
ProbeManager * getProbeManager()
Get the probe manager for this object.
Bitfield< 30 > te
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
Bitfield< 7 > i
Definition misc_types.hh:67
static const char * regimeToStr(TranslationRegime regime)
Definition types.hh:474
Bitfield< 0 > ns
Bitfield< 59, 56 > tlb
Bitfield< 29, 6 > pfn
Bitfield< 0 > p
Bitfield< 3 > x
Definition pagetable.hh:73
const FlagsType nozero
Don't print if this is zero.
Definition info.hh:67
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
statistics::Formula writeAccesses
Definition tlb.hh:146
statistics::Scalar readHits
Definition tlb.hh:137
statistics::Scalar instHits
Definition tlb.hh:135
statistics::Scalar flushedEntries
Definition tlb.hh:143
statistics::Formula readAccesses
Definition tlb.hh:145
statistics::Scalar inserts
Definition tlb.hh:141
statistics::Scalar flushTlb
Definition tlb.hh:142
TlbStats(TLB &parent)
Definition tlb.cc:340
statistics::Scalar readMisses
Definition tlb.hh:138
statistics::Scalar writeHits
Definition tlb.hh:139
statistics::Scalar writeMisses
Definition tlb.hh:140
statistics::Formula instAccesses
Definition tlb.hh:147
statistics::Scalar instMisses
Definition tlb.hh:136
statistics::Scalar partialHits
Definition tlb.hh:134
TranslationRegime regime
Definition pagetable.hh:245
LookupLevel lookupLevel
Definition pagetable.hh:217
Addr pAddr(Addr va) const
Definition pagetable.hh:351
The file contains the definition of a set of TLB Invalidate Instructions.

Generated on Tue Jun 18 2024 16:24:00 for gem5 by doxygen 1.11.0