gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
tlb.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2013, 2016-2024 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
63{
64 auto entry = findEntry(key);
65
66 if (entry && !key.functional) {
67 accessEntry(entry);
68 }
69
70 return entry;
71}
72
75{
76 // Exploiting locality to maximaize simulator performance
77 if (prev && prev->N == key.pageSize && prev->match(key)) {
78 return prev;
79 }
80
81 for (auto candidate : indexingPolicy->getPossibleEntries(key)) {
82 auto entry = static_cast<TlbEntry*>(candidate);
83 // We check for pageSize match outside of the Entry::match
84 // as the latter is also used to match entries in TLBI invalidation
85 // where we don't care about the pageSize
86 if (entry->N == key.pageSize && entry->match(key)) {
87 return prev = entry;
88 }
89 }
90
91 return nullptr;
92}
93
94void
96{
97 if (!invalid || invalid == prev)
98 prev = nullptr;
99}
100
101TLB::TLB(const ArmTLBParams &p)
102 : BaseTLB(p),
103 table(name().c_str(), p.size, p.assoc,
104 p.replacement_policy, p.indexing_policy),
105 size(p.size),
106 isStage2(p.is_stage2),
107 _walkCache(false),
108 tableWalker(nullptr),
109 stats(*this), rangeMRU(1), vmid(0)
110{
111 for (int lvl = LookupLevel::L0;
112 lvl < LookupLevel::Num_ArmLookupLevel; lvl++) {
113
114 auto it = std::find(
115 p.partial_levels.begin(),
116 p.partial_levels.end(),
117 lvl);
118
119 auto lookup_lvl = static_cast<LookupLevel>(lvl);
120
121 if (it != p.partial_levels.end()) {
122 // A partial entry from of the current LookupLevel can be
123 // cached within the TLB
124 partialLevels[lookup_lvl] = true;
125
126 // Make sure this is not the last level (complete translation)
127 if (lvl != LookupLevel::Num_ArmLookupLevel - 1) {
128 _walkCache = true;
129 }
130 } else {
131 partialLevels[lookup_lvl] = false;
132 }
133 }
134
135 table.setDebugFlag(::gem5::debug::TLB);
136}
137
139{
140}
141
142void
144{
145 tableWalker = table_walker;
146 tableWalker->setTlb(this);
147}
148
150TLB::lookup(Lookup lookup_data)
151{
152 const auto mode = lookup_data.mode;
153
154 TlbEntry *retval = nullptr;
155 // We iterate over all stored sizes, starting from the
156 // smallest until the biggest. In this way we prioritize
157 // complete translations over partial translations
158 for (const auto &page_size : observedPageSizes) {
159 lookup_data.pageSize = page_size;
160 if (retval = table.accessEntry(lookup_data); retval)
161 break;
162 }
163
164 DPRINTF(TLBVerbose, "Lookup %#x, asn %#x -> %s vmn 0x%x ss %s "
165 "ppn %#x size: %#x pa: %#x ap:%d piindex:%d "
166 "ns:%d ss:%s g:%d asid: %d "
167 "xs: %d regime: %s\n",
168 lookup_data.va, lookup_data.asn, retval ? "hit" : "miss",
169 lookup_data.vmid, lookup_data.ss,
170 retval ? retval->pfn : 0, retval ? retval->size : 0,
171 retval ? retval->pAddr(lookup_data.va) : 0,
172 retval ? retval->ap : 0,
173 retval ? retval->piindex : 0,
174 retval ? retval->ns : 0,
175 retval ? retval->ss : SecurityState::NonSecure,
176 retval ? retval->global : 0, retval ? retval->asid : 0,
177 retval ? retval->xs : 0,
178 retval ? regimeToStr(retval->regime) : "None");
179
180 // Updating stats if this was not a functional lookup
181 if (!lookup_data.functional) {
182 if (!retval) {
183 if (mode == BaseMMU::Execute) {
184 stats.instMisses++;
185 } else if (mode == BaseMMU::Write) {
186 stats.writeMisses++;
187 } else {
188 stats.readMisses++;
189 }
190 } else {
191 if (retval->partial) {
192 stats.partialHits++;
193 }
194
195 if (mode == BaseMMU::Execute) {
196 stats.instHits++;
197 } else if (mode == BaseMMU::Write) {
198 stats.writeHits++;
199 } else {
200 stats.readHits++;
201 }
202 }
203 }
204
205 return retval;
206}
207
209TLB::multiLookup(const Lookup &lookup_data)
210{
211 TlbEntry* te = lookup(lookup_data);
212
213 if (te) {
214 checkPromotion(te, lookup_data.mode);
215 } else {
216 if (auto tlb = static_cast<TLB*>(nextLevel())) {
217 te = tlb->multiLookup(lookup_data);
218 if (te && !lookup_data.functional &&
219 (!te->partial || partialLevels[te->lookupLevel])) {
220 // Insert entry only if this is not a functional
221 // lookup and if the translation is complete (unless this
222 // TLB caches partial translations)
223 insert(lookup_data, *te);
224 }
225 }
226 }
227
228 return te;
229}
230
231void
233{
234 TypeTLB acc_type = (mode == BaseMMU::Execute) ?
235 TypeTLB::instruction : TypeTLB::data;
236
237 // Hitting an instruction TLB entry on a data access or
238 // a data TLB entry on an instruction access:
239 // promoting the entry to unified
240 if (!(entry->type & acc_type))
241 entry->type = TypeTLB::unified;
242}
243
244// insert a new TLB entry
245void
246TLB::insert(const Lookup &lookup_data, TlbEntry &entry)
247{
248 TlbEntry *victim = table.findVictim(lookup_data);
249
250 *victim = entry;
251
252 table.insertEntry(lookup_data, victim);
253
254 table.invalidatePrev(victim);
255
256 observedPageSizes.insert(entry.N);
257 stats.inserts++;
258 ppRefills->notify(1);
259}
260
261void
263{
264 // Insert a partial translation only if the TLB is configured
265 // as a walk cache
266 if (!entry.partial || partialLevels[entry.lookupLevel]) {
267 insert(lookup, entry);
268 }
269
270 if (auto next_level = static_cast<TLB*>(nextLevel())) {
271 next_level->multiInsert(lookup, entry);
272 }
273}
274
275void
277{
278 DPRINTF(TLB, "Current TLB contents:\n");
279 for (auto& te : table) {
280 if (te.valid)
281 DPRINTF(TLB, " * %s\n", te.print());
282 }
283}
284
285void
287{
288 DPRINTF(TLB, "Flushing all TLB entries\n");
289 for (auto& te : table) {
290 if (te.valid) {
291 DPRINTF(TLB, " - %s\n", te.print());
292 table.invalidate(&te);
293 stats.flushedEntries++;
294 }
295 }
296
297 table.invalidatePrev();
298
299 stats.flushTlb++;
300 observedPageSizes.clear();
301}
302
303void
304TLB::flush(const TLBIOp& tlbi_op)
305{
306 bool valid_entry = false;
307 for (auto& te : table) {
308 if (tlbi_op.match(&te, vmid)) {
309 DPRINTF(TLB, " - %s\n", te.print());
310 table.invalidate(&te);
311
312 table.invalidatePrev(&te);
313
314 stats.flushedEntries++;
315 }
316 valid_entry = valid_entry || te.valid;
317 }
318
319 stats.flushTlb++;
320 if (!valid_entry)
321 observedPageSizes.clear();
322}
323
324void
326{
327}
328
330 : statistics::Group(&parent), tlb(parent),
331 ADD_STAT(partialHits, statistics::units::Count::get(),
332 "partial translation hits"),
333 ADD_STAT(instHits, statistics::units::Count::get(), "Inst hits"),
334 ADD_STAT(instMisses, statistics::units::Count::get(), "Inst misses"),
335 ADD_STAT(readHits, statistics::units::Count::get(), "Read hits"),
336 ADD_STAT(readMisses, statistics::units::Count::get(), "Read misses"),
337 ADD_STAT(writeHits, statistics::units::Count::get(), "Write hits"),
338 ADD_STAT(writeMisses, statistics::units::Count::get(), "Write misses"),
339 ADD_STAT(inserts, statistics::units::Count::get(),
340 "Number of times an entry is inserted into the TLB"),
341 ADD_STAT(flushTlb, statistics::units::Count::get(),
342 "Number of times a TLB invalidation was requested"),
343 ADD_STAT(flushedEntries, statistics::units::Count::get(),
344 "Number of entries that have been flushed from TLB"),
345 ADD_STAT(readAccesses, statistics::units::Count::get(), "Read accesses",
347 ADD_STAT(writeAccesses, statistics::units::Count::get(), "Write accesses",
349 ADD_STAT(instAccesses, statistics::units::Count::get(), "Inst accesses",
351 ADD_STAT(hits, statistics::units::Count::get(),
352 "Total TLB (inst and data) hits",
354 ADD_STAT(misses, statistics::units::Count::get(),
355 "Total TLB (inst and data) misses",
357 ADD_STAT(accesses, statistics::units::Count::get(),
358 "Total TLB (inst and data) accesses",
360{
361 // If this is a pure Data TLB, mark the instruction
362 // stats as nozero, so that they won't make it in
363 // into the final stats file
364 if (tlb.type() == TypeTLB::data) {
365 instHits.flags(statistics::nozero);
366 instMisses.flags(statistics::nozero);
367
368 instAccesses.flags(statistics::nozero);
369 }
370
371 // If this is a pure Instruction TLB, mark the data
372 // stats as nozero, so that they won't make it in
373 // into the final stats file
374 if (tlb.type() & TypeTLB::instruction) {
375 readHits.flags(statistics::nozero);
376 readMisses.flags(statistics::nozero);
377 writeHits.flags(statistics::nozero);
378 writeMisses.flags(statistics::nozero);
379
380 readAccesses.flags(statistics::nozero);
381 writeAccesses.flags(statistics::nozero);
382 }
383
385}
386
387void
389{
390 ppRefills.reset(new probing::PMU(getProbeManager(), "Refills"));
391}
392
393Port *
395{
396 return &tableWalker->getTableWalkerPort();
397}
398
399} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
bool match(TlbEntry *entry, vmid_t curr_vmid) const
Definition tlbi_op.cc:49
TlbEntry * findEntry(const KeyType &key) const override
Definition tlb.cc:74
TlbEntry * accessEntry(const KeyType &key) override
Definition tlb.cc:62
TlbEntry * prev
Last matched entry.
Definition tlb.hh:127
void invalidatePrev(const TlbEntry *invalid=nullptr)
Invalidate the last matched entry The method has an optional param, which means: invalidate cached pr...
Definition tlb.cc:95
int size
TLB Size.
Definition tlb.hh:131
TlbEntry::KeyType Lookup
Definition tlb.hh:194
void takeOverFrom(BaseTLB *otlb) override
Take over from an old tlb context.
Definition tlb.cc:325
TableWalker * tableWalker
Definition tlb.hh:148
std::set< Addr > observedPageSizes
Set of observed page sizes in the TLB We update the set conservatively, therefore allowing false posi...
Definition tlb.hh:190
void setTableWalker(TableWalker *table_walker)
Definition tlb.cc:143
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:209
void flush(const TLBIOp &tlbi_op)
Flush TLB entries.
Definition tlb.cc:304
void regProbePoints() override
Register probe points for this object.
Definition tlb.cc:388
void printTlb() const
Definition tlb.cc:276
TLB(const Params &p)
Definition tlb.cc:101
virtual ~TLB()
Definition tlb.cc:138
Port * getTableWalkerPort() override
Get the table walker port.
Definition tlb.cc:394
probing::PMUUPtr ppRefills
PMU probe for TLB refills.
Definition tlb.hh:177
bool _walkCache
True if the TLB caches partial translations.
Definition tlb.hh:146
gem5::ArmISA::TLB::Table table
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:141
void insert(const Lookup &lookup_data, TlbEntry &pte)
Insert a PTE in the current TLB.
Definition tlb.cc:246
vmid_t vmid
Definition tlb.hh:180
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:232
gem5::ArmISA::TLB::TlbStats stats
TlbEntry * lookup(Lookup lookup_data)
Lookup an entry in the TLB.
Definition tlb.cc:150
enums::ArmLookupLevel LookupLevel
Definition tlb.hh:195
bool isStage2
Indicates this TLB caches IPA->PA translations.
Definition tlb.hh:134
void flushAll() override
Reset the entire TLB.
Definition tlb.cc:286
void multiInsert(const Lookup &lookup_data, TlbEntry &pte)
Insert a PTE in the current TLB and in the higher levels.
Definition tlb.cc:262
BaseTLB(const BaseTLBParams &p)
Definition tlb.hh:61
BaseTLB * nextLevel() const
Definition tlb.hh:127
virtual std::string name() const
Definition named.hh:60
Ports are used to interface objects to each other.
Definition port.hh:62
#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
static const char * regimeToStr(TranslationRegime regime)
Definition types.hh:503
Bitfield< 59, 56 > tlb
Bitfield< 0 > p
ProbePointArg< uint64_t > PMU
PMU probe point.
Definition pmu.hh:59
Units for Stats.
Definition units.hh:113
const FlagsType nozero
Don't print if this is zero.
Definition info.hh:67
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
statistics::Formula writeAccesses
Definition tlb.hh:169
statistics::Formula hits
Definition tlb.hh:171
statistics::Scalar readHits
Definition tlb.hh:160
statistics::Scalar instHits
Definition tlb.hh:158
statistics::Scalar flushedEntries
Definition tlb.hh:166
statistics::Formula misses
Definition tlb.hh:172
statistics::Formula readAccesses
Definition tlb.hh:168
statistics::Formula accesses
Definition tlb.hh:173
statistics::Scalar inserts
Definition tlb.hh:164
statistics::Scalar flushTlb
Definition tlb.hh:165
TlbStats(TLB &parent)
Definition tlb.cc:329
statistics::Scalar readMisses
Definition tlb.hh:161
statistics::Scalar writeHits
Definition tlb.hh:162
statistics::Scalar writeMisses
Definition tlb.hh:163
statistics::Formula instAccesses
Definition tlb.hh:170
statistics::Scalar instMisses
Definition tlb.hh:159
statistics::Scalar partialHits
Definition tlb.hh:157
TranslationRegime regime
Definition pagetable.hh:283
LookupLevel lookupLevel
Definition pagetable.hh:252
Addr pAddr(Addr va) const
Definition pagetable.hh:451
The file contains the definition of a set of TLB Invalidate Instructions.

Generated on Mon May 26 2025 09:19:05 for gem5 by doxygen 1.13.2