table_walker.cc (10024:fc10e1f9f124) table_walker.cc (10037:5cac77888310)
1/*
1/*
2 * Copyright (c) 2010 ARM Limited
2 * Copyright (c) 2010, 2012-2013 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

--- 19 unchanged lines hidden (view full) ---

30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Ali Saidi
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

--- 19 unchanged lines hidden (view full) ---

30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Ali Saidi
38 * Giacomo Gabrielli
38 */
39
40#include "arch/arm/faults.hh"
39 */
40
41#include "arch/arm/faults.hh"
42#include "arch/arm/stage2_mmu.hh"
43#include "arch/arm/system.hh"
41#include "arch/arm/table_walker.hh"
42#include "arch/arm/tlb.hh"
43#include "cpu/base.hh"
44#include "cpu/thread_context.hh"
45#include "debug/Checkpoint.hh"
46#include "debug/Drain.hh"
47#include "debug/TLB.hh"
48#include "debug/TLBVerbose.hh"
49#include "sim/system.hh"
50
51using namespace ArmISA;
52
53TableWalker::TableWalker(const Params *p)
44#include "arch/arm/table_walker.hh"
45#include "arch/arm/tlb.hh"
46#include "cpu/base.hh"
47#include "cpu/thread_context.hh"
48#include "debug/Checkpoint.hh"
49#include "debug/Drain.hh"
50#include "debug/TLB.hh"
51#include "debug/TLBVerbose.hh"
52#include "sim/system.hh"
53
54using namespace ArmISA;
55
56TableWalker::TableWalker(const Params *p)
54 : MemObject(p), port(this, params()->sys), drainManager(NULL),
55 tlb(NULL), currState(NULL), pending(false),
56 masterId(p->sys->getMasterId(name())),
57 : MemObject(p), port(this, p->sys), drainManager(NULL),
58 stage2Mmu(NULL), isStage2(p->is_stage2), tlb(NULL),
59 currState(NULL), pending(false), masterId(p->sys->getMasterId(name())),
57 numSquashable(p->num_squash_per_cycle),
60 numSquashable(p->num_squash_per_cycle),
58 doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this)
61 doL1DescEvent(this), doL2DescEvent(this),
62 doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this),
63 doL3LongDescEvent(this),
64 doProcessEvent(this)
59{
60 sctlr = 0;
65{
66 sctlr = 0;
67
68 // Cache system-level properties
69 if (FullSystem) {
70 armSys = dynamic_cast<ArmSystem *>(p->sys);
71 assert(armSys);
72 haveSecurity = armSys->haveSecurity();
73 _haveLPAE = armSys->haveLPAE();
74 _haveVirtualization = armSys->haveVirtualization();
75 physAddrRange = armSys->physAddrRange();
76 _haveLargeAsid64 = armSys->haveLargeAsid64();
77 } else {
78 armSys = NULL;
79 haveSecurity = _haveLPAE = _haveVirtualization = false;
80 _haveLargeAsid64 = false;
81 physAddrRange = 32;
82 }
83
61}
62
63TableWalker::~TableWalker()
64{
65 ;
66}
67
84}
85
86TableWalker::~TableWalker()
87{
88 ;
89}
90
91TableWalker::WalkerState::WalkerState() : stage2Tran(NULL), l2Desc(l1Desc)
92{
93}
94
68void
69TableWalker::completeDrain()
70{
95void
96TableWalker::completeDrain()
97{
71 if (drainManager && stateQueueL1.empty() && stateQueueL2.empty() &&
98 if (drainManager && stateQueues[L1].empty() && stateQueues[L2].empty() &&
72 pendingQueue.empty()) {
73 setDrainState(Drainable::Drained);
74 DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
75 drainManager->signalDrainDone();
76 drainManager = NULL;
77 }
78}
79
80unsigned int
81TableWalker::drain(DrainManager *dm)
82{
83 unsigned int count = port.drain(dm);
84
99 pendingQueue.empty()) {
100 setDrainState(Drainable::Drained);
101 DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
102 drainManager->signalDrainDone();
103 drainManager = NULL;
104 }
105}
106
107unsigned int
108TableWalker::drain(DrainManager *dm)
109{
110 unsigned int count = port.drain(dm);
111
85 if (stateQueueL1.empty() && stateQueueL2.empty() &&
86 pendingQueue.empty()) {
87 setDrainState(Drainable::Drained);
88 DPRINTF(Drain, "TableWalker free, no need to drain\n");
112 bool state_queues_not_empty = false;
89
113
90 // table walker is drained, but its ports may still need to be drained
91 return count;
92 } else {
114 for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) {
115 if (!stateQueues[i].empty()) {
116 state_queues_not_empty = true;
117 break;
118 }
119 }
120
121 if (state_queues_not_empty || pendingQueue.size()) {
93 drainManager = dm;
94 setDrainState(Drainable::Draining);
95 DPRINTF(Drain, "TableWalker not drained\n");
96
97 // return port drain count plus the table walker itself needs to drain
98 return count + 1;
122 drainManager = dm;
123 setDrainState(Drainable::Draining);
124 DPRINTF(Drain, "TableWalker not drained\n");
125
126 // return port drain count plus the table walker itself needs to drain
127 return count + 1;
128 } else {
129 setDrainState(Drainable::Drained);
130 DPRINTF(Drain, "TableWalker free, no need to drain\n");
99
131
132 // table walker is drained, but its ports may still need to be drained
133 return count;
100 }
101}
102
103void
104TableWalker::drainResume()
105{
106 Drainable::drainResume();
107 if (params()->sys->isTimingMode() && currState) {

--- 7 unchanged lines hidden (view full) ---

115{
116 if (if_name == "port") {
117 return port;
118 }
119 return MemObject::getMasterPort(if_name, idx);
120}
121
122Fault
134 }
135}
136
137void
138TableWalker::drainResume()
139{
140 Drainable::drainResume();
141 if (params()->sys->isTimingMode() && currState) {

--- 7 unchanged lines hidden (view full) ---

149{
150 if (if_name == "port") {
151 return port;
152 }
153 return MemObject::getMasterPort(if_name, idx);
154}
155
156Fault
123TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode,
124 TLB::Translation *_trans, bool _timing, bool _functional)
157TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid,
158 uint8_t _vmid, bool _isHyp, TLB::Mode _mode,
159 TLB::Translation *_trans, bool _timing, bool _functional,
160 bool secure, TLB::ArmTranslationType tranType)
125{
126 assert(!(_functional && _timing));
161{
162 assert(!(_functional && _timing));
163
127 if (!currState) {
128 // For atomic mode, a new WalkerState instance should be only created
129 // once per TLB. For timing mode, a new instance is generated for every
130 // TLB miss.
131 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
132
133 currState = new WalkerState();
134 currState->tableWalker = this;
135 } else if (_timing) {
136 // This is a translation that was completed and then faulted again
137 // because some underlying parameters that affect the translation
138 // changed out from under us (e.g. asid). It will either be a
139 // misprediction, in which case nothing will happen or we'll use
140 // this fault to re-execute the faulting instruction which should clean
141 // up everything.
164 if (!currState) {
165 // For atomic mode, a new WalkerState instance should be only created
166 // once per TLB. For timing mode, a new instance is generated for every
167 // TLB miss.
168 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
169
170 currState = new WalkerState();
171 currState->tableWalker = this;
172 } else if (_timing) {
173 // This is a translation that was completed and then faulted again
174 // because some underlying parameters that affect the translation
175 // changed out from under us (e.g. asid). It will either be a
176 // misprediction, in which case nothing will happen or we'll use
177 // this fault to re-execute the faulting instruction which should clean
178 // up everything.
142 if (currState->vaddr == _req->getVaddr()) {
179 if (currState->vaddr_tainted == _req->getVaddr()) {
143 return new ReExec;
144 }
180 return new ReExec;
181 }
145 panic("currState should always be empty in timing mode!\n");
146 }
147
148 currState->tc = _tc;
182 }
183
184 currState->tc = _tc;
185 currState->aarch64 = opModeIs64(currOpMode(_tc));
186 currState->el = currEL(_tc);
149 currState->transState = _trans;
150 currState->req = _req;
151 currState->fault = NoFault;
187 currState->transState = _trans;
188 currState->req = _req;
189 currState->fault = NoFault;
152 currState->contextId = _cid;
190 currState->asid = _asid;
191 currState->vmid = _vmid;
192 currState->isHyp = _isHyp;
153 currState->timing = _timing;
154 currState->functional = _functional;
155 currState->mode = _mode;
193 currState->timing = _timing;
194 currState->functional = _functional;
195 currState->mode = _mode;
196 currState->tranType = tranType;
197 currState->isSecure = secure;
198 currState->physAddrRange = physAddrRange;
156
157 /** @todo These should be cached or grabbed from cached copies in
158 the TLB, all these miscreg reads are expensive */
199
200 /** @todo These should be cached or grabbed from cached copies in
201 the TLB, all these miscreg reads are expensive */
159 currState->vaddr = currState->req->getVaddr();
160 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR);
202 currState->vaddr_tainted = currState->req->getVaddr();
203 if (currState->aarch64)
204 currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted,
205 currState->tc, currState->el);
206 else
207 currState->vaddr = currState->vaddr_tainted;
208
209 if (currState->aarch64) {
210 switch (currState->el) {
211 case EL0:
212 case EL1:
213 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1);
214 currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL1);
215 break;
216 // @todo: uncomment this to enable Virtualization
217 // case EL2:
218 // assert(haveVirtualization);
219 // currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2);
220 // currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL2);
221 // break;
222 case EL3:
223 assert(haveSecurity);
224 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3);
225 currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL3);
226 break;
227 default:
228 panic("Invalid exception level");
229 break;
230 }
231 } else {
232 currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
233 MISCREG_SCTLR, currState->tc, !currState->isSecure));
234 currState->ttbcr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
235 MISCREG_TTBCR, currState->tc, !currState->isSecure));
236 currState->htcr = currState->tc->readMiscReg(MISCREG_HTCR);
237 currState->hcr = currState->tc->readMiscReg(MISCREG_HCR);
238 currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR);
239 }
161 sctlr = currState->sctlr;
240 sctlr = currState->sctlr;
162 currState->N = currState->tc->readMiscReg(MISCREG_TTBCR);
163
164 currState->isFetch = (currState->mode == TLB::Execute);
165 currState->isWrite = (currState->mode == TLB::Write);
166
241
242 currState->isFetch = (currState->mode == TLB::Execute);
243 currState->isWrite = (currState->mode == TLB::Write);
244
245 // We only do a second stage of translation if we're not secure, or in
246 // hyp mode, the second stage MMU is enabled, and this table walker
247 // instance is the first stage.
248 currState->doingStage2 = false;
249 // @todo: for now disable this in AArch64 (HCR is not set)
250 currState->stage2Req = !currState->aarch64 && currState->hcr.vm &&
251 !isStage2 && !currState->isSecure && !currState->isHyp;
167
252
168 if (!currState->timing)
169 return processWalk();
253 bool long_desc_format = currState->aarch64 ||
254 (_haveLPAE && currState->ttbcr.eae) ||
255 _isHyp || isStage2;
170
256
257 if (long_desc_format) {
258 // Helper variables used for hierarchical permissions
259 currState->secureLookup = currState->isSecure;
260 currState->rwTable = true;
261 currState->userTable = true;
262 currState->xnTable = false;
263 currState->pxnTable = false;
264 }
265
266 if (!currState->timing) {
267 if (currState->aarch64)
268 return processWalkAArch64();
269 else if (long_desc_format)
270 return processWalkLPAE();
271 else
272 return processWalk();
273 }
274
171 if (pending || pendingQueue.size()) {
172 pendingQueue.push_back(currState);
173 currState = NULL;
174 } else {
175 pending = true;
275 if (pending || pendingQueue.size()) {
276 pendingQueue.push_back(currState);
277 currState = NULL;
278 } else {
279 pending = true;
176 return processWalk();
280 if (currState->aarch64)
281 return processWalkAArch64();
282 else if (long_desc_format)
283 return processWalkLPAE();
284 else
285 return processWalk();
177 }
178
179 return NoFault;
180}
181
182void
183TableWalker::processWalkWrapper()
184{
185 assert(!currState);
186 assert(pendingQueue.size());
187 currState = pendingQueue.front();
188
286 }
287
288 return NoFault;
289}
290
291void
292TableWalker::processWalkWrapper()
293{
294 assert(!currState);
295 assert(pendingQueue.size());
296 currState = pendingQueue.front();
297
298 ExceptionLevel target_el = EL0;
299 if (currState->aarch64)
300 target_el = currEL(currState->tc);
301 else
302 target_el = EL1;
303
189 // Check if a previous walk filled this request already
304 // Check if a previous walk filled this request already
190 TlbEntry* te = tlb->lookup(currState->vaddr, currState->contextId, true);
305 // @TODO Should this always be the TLB or should we look in the stage2 TLB?
306 TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid,
307 currState->vmid, currState->isHyp, currState->isSecure, true, false,
308 target_el);
191
192 // Check if we still need to have a walk for this request. If the requesting
193 // instruction has been squashed, or a previous walk has filled the TLB with
194 // a match, we just want to get rid of the walk. The latter could happen
195 // when there are multiple outstanding misses to a single page and a
196 // previous request has been successfully translated.
197 if (!currState->transState->squashed() && !te) {
198 // We've got a valid request, lets process it
199 pending = true;
200 pendingQueue.pop_front();
309
310 // Check if we still need to have a walk for this request. If the requesting
311 // instruction has been squashed, or a previous walk has filled the TLB with
312 // a match, we just want to get rid of the walk. The latter could happen
313 // when there are multiple outstanding misses to a single page and a
314 // previous request has been successfully translated.
315 if (!currState->transState->squashed() && !te) {
316 // We've got a valid request, lets process it
317 pending = true;
318 pendingQueue.pop_front();
201 processWalk();
319 if (currState->aarch64)
320 processWalkAArch64();
321 else if ((_haveLPAE && currState->ttbcr.eae) || currState->isHyp || isStage2)
322 processWalkLPAE();
323 else
324 processWalk();
202 return;
203 }
204
205
206 // If the instruction that we were translating for has been
207 // squashed we shouldn't bother.
208 unsigned num_squashed = 0;
209 ThreadContext *tc = currState->tc;
210 while ((num_squashed < numSquashable) && currState &&
211 (currState->transState->squashed() || te)) {
212 pendingQueue.pop_front();
213 num_squashed++;
214
325 return;
326 }
327
328
329 // If the instruction that we were translating for has been
330 // squashed we shouldn't bother.
331 unsigned num_squashed = 0;
332 ThreadContext *tc = currState->tc;
333 while ((num_squashed < numSquashable) && currState &&
334 (currState->transState->squashed() || te)) {
335 pendingQueue.pop_front();
336 num_squashed++;
337
215 DPRINTF(TLB, "Squashing table walk for address %#x\n", currState->vaddr);
338 DPRINTF(TLB, "Squashing table walk for address %#x\n",
339 currState->vaddr_tainted);
216
217 if (currState->transState->squashed()) {
218 // finish the translation which will delete the translation object
219 currState->transState->finish(new UnimpFault("Squashed Inst"),
220 currState->req, currState->tc, currState->mode);
221 } else {
222 // translate the request now that we know it will work
340
341 if (currState->transState->squashed()) {
342 // finish the translation which will delete the translation object
343 currState->transState->finish(new UnimpFault("Squashed Inst"),
344 currState->req, currState->tc, currState->mode);
345 } else {
346 // translate the request now that we know it will work
223 currState->fault = tlb->translateTiming(currState->req, currState->tc,
224 currState->transState, currState->mode);
347 tlb->translateTiming(currState->req, currState->tc,
348 currState->transState, currState->mode);
349
225 }
226
227 // delete the current request
228 delete currState;
229
230 // peak at the next one
231 if (pendingQueue.size()) {
232 currState = pendingQueue.front();
350 }
351
352 // delete the current request
353 delete currState;
354
355 // peak at the next one
356 if (pendingQueue.size()) {
357 currState = pendingQueue.front();
233 te = tlb->lookup(currState->vaddr, currState->contextId, true);
358 te = tlb->lookup(currState->vaddr, currState->asid,
359 currState->vmid, currState->isHyp, currState->isSecure, true,
360 false, target_el);
234 } else {
235 // Terminate the loop, nothing more to do
236 currState = NULL;
237 }
238 }
239
240 // if we've still got pending translations schedule more work
241 nextWalk(tc);
242 currState = NULL;
243 completeDrain();
244}
245
246Fault
247TableWalker::processWalk()
248{
249 Addr ttbr = 0;
250
251 // If translation isn't enabled, we shouldn't be here
361 } else {
362 // Terminate the loop, nothing more to do
363 currState = NULL;
364 }
365 }
366
367 // if we've still got pending translations schedule more work
368 nextWalk(tc);
369 currState = NULL;
370 completeDrain();
371}
372
373Fault
374TableWalker::processWalk()
375{
376 Addr ttbr = 0;
377
378 // If translation isn't enabled, we shouldn't be here
252 assert(currState->sctlr.m);
379 assert(currState->sctlr.m || isStage2);
253
380
254 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
255 currState->vaddr, currState->N, mbits(currState->vaddr, 31,
256 32-currState->N));
381 DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n",
382 currState->vaddr_tainted, currState->ttbcr, mbits(currState->vaddr, 31,
383 32 - currState->ttbcr.n));
257
384
258 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) {
385 if (currState->ttbcr.n == 0 || !mbits(currState->vaddr, 31,
386 32 - currState->ttbcr.n)) {
259 DPRINTF(TLB, " - Selecting TTBR0\n");
387 DPRINTF(TLB, " - Selecting TTBR0\n");
260 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0);
388 // Check if table walk is allowed when Security Extensions are enabled
389 if (haveSecurity && currState->ttbcr.pd0) {
390 if (currState->isFetch)
391 return new PrefetchAbort(currState->vaddr_tainted,
392 ArmFault::TranslationLL + L1,
393 isStage2,
394 ArmFault::VmsaTran);
395 else
396 return new DataAbort(currState->vaddr_tainted,
397 TlbEntry::DomainType::NoAccess, currState->isWrite,
398 ArmFault::TranslationLL + L1, isStage2,
399 ArmFault::VmsaTran);
400 }
401 ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
402 MISCREG_TTBR0, currState->tc, !currState->isSecure));
261 } else {
262 DPRINTF(TLB, " - Selecting TTBR1\n");
403 } else {
404 DPRINTF(TLB, " - Selecting TTBR1\n");
263 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1);
264 currState->N = 0;
405 // Check if table walk is allowed when Security Extensions are enabled
406 if (haveSecurity && currState->ttbcr.pd1) {
407 if (currState->isFetch)
408 return new PrefetchAbort(currState->vaddr_tainted,
409 ArmFault::TranslationLL + L1,
410 isStage2,
411 ArmFault::VmsaTran);
412 else
413 return new DataAbort(currState->vaddr_tainted,
414 TlbEntry::DomainType::NoAccess, currState->isWrite,
415 ArmFault::TranslationLL + L1, isStage2,
416 ArmFault::VmsaTran);
417 }
418 ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
419 MISCREG_TTBR1, currState->tc, !currState->isSecure));
420 currState->ttbcr.n = 0;
265 }
266
421 }
422
267 Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) |
268 (bits(currState->vaddr,31-currState->N,20) << 2);
269 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr);
423 Addr l1desc_addr = mbits(ttbr, 31, 14 - currState->ttbcr.n) |
424 (bits(currState->vaddr, 31 - currState->ttbcr.n, 20) << 2);
425 DPRINTF(TLB, " - Descriptor at address %#x (%s)\n", l1desc_addr,
426 currState->isSecure ? "s" : "ns");
270
427
271
272 // Trickbox address check
273 Fault f;
428 // Trickbox address check
429 Fault f;
274 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t),
275 currState->isFetch, currState->isWrite, 0, true);
430 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->isSecure,
431 currState->vaddr, sizeof(uint32_t), currState->isFetch,
432 currState->isWrite, TlbEntry::DomainType::NoAccess, L1);
276 if (f) {
433 if (f) {
277 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr);
434 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
278 if (currState->timing) {
279 pending = false;
280 nextWalk(currState->tc);
281 currState = NULL;
282 } else {
283 currState->tc = NULL;
284 currState->req = NULL;
285 }
286 return f;
287 }
288
289 Request::Flags flag = 0;
290 if (currState->sctlr.c == 0) {
291 flag = Request::UNCACHEABLE;
292 }
293
435 if (currState->timing) {
436 pending = false;
437 nextWalk(currState->tc);
438 currState = NULL;
439 } else {
440 currState->tc = NULL;
441 currState->req = NULL;
442 }
443 return f;
444 }
445
446 Request::Flags flag = 0;
447 if (currState->sctlr.c == 0) {
448 flag = Request::UNCACHEABLE;
449 }
450
451 bool delayed;
452 delayed = fetchDescriptor(l1desc_addr, (uint8_t*)&currState->l1Desc.data,
453 sizeof(uint32_t), flag, L1, &doL1DescEvent,
454 &TableWalker::doL1Descriptor);
455 if (!delayed) {
456 f = currState->fault;
457 }
458
459 return f;
460}
461
462Fault
463TableWalker::processWalkLPAE()
464{
465 Addr ttbr, ttbr0_max, ttbr1_min, desc_addr;
466 int tsz, n;
467 LookupLevel start_lookup_level = L1;
468
469 DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x\n",
470 currState->vaddr_tainted, currState->ttbcr);
471
472 Request::Flags flag = 0;
473 if (currState->isSecure)
474 flag.set(Request::SECURE);
475
476 // work out which base address register to use, if in hyp mode we always
477 // use HTTBR
478 if (isStage2) {
479 DPRINTF(TLB, " - Selecting VTTBR (long-desc.)\n");
480 ttbr = currState->tc->readMiscReg(MISCREG_VTTBR);
481 tsz = sext<4>(currState->vtcr.t0sz);
482 start_lookup_level = currState->vtcr.sl0 ? L1 : L2;
483 } else if (currState->isHyp) {
484 DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n");
485 ttbr = currState->tc->readMiscReg(MISCREG_HTTBR);
486 tsz = currState->htcr.t0sz;
487 } else {
488 assert(_haveLPAE && currState->ttbcr.eae);
489
490 // Determine boundaries of TTBR0/1 regions
491 if (currState->ttbcr.t0sz)
492 ttbr0_max = (1ULL << (32 - currState->ttbcr.t0sz)) - 1;
493 else if (currState->ttbcr.t1sz)
494 ttbr0_max = (1ULL << 32) -
495 (1ULL << (32 - currState->ttbcr.t1sz)) - 1;
496 else
497 ttbr0_max = (1ULL << 32) - 1;
498 if (currState->ttbcr.t1sz)
499 ttbr1_min = (1ULL << 32) - (1ULL << (32 - currState->ttbcr.t1sz));
500 else
501 ttbr1_min = (1ULL << (32 - currState->ttbcr.t0sz));
502
503 // The following code snippet selects the appropriate translation table base
504 // address (TTBR0 or TTBR1) and the appropriate starting lookup level
505 // depending on the address range supported by the translation table (ARM
506 // ARM issue C B3.6.4)
507 if (currState->vaddr <= ttbr0_max) {
508 DPRINTF(TLB, " - Selecting TTBR0 (long-desc.)\n");
509 // Check if table walk is allowed
510 if (currState->ttbcr.epd0) {
511 if (currState->isFetch)
512 return new PrefetchAbort(currState->vaddr_tainted,
513 ArmFault::TranslationLL + L1,
514 isStage2,
515 ArmFault::LpaeTran);
516 else
517 return new DataAbort(currState->vaddr_tainted,
518 TlbEntry::DomainType::NoAccess,
519 currState->isWrite,
520 ArmFault::TranslationLL + L1,
521 isStage2,
522 ArmFault::LpaeTran);
523 }
524 ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
525 MISCREG_TTBR0, currState->tc, !currState->isSecure));
526 tsz = currState->ttbcr.t0sz;
527 if (ttbr0_max < (1ULL << 30)) // Upper limit < 1 GB
528 start_lookup_level = L2;
529 } else if (currState->vaddr >= ttbr1_min) {
530 DPRINTF(TLB, " - Selecting TTBR1 (long-desc.)\n");
531 // Check if table walk is allowed
532 if (currState->ttbcr.epd1) {
533 if (currState->isFetch)
534 return new PrefetchAbort(currState->vaddr_tainted,
535 ArmFault::TranslationLL + L1,
536 isStage2,
537 ArmFault::LpaeTran);
538 else
539 return new DataAbort(currState->vaddr_tainted,
540 TlbEntry::DomainType::NoAccess,
541 currState->isWrite,
542 ArmFault::TranslationLL + L1,
543 isStage2,
544 ArmFault::LpaeTran);
545 }
546 ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked(
547 MISCREG_TTBR1, currState->tc, !currState->isSecure));
548 tsz = currState->ttbcr.t1sz;
549 if (ttbr1_min >= (1ULL << 31) + (1ULL << 30)) // Lower limit >= 3 GB
550 start_lookup_level = L2;
551 } else {
552 // Out of boundaries -> translation fault
553 if (currState->isFetch)
554 return new PrefetchAbort(currState->vaddr_tainted,
555 ArmFault::TranslationLL + L1,
556 isStage2,
557 ArmFault::LpaeTran);
558 else
559 return new DataAbort(currState->vaddr_tainted,
560 TlbEntry::DomainType::NoAccess,
561 currState->isWrite, ArmFault::TranslationLL + L1,
562 isStage2, ArmFault::LpaeTran);
563 }
564
565 }
566
567 // Perform lookup (ARM ARM issue C B3.6.6)
568 if (start_lookup_level == L1) {
569 n = 5 - tsz;
570 desc_addr = mbits(ttbr, 39, n) |
571 (bits(currState->vaddr, n + 26, 30) << 3);
572 DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
573 desc_addr, currState->isSecure ? "s" : "ns");
574 } else {
575 // Skip first-level lookup
576 n = (tsz >= 2 ? 14 - tsz : 12);
577 desc_addr = mbits(ttbr, 39, n) |
578 (bits(currState->vaddr, n + 17, 21) << 3);
579 DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n",
580 desc_addr, currState->isSecure ? "s" : "ns");
581 }
582
583 // Trickbox address check
584 Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure,
585 currState->vaddr, sizeof(uint64_t), currState->isFetch,
586 currState->isWrite, TlbEntry::DomainType::NoAccess,
587 start_lookup_level);
588 if (f) {
589 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
590 if (currState->timing) {
591 pending = false;
592 nextWalk(currState->tc);
593 currState = NULL;
594 } else {
595 currState->tc = NULL;
596 currState->req = NULL;
597 }
598 return f;
599 }
600
601 if (currState->sctlr.c == 0) {
602 flag = Request::UNCACHEABLE;
603 }
604
605 if (currState->isSecure)
606 flag.set(Request::SECURE);
607
608 currState->longDesc.lookupLevel = start_lookup_level;
609 currState->longDesc.aarch64 = false;
610 currState->longDesc.largeGrain = false;
611 currState->longDesc.grainSize = 12;
612
613 Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent
614 : (Event *) &doL2LongDescEvent;
615
616 bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data,
617 sizeof(uint64_t), flag, start_lookup_level,
618 event, &TableWalker::doLongDescriptor);
619 if (!delayed) {
620 f = currState->fault;
621 }
622
623 return f;
624}
625
626unsigned
627TableWalker::adjustTableSizeAArch64(unsigned tsz)
628{
629 if (tsz < 25)
630 return 25;
631 if (tsz > 48)
632 return 48;
633 return tsz;
634}
635
636bool
637TableWalker::checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange)
638{
639 return (currPhysAddrRange != MaxPhysAddrRange &&
640 bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange));
641}
642
643Fault
644TableWalker::processWalkAArch64()
645{
646 assert(currState->aarch64);
647
648 DPRINTF(TLB, "Beginning table walk for address %#llx, TTBCR: %#llx\n",
649 currState->vaddr_tainted, currState->ttbcr);
650
651 // Determine TTBR, table size, granule size and phys. address range
652 Addr ttbr = 0;
653 int tsz = 0, ps = 0;
654 bool large_grain = false;
655 bool fault = false;
656 switch (currState->el) {
657 case EL0:
658 case EL1:
659 switch (bits(currState->vaddr, 63,48)) {
660 case 0:
661 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
662 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1);
663 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t0sz);
664 large_grain = currState->ttbcr.tg0;
665 if (bits(currState->vaddr, 63, tsz) != 0x0 ||
666 currState->ttbcr.epd0)
667 fault = true;
668 break;
669 case 0xffff:
670 DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n");
671 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1);
672 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t1sz);
673 large_grain = currState->ttbcr.tg1;
674 if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) ||
675 currState->ttbcr.epd1)
676 fault = true;
677 break;
678 default:
679 // top two bytes must be all 0s or all 1s, else invalid addr
680 fault = true;
681 }
682 ps = currState->ttbcr.ips;
683 break;
684 case EL2:
685 case EL3:
686 switch(bits(currState->vaddr, 63,48)) {
687 case 0:
688 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n");
689 if (currState->el == EL2)
690 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2);
691 else
692 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3);
693 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t0sz);
694 large_grain = currState->ttbcr.tg0;
695 break;
696 default:
697 // invalid addr if top two bytes are not all 0s
698 fault = true;
699 }
700 ps = currState->ttbcr.ps;
701 break;
702 }
703
704 if (fault) {
705 Fault f;
706 if (currState->isFetch)
707 f = new PrefetchAbort(currState->vaddr_tainted,
708 ArmFault::TranslationLL + L0, isStage2,
709 ArmFault::LpaeTran);
710 else
711 f = new DataAbort(currState->vaddr_tainted,
712 TlbEntry::DomainType::NoAccess,
713 currState->isWrite,
714 ArmFault::TranslationLL + L0,
715 isStage2, ArmFault::LpaeTran);
716
717 if (currState->timing) {
718 pending = false;
719 nextWalk(currState->tc);
720 currState = NULL;
721 } else {
722 currState->tc = NULL;
723 currState->req = NULL;
724 }
725 return f;
726
727 }
728
729 // Determine starting lookup level
730 LookupLevel start_lookup_level;
731 int grain_size, stride;
732 if (large_grain) { // 64 KB granule
733 grain_size = 16;
734 stride = grain_size - 3;
735 if (tsz > grain_size + 2 * stride)
736 start_lookup_level = L1;
737 else if (tsz > grain_size + stride)
738 start_lookup_level = L2;
739 else
740 start_lookup_level = L3;
741 } else { // 4 KB granule
742 grain_size = 12;
743 stride = grain_size - 3;
744 if (tsz > grain_size + 3 * stride)
745 start_lookup_level = L0;
746 else if (tsz > grain_size + 2 * stride)
747 start_lookup_level = L1;
748 else
749 start_lookup_level = L2;
750 }
751
752 // Determine table base address
753 int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) -
754 grain_size;
755 Addr base_addr = mbits(ttbr, 47, base_addr_lo);
756
757 // Determine physical address size and raise an Address Size Fault if
758 // necessary
759 int pa_range = decodePhysAddrRange64(ps);
760 // Clamp to lower limit
761 if (pa_range > physAddrRange)
762 currState->physAddrRange = physAddrRange;
763 else
764 currState->physAddrRange = pa_range;
765 if (checkAddrSizeFaultAArch64(base_addr, currState->physAddrRange)) {
766 DPRINTF(TLB, "Address size fault before any lookup\n");
767 Fault f;
768 if (currState->isFetch)
769 f = new PrefetchAbort(currState->vaddr_tainted,
770 ArmFault::AddressSizeLL + start_lookup_level,
771 isStage2,
772 ArmFault::LpaeTran);
773 else
774 f = new DataAbort(currState->vaddr_tainted,
775 TlbEntry::DomainType::NoAccess,
776 currState->isWrite,
777 ArmFault::AddressSizeLL + start_lookup_level,
778 isStage2,
779 ArmFault::LpaeTran);
780
781
782 if (currState->timing) {
783 pending = false;
784 nextWalk(currState->tc);
785 currState = NULL;
786 } else {
787 currState->tc = NULL;
788 currState->req = NULL;
789 }
790 return f;
791
792 }
793
794 // Determine descriptor address
795 Addr desc_addr = base_addr |
796 (bits(currState->vaddr, tsz - 1,
797 stride * (3 - start_lookup_level) + grain_size) << 3);
798
799 // Trickbox address check
800 Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure,
801 currState->vaddr, sizeof(uint64_t), currState->isFetch,
802 currState->isWrite, TlbEntry::DomainType::NoAccess,
803 start_lookup_level);
804 if (f) {
805 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted);
806 if (currState->timing) {
807 pending = false;
808 nextWalk(currState->tc);
809 currState = NULL;
810 } else {
811 currState->tc = NULL;
812 currState->req = NULL;
813 }
814 return f;
815 }
816
817 Request::Flags flag = 0;
818 if (currState->sctlr.c == 0) {
819 flag = Request::UNCACHEABLE;
820 }
821
822 currState->longDesc.lookupLevel = start_lookup_level;
823 currState->longDesc.aarch64 = true;
824 currState->longDesc.largeGrain = large_grain;
825 currState->longDesc.grainSize = grain_size;
826
294 if (currState->timing) {
827 if (currState->timing) {
295 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
296 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data,
828 Event *event;
829 switch (start_lookup_level) {
830 case L0:
831 event = (Event *) &doL0LongDescEvent;
832 break;
833 case L1:
834 event = (Event *) &doL1LongDescEvent;
835 break;
836 case L2:
837 event = (Event *) &doL2LongDescEvent;
838 break;
839 case L3:
840 event = (Event *) &doL3LongDescEvent;
841 break;
842 default:
843 panic("Invalid table lookup level");
844 break;
845 }
846 port.dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), event,
847 (uint8_t*) &currState->longDesc.data,
297 currState->tc->getCpuPtr()->clockPeriod(), flag);
848 currState->tc->getCpuPtr()->clockPeriod(), flag);
298 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before "
299 "adding: %d\n",
300 stateQueueL1.size());
301 stateQueueL1.push_back(currState);
849 DPRINTF(TLBVerbose,
850 "Adding to walker fifo: queue size before adding: %d\n",
851 stateQueues[start_lookup_level].size());
852 stateQueues[start_lookup_level].push_back(currState);
302 currState = NULL;
303 } else if (!currState->functional) {
853 currState = NULL;
854 } else if (!currState->functional) {
304 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
305 NULL, (uint8_t*)&currState->l1Desc.data,
855 port.dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t),
856 NULL, (uint8_t*) &currState->longDesc.data,
306 currState->tc->getCpuPtr()->clockPeriod(), flag);
857 currState->tc->getCpuPtr()->clockPeriod(), flag);
307 doL1Descriptor();
858 doLongDescriptor();
308 f = currState->fault;
309 } else {
859 f = currState->fault;
860 } else {
310 RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId);
311 req->taskId(ContextSwitchTaskId::DMA);
861 RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag,
862 masterId);
312 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
863 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
313 pkt->dataStatic((uint8_t*)&currState->l1Desc.data);
864 pkt->dataStatic((uint8_t*) &currState->longDesc.data);
314 port.sendFunctional(pkt);
865 port.sendFunctional(pkt);
315 doL1Descriptor();
866 doLongDescriptor();
316 delete req;
317 delete pkt;
318 f = currState->fault;
319 }
320
321 return f;
322}
323
324void
325TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
326 uint8_t texcb, bool s)
327{
328 // Note: tc and sctlr local variables are hiding tc and sctrl class
329 // variables
330 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
331 te.shareable = false; // default value
332 te.nonCacheable = false;
867 delete req;
868 delete pkt;
869 f = currState->fault;
870 }
871
872 return f;
873}
874
875void
876TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
877 uint8_t texcb, bool s)
878{
879 // Note: tc and sctlr local variables are hiding tc and sctrl class
880 // variables
881 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
882 te.shareable = false; // default value
883 te.nonCacheable = false;
333 bool outer_shareable = false;
884 te.outerShareable = false;
334 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
335 switch(texcb) {
336 case 0: // Stongly-ordered
337 te.nonCacheable = true;
885 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
886 switch(texcb) {
887 case 0: // Stongly-ordered
888 te.nonCacheable = true;
338 te.mtype = TlbEntry::StronglyOrdered;
889 te.mtype = TlbEntry::MemoryType::StronglyOrdered;
339 te.shareable = true;
340 te.innerAttrs = 1;
341 te.outerAttrs = 0;
342 break;
343 case 1: // Shareable Device
344 te.nonCacheable = true;
890 te.shareable = true;
891 te.innerAttrs = 1;
892 te.outerAttrs = 0;
893 break;
894 case 1: // Shareable Device
895 te.nonCacheable = true;
345 te.mtype = TlbEntry::Device;
896 te.mtype = TlbEntry::MemoryType::Device;
346 te.shareable = true;
347 te.innerAttrs = 3;
348 te.outerAttrs = 0;
349 break;
350 case 2: // Outer and Inner Write-Through, no Write-Allocate
897 te.shareable = true;
898 te.innerAttrs = 3;
899 te.outerAttrs = 0;
900 break;
901 case 2: // Outer and Inner Write-Through, no Write-Allocate
351 te.mtype = TlbEntry::Normal;
902 te.mtype = TlbEntry::MemoryType::Normal;
352 te.shareable = s;
353 te.innerAttrs = 6;
354 te.outerAttrs = bits(texcb, 1, 0);
355 break;
356 case 3: // Outer and Inner Write-Back, no Write-Allocate
903 te.shareable = s;
904 te.innerAttrs = 6;
905 te.outerAttrs = bits(texcb, 1, 0);
906 break;
907 case 3: // Outer and Inner Write-Back, no Write-Allocate
357 te.mtype = TlbEntry::Normal;
908 te.mtype = TlbEntry::MemoryType::Normal;
358 te.shareable = s;
359 te.innerAttrs = 7;
360 te.outerAttrs = bits(texcb, 1, 0);
361 break;
362 case 4: // Outer and Inner Non-cacheable
363 te.nonCacheable = true;
909 te.shareable = s;
910 te.innerAttrs = 7;
911 te.outerAttrs = bits(texcb, 1, 0);
912 break;
913 case 4: // Outer and Inner Non-cacheable
914 te.nonCacheable = true;
364 te.mtype = TlbEntry::Normal;
915 te.mtype = TlbEntry::MemoryType::Normal;
365 te.shareable = s;
366 te.innerAttrs = 0;
367 te.outerAttrs = bits(texcb, 1, 0);
368 break;
369 case 5: // Reserved
370 panic("Reserved texcb value!\n");
371 break;
372 case 6: // Implementation Defined
373 panic("Implementation-defined texcb value!\n");
374 break;
375 case 7: // Outer and Inner Write-Back, Write-Allocate
916 te.shareable = s;
917 te.innerAttrs = 0;
918 te.outerAttrs = bits(texcb, 1, 0);
919 break;
920 case 5: // Reserved
921 panic("Reserved texcb value!\n");
922 break;
923 case 6: // Implementation Defined
924 panic("Implementation-defined texcb value!\n");
925 break;
926 case 7: // Outer and Inner Write-Back, Write-Allocate
376 te.mtype = TlbEntry::Normal;
927 te.mtype = TlbEntry::MemoryType::Normal;
377 te.shareable = s;
378 te.innerAttrs = 5;
379 te.outerAttrs = 1;
380 break;
381 case 8: // Non-shareable Device
382 te.nonCacheable = true;
928 te.shareable = s;
929 te.innerAttrs = 5;
930 te.outerAttrs = 1;
931 break;
932 case 8: // Non-shareable Device
933 te.nonCacheable = true;
383 te.mtype = TlbEntry::Device;
934 te.mtype = TlbEntry::MemoryType::Device;
384 te.shareable = false;
385 te.innerAttrs = 3;
386 te.outerAttrs = 0;
387 break;
388 case 9 ... 15: // Reserved
389 panic("Reserved texcb value!\n");
390 break;
391 case 16 ... 31: // Cacheable Memory
935 te.shareable = false;
936 te.innerAttrs = 3;
937 te.outerAttrs = 0;
938 break;
939 case 9 ... 15: // Reserved
940 panic("Reserved texcb value!\n");
941 break;
942 case 16 ... 31: // Cacheable Memory
392 te.mtype = TlbEntry::Normal;
943 te.mtype = TlbEntry::MemoryType::Normal;
393 te.shareable = s;
394 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
395 te.nonCacheable = true;
396 te.innerAttrs = bits(texcb, 1, 0);
397 te.outerAttrs = bits(texcb, 3, 2);
398 break;
399 default:
400 panic("More than 32 states for 5 bits?\n");
401 }
402 } else {
403 assert(tc);
944 te.shareable = s;
945 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
946 te.nonCacheable = true;
947 te.innerAttrs = bits(texcb, 1, 0);
948 te.outerAttrs = bits(texcb, 3, 2);
949 break;
950 default:
951 panic("More than 32 states for 5 bits?\n");
952 }
953 } else {
954 assert(tc);
404 PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
405 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
955 PRRR prrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_PRRR,
956 currState->tc, !currState->isSecure));
957 NMRR nmrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_NMRR,
958 currState->tc, !currState->isSecure));
406 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
407 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
408 switch(bits(texcb, 2,0)) {
409 case 0:
410 curr_tr = prrr.tr0;
411 curr_ir = nmrr.ir0;
412 curr_or = nmrr.or0;
959 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
960 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
961 switch(bits(texcb, 2,0)) {
962 case 0:
963 curr_tr = prrr.tr0;
964 curr_ir = nmrr.ir0;
965 curr_or = nmrr.or0;
413 outer_shareable = (prrr.nos0 == 0);
966 te.outerShareable = (prrr.nos0 == 0);
414 break;
415 case 1:
416 curr_tr = prrr.tr1;
417 curr_ir = nmrr.ir1;
418 curr_or = nmrr.or1;
967 break;
968 case 1:
969 curr_tr = prrr.tr1;
970 curr_ir = nmrr.ir1;
971 curr_or = nmrr.or1;
419 outer_shareable = (prrr.nos1 == 0);
972 te.outerShareable = (prrr.nos1 == 0);
420 break;
421 case 2:
422 curr_tr = prrr.tr2;
423 curr_ir = nmrr.ir2;
424 curr_or = nmrr.or2;
973 break;
974 case 2:
975 curr_tr = prrr.tr2;
976 curr_ir = nmrr.ir2;
977 curr_or = nmrr.or2;
425 outer_shareable = (prrr.nos2 == 0);
978 te.outerShareable = (prrr.nos2 == 0);
426 break;
427 case 3:
428 curr_tr = prrr.tr3;
429 curr_ir = nmrr.ir3;
430 curr_or = nmrr.or3;
979 break;
980 case 3:
981 curr_tr = prrr.tr3;
982 curr_ir = nmrr.ir3;
983 curr_or = nmrr.or3;
431 outer_shareable = (prrr.nos3 == 0);
984 te.outerShareable = (prrr.nos3 == 0);
432 break;
433 case 4:
434 curr_tr = prrr.tr4;
435 curr_ir = nmrr.ir4;
436 curr_or = nmrr.or4;
985 break;
986 case 4:
987 curr_tr = prrr.tr4;
988 curr_ir = nmrr.ir4;
989 curr_or = nmrr.or4;
437 outer_shareable = (prrr.nos4 == 0);
990 te.outerShareable = (prrr.nos4 == 0);
438 break;
439 case 5:
440 curr_tr = prrr.tr5;
441 curr_ir = nmrr.ir5;
442 curr_or = nmrr.or5;
991 break;
992 case 5:
993 curr_tr = prrr.tr5;
994 curr_ir = nmrr.ir5;
995 curr_or = nmrr.or5;
443 outer_shareable = (prrr.nos5 == 0);
996 te.outerShareable = (prrr.nos5 == 0);
444 break;
445 case 6:
446 panic("Imp defined type\n");
447 case 7:
448 curr_tr = prrr.tr7;
449 curr_ir = nmrr.ir7;
450 curr_or = nmrr.or7;
997 break;
998 case 6:
999 panic("Imp defined type\n");
1000 case 7:
1001 curr_tr = prrr.tr7;
1002 curr_ir = nmrr.ir7;
1003 curr_or = nmrr.or7;
451 outer_shareable = (prrr.nos7 == 0);
1004 te.outerShareable = (prrr.nos7 == 0);
452 break;
453 }
454
455 switch(curr_tr) {
456 case 0:
457 DPRINTF(TLBVerbose, "StronglyOrdered\n");
1005 break;
1006 }
1007
1008 switch(curr_tr) {
1009 case 0:
1010 DPRINTF(TLBVerbose, "StronglyOrdered\n");
458 te.mtype = TlbEntry::StronglyOrdered;
1011 te.mtype = TlbEntry::MemoryType::StronglyOrdered;
459 te.nonCacheable = true;
460 te.innerAttrs = 1;
461 te.outerAttrs = 0;
462 te.shareable = true;
463 break;
464 case 1:
465 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
466 prrr.ds1, prrr.ds0, s);
1012 te.nonCacheable = true;
1013 te.innerAttrs = 1;
1014 te.outerAttrs = 0;
1015 te.shareable = true;
1016 break;
1017 case 1:
1018 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
1019 prrr.ds1, prrr.ds0, s);
467 te.mtype = TlbEntry::Device;
1020 te.mtype = TlbEntry::MemoryType::Device;
468 te.nonCacheable = true;
469 te.innerAttrs = 3;
470 te.outerAttrs = 0;
471 if (prrr.ds1 && s)
472 te.shareable = true;
473 if (prrr.ds0 && !s)
474 te.shareable = true;
475 break;
476 case 2:
477 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
478 prrr.ns1, prrr.ns0, s);
1021 te.nonCacheable = true;
1022 te.innerAttrs = 3;
1023 te.outerAttrs = 0;
1024 if (prrr.ds1 && s)
1025 te.shareable = true;
1026 if (prrr.ds0 && !s)
1027 te.shareable = true;
1028 break;
1029 case 2:
1030 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
1031 prrr.ns1, prrr.ns0, s);
479 te.mtype = TlbEntry::Normal;
1032 te.mtype = TlbEntry::MemoryType::Normal;
480 if (prrr.ns1 && s)
481 te.shareable = true;
482 if (prrr.ns0 && !s)
483 te.shareable = true;
484 break;
485 case 3:
486 panic("Reserved type");
487 }
488
1033 if (prrr.ns1 && s)
1034 te.shareable = true;
1035 if (prrr.ns0 && !s)
1036 te.shareable = true;
1037 break;
1038 case 3:
1039 panic("Reserved type");
1040 }
1041
489 if (te.mtype == TlbEntry::Normal){
1042 if (te.mtype == TlbEntry::MemoryType::Normal){
490 switch(curr_ir) {
491 case 0:
492 te.nonCacheable = true;
493 te.innerAttrs = 0;
494 break;
495 case 1:
496 te.innerAttrs = 5;
497 break;

--- 20 unchanged lines hidden (view full) ---

518 te.outerAttrs = 3;
519 break;
520 }
521 }
522 }
523 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \
524 outerAttrs: %d\n",
525 te.shareable, te.innerAttrs, te.outerAttrs);
1043 switch(curr_ir) {
1044 case 0:
1045 te.nonCacheable = true;
1046 te.innerAttrs = 0;
1047 break;
1048 case 1:
1049 te.innerAttrs = 5;
1050 break;

--- 20 unchanged lines hidden (view full) ---

1071 te.outerAttrs = 3;
1072 break;
1073 }
1074 }
1075 }
1076 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \
1077 outerAttrs: %d\n",
1078 te.shareable, te.innerAttrs, te.outerAttrs);
1079 te.setAttributes(false);
1080}
526
1081
527 /** Formatting for Physical Address Register (PAR)
528 * Only including lower bits (TLB info here)
529 * PAR:
530 * PA [31:12]
531 * Reserved [11]
532 * TLB info [10:1]
533 * NOS [10] (Not Outer Sharable)
534 * NS [9] (Non-Secure)
535 * -- [8] (Implementation Defined)
536 * SH [7] (Sharable)
537 * Inner[6:4](Inner memory attributes)
538 * Outer[3:2](Outer memory attributes)
539 * SS [1] (SuperSection)
540 * F [0] (Fault, Fault Status in [6:1] if faulted)
541 */
542 te.attributes = (
543 ((outer_shareable ? 0:1) << 10) |
544 // TODO: NS Bit
545 ((te.shareable ? 1:0) << 7) |
546 (te.innerAttrs << 4) |
547 (te.outerAttrs << 2)
548 // TODO: Supersection bit
549 // TODO: Fault bit
550 );
1082void
1083TableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te,
1084 LongDescriptor &lDescriptor)
1085{
1086 assert(_haveLPAE);
551
1087
1088 uint8_t attr;
1089 uint8_t sh = lDescriptor.sh();
1090 // Different format and source of attributes if this is a stage 2
1091 // translation
1092 if (isStage2) {
1093 attr = lDescriptor.memAttr();
1094 uint8_t attr_3_2 = (attr >> 2) & 0x3;
1095 uint8_t attr_1_0 = attr & 0x3;
552
1096
1097 DPRINTF(TLBVerbose, "memAttrsLPAE MemAttr:%#x sh:%#x\n", attr, sh);
1098
1099 if (attr_3_2 == 0) {
1100 te.mtype = attr_1_0 == 0 ? TlbEntry::MemoryType::StronglyOrdered
1101 : TlbEntry::MemoryType::Device;
1102 te.outerAttrs = 0;
1103 te.innerAttrs = attr_1_0 == 0 ? 1 : 3;
1104 te.nonCacheable = true;
1105 } else {
1106 te.mtype = TlbEntry::MemoryType::Normal;
1107 te.outerAttrs = attr_3_2 == 1 ? 0 :
1108 attr_3_2 == 2 ? 2 : 1;
1109 te.innerAttrs = attr_1_0 == 1 ? 0 :
1110 attr_1_0 == 2 ? 6 : 5;
1111 te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1);
1112 }
1113 } else {
1114 uint8_t attrIndx = lDescriptor.attrIndx();
1115
1116 // LPAE always uses remapping of memory attributes, irrespective of the
1117 // value of SCTLR.TRE
1118 int reg = attrIndx & 0x4 ? MISCREG_MAIR1 : MISCREG_MAIR0;
1119 reg = flattenMiscRegNsBanked(reg, currState->tc, !currState->isSecure);
1120 uint32_t mair = currState->tc->readMiscReg(reg);
1121 attr = (mair >> (8 * (attrIndx % 4))) & 0xff;
1122 uint8_t attr_7_4 = bits(attr, 7, 4);
1123 uint8_t attr_3_0 = bits(attr, 3, 0);
1124 DPRINTF(TLBVerbose, "memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx, sh, attr);
1125
1126 // Note: the memory subsystem only cares about the 'cacheable' memory
1127 // attribute. The other attributes are only used to fill the PAR register
1128 // accordingly to provide the illusion of full support
1129 te.nonCacheable = false;
1130
1131 switch (attr_7_4) {
1132 case 0x0:
1133 // Strongly-ordered or Device memory
1134 if (attr_3_0 == 0x0)
1135 te.mtype = TlbEntry::MemoryType::StronglyOrdered;
1136 else if (attr_3_0 == 0x4)
1137 te.mtype = TlbEntry::MemoryType::Device;
1138 else
1139 panic("Unpredictable behavior\n");
1140 te.nonCacheable = true;
1141 te.outerAttrs = 0;
1142 break;
1143 case 0x4:
1144 // Normal memory, Outer Non-cacheable
1145 te.mtype = TlbEntry::MemoryType::Normal;
1146 te.outerAttrs = 0;
1147 if (attr_3_0 == 0x4)
1148 // Inner Non-cacheable
1149 te.nonCacheable = true;
1150 else if (attr_3_0 < 0x8)
1151 panic("Unpredictable behavior\n");
1152 break;
1153 case 0x8:
1154 case 0x9:
1155 case 0xa:
1156 case 0xb:
1157 case 0xc:
1158 case 0xd:
1159 case 0xe:
1160 case 0xf:
1161 if (attr_7_4 & 0x4) {
1162 te.outerAttrs = (attr_7_4 & 1) ? 1 : 3;
1163 } else {
1164 te.outerAttrs = 0x2;
1165 }
1166 // Normal memory, Outer Cacheable
1167 te.mtype = TlbEntry::MemoryType::Normal;
1168 if (attr_3_0 != 0x4 && attr_3_0 < 0x8)
1169 panic("Unpredictable behavior\n");
1170 break;
1171 default:
1172 panic("Unpredictable behavior\n");
1173 break;
1174 }
1175
1176 switch (attr_3_0) {
1177 case 0x0:
1178 te.innerAttrs = 0x1;
1179 break;
1180 case 0x4:
1181 te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0;
1182 break;
1183 case 0x8:
1184 case 0x9:
1185 case 0xA:
1186 case 0xB:
1187 te.innerAttrs = 6;
1188 break;
1189 case 0xC:
1190 case 0xD:
1191 case 0xE:
1192 case 0xF:
1193 te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7;
1194 break;
1195 default:
1196 panic("Unpredictable behavior\n");
1197 break;
1198 }
1199 }
1200
1201 te.outerShareable = sh == 2;
1202 te.shareable = (sh & 0x2) ? true : false;
1203 te.setAttributes(true);
1204 te.attributes |= (uint64_t) attr << 56;
553}
554
555void
1205}
1206
1207void
1208TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx,
1209 uint8_t sh)
1210{
1211 DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh);
1212
1213 // Select MAIR
1214 uint64_t mair;
1215 switch (currState->el) {
1216 case EL0:
1217 case EL1:
1218 mair = tc->readMiscReg(MISCREG_MAIR_EL1);
1219 break;
1220 case EL2:
1221 mair = tc->readMiscReg(MISCREG_MAIR_EL2);
1222 break;
1223 case EL3:
1224 mair = tc->readMiscReg(MISCREG_MAIR_EL3);
1225 break;
1226 default:
1227 panic("Invalid exception level");
1228 break;
1229 }
1230
1231 // Select attributes
1232 uint8_t attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx);
1233 uint8_t attr_lo = bits(attr, 3, 0);
1234 uint8_t attr_hi = bits(attr, 7, 4);
1235
1236 // Memory type
1237 te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal;
1238
1239 // Cacheability
1240 te.nonCacheable = false;
1241 if (te.mtype == TlbEntry::MemoryType::Device || // Device memory
1242 attr_hi == 0x8 || // Normal memory, Outer Non-cacheable
1243 attr_lo == 0x8) { // Normal memory, Inner Non-cacheable
1244 te.nonCacheable = true;
1245 }
1246
1247 te.shareable = sh == 2;
1248 te.outerShareable = (sh & 0x2) ? true : false;
1249 // Attributes formatted according to the 64-bit PAR
1250 te.attributes = ((uint64_t) attr << 56) |
1251 (1 << 11) | // LPAE bit
1252 (te.ns << 9) | // NS bit
1253 (sh << 7);
1254}
1255
1256void
556TableWalker::doL1Descriptor()
557{
1257TableWalker::doL1Descriptor()
1258{
1259 if (currState->fault != NoFault) {
1260 return;
1261 }
1262
558 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
1263 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
559 currState->vaddr, currState->l1Desc.data);
1264 currState->vaddr_tainted, currState->l1Desc.data);
560 TlbEntry te;
561
562 switch (currState->l1Desc.type()) {
563 case L1Descriptor::Ignore:
564 case L1Descriptor::Reserved:
565 if (!currState->timing) {
566 currState->tc = NULL;
567 currState->req = NULL;
568 }
569 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
570 if (currState->isFetch)
571 currState->fault =
1265 TlbEntry te;
1266
1267 switch (currState->l1Desc.type()) {
1268 case L1Descriptor::Ignore:
1269 case L1Descriptor::Reserved:
1270 if (!currState->timing) {
1271 currState->tc = NULL;
1272 currState->req = NULL;
1273 }
1274 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
1275 if (currState->isFetch)
1276 currState->fault =
572 new PrefetchAbort(currState->vaddr, ArmFault::Translation0);
1277 new PrefetchAbort(currState->vaddr_tainted,
1278 ArmFault::TranslationLL + L1,
1279 isStage2,
1280 ArmFault::VmsaTran);
573 else
574 currState->fault =
1281 else
1282 currState->fault =
575 new DataAbort(currState->vaddr, 0, currState->isWrite,
576 ArmFault::Translation0);
1283 new DataAbort(currState->vaddr_tainted,
1284 TlbEntry::DomainType::NoAccess,
1285 currState->isWrite,
1286 ArmFault::TranslationLL + L1, isStage2,
1287 ArmFault::VmsaTran);
577 return;
578 case L1Descriptor::Section:
579 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
580 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
581 * enabled if set, do l1.Desc.setAp0() instead of generating
582 * AccessFlag0
583 */
584
1288 return;
1289 case L1Descriptor::Section:
1290 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
1291 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
1292 * enabled if set, do l1.Desc.setAp0() instead of generating
1293 * AccessFlag0
1294 */
1295
585 currState->fault = new DataAbort(currState->vaddr,
586 currState->l1Desc.domain(), currState->isWrite,
587 ArmFault::AccessFlag0);
1296 currState->fault = new DataAbort(currState->vaddr_tainted,
1297 currState->l1Desc.domain(),
1298 currState->isWrite,
1299 ArmFault::AccessFlagLL + L1,
1300 isStage2,
1301 ArmFault::VmsaTran);
588 }
589 if (currState->l1Desc.supersection()) {
590 panic("Haven't implemented supersections\n");
591 }
1302 }
1303 if (currState->l1Desc.supersection()) {
1304 panic("Haven't implemented supersections\n");
1305 }
592 te.N = 20;
593 te.pfn = currState->l1Desc.pfn();
594 te.size = (1<<te.N) - 1;
595 te.global = !currState->l1Desc.global();
596 te.valid = true;
597 te.vpn = currState->vaddr >> te.N;
598 te.sNp = true;
599 te.xn = currState->l1Desc.xn();
600 te.ap = currState->l1Desc.ap();
601 te.domain = currState->l1Desc.domain();
602 te.asid = currState->contextId;
603 memAttrs(currState->tc, te, currState->sctlr,
604 currState->l1Desc.texcb(), currState->l1Desc.shareable());
1306 insertTableEntry(currState->l1Desc, false);
1307 return;
1308 case L1Descriptor::PageTable:
1309 {
1310 Addr l2desc_addr;
1311 l2desc_addr = currState->l1Desc.l2Addr() |
1312 (bits(currState->vaddr, 19, 12) << 2);
1313 DPRINTF(TLB, "L1 descriptor points to page table at: %#x (%s)\n",
1314 l2desc_addr, currState->isSecure ? "s" : "ns");
605
1315
606 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n");
607 DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n",
608 te.N, te.pfn, te.size, te.global, te.valid);
609 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n",
610 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid,
611 te.nonCacheable);
612 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
613 currState->l1Desc.domain(), currState->l1Desc.data,
614 (currState->l1Desc.data >> 5) & 0xF );
1316 // Trickbox address check
1317 currState->fault = tlb->walkTrickBoxCheck(
1318 l2desc_addr, currState->isSecure, currState->vaddr,
1319 sizeof(uint32_t), currState->isFetch, currState->isWrite,
1320 currState->l1Desc.domain(), L2);
615
1321
1322 if (currState->fault) {
1323 if (!currState->timing) {
1324 currState->tc = NULL;
1325 currState->req = NULL;
1326 }
1327 return;
1328 }
1329
1330 Request::Flags flag = 0;
1331 if (currState->isSecure)
1332 flag.set(Request::SECURE);
1333
1334 bool delayed;
1335 delayed = fetchDescriptor(l2desc_addr,
1336 (uint8_t*)&currState->l2Desc.data,
1337 sizeof(uint32_t), flag, -1, &doL2DescEvent,
1338 &TableWalker::doL2Descriptor);
1339 if (delayed) {
1340 currState->delayed = true;
1341 }
1342
1343 return;
1344 }
1345 default:
1346 panic("A new type in a 2 bit field?\n");
1347 }
1348}
1349
1350void
1351TableWalker::doLongDescriptor()
1352{
1353 if (currState->fault != NoFault) {
1354 return;
1355 }
1356
1357 DPRINTF(TLB, "L%d descriptor for %#llx is %#llx (%s)\n",
1358 currState->longDesc.lookupLevel, currState->vaddr_tainted,
1359 currState->longDesc.data,
1360 currState->aarch64 ? "AArch64" : "long-desc.");
1361
1362 if ((currState->longDesc.type() == LongDescriptor::Block) ||
1363 (currState->longDesc.type() == LongDescriptor::Page)) {
1364 DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, pxn: %d, "
1365 "xn: %d, ap: %d, af: %d, type: %d\n",
1366 currState->longDesc.lookupLevel,
1367 currState->longDesc.data,
1368 currState->longDesc.pxn(),
1369 currState->longDesc.xn(),
1370 currState->longDesc.ap(),
1371 currState->longDesc.af(),
1372 currState->longDesc.type());
1373 } else {
1374 DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, type: %d\n",
1375 currState->longDesc.lookupLevel,
1376 currState->longDesc.data,
1377 currState->longDesc.type());
1378 }
1379
1380 TlbEntry te;
1381
1382 switch (currState->longDesc.type()) {
1383 case LongDescriptor::Invalid:
616 if (!currState->timing) {
617 currState->tc = NULL;
618 currState->req = NULL;
619 }
1384 if (!currState->timing) {
1385 currState->tc = NULL;
1386 currState->req = NULL;
1387 }
620 tlb->insert(currState->vaddr, te);
621
1388
1389 DPRINTF(TLB, "L%d descriptor Invalid, causing fault type %d\n",
1390 currState->longDesc.lookupLevel,
1391 ArmFault::TranslationLL + currState->longDesc.lookupLevel);
1392 if (currState->isFetch)
1393 currState->fault = new PrefetchAbort(
1394 currState->vaddr_tainted,
1395 ArmFault::TranslationLL + currState->longDesc.lookupLevel,
1396 isStage2,
1397 ArmFault::LpaeTran);
1398 else
1399 currState->fault = new DataAbort(
1400 currState->vaddr_tainted,
1401 TlbEntry::DomainType::NoAccess,
1402 currState->isWrite,
1403 ArmFault::TranslationLL + currState->longDesc.lookupLevel,
1404 isStage2,
1405 ArmFault::LpaeTran);
622 return;
1406 return;
623 case L1Descriptor::PageTable:
624 Addr l2desc_addr;
625 l2desc_addr = currState->l1Desc.l2Addr() |
626 (bits(currState->vaddr, 19,12) << 2);
627 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n",
628 l2desc_addr);
1407 case LongDescriptor::Block:
1408 case LongDescriptor::Page:
1409 {
1410 bool fault = false;
1411 bool aff = false;
1412 // Check for address size fault
1413 if (checkAddrSizeFaultAArch64(
1414 mbits(currState->longDesc.data, MaxPhysAddrRange - 1,
1415 currState->longDesc.offsetBits()),
1416 currState->physAddrRange)) {
1417 fault = true;
1418 DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n",
1419 currState->longDesc.lookupLevel);
1420 // Check for access fault
1421 } else if (currState->longDesc.af() == 0) {
1422 fault = true;
1423 DPRINTF(TLB, "L%d descriptor causing Access Fault\n",
1424 currState->longDesc.lookupLevel);
1425 aff = true;
1426 }
1427 if (fault) {
1428 if (currState->isFetch)
1429 currState->fault = new PrefetchAbort(
1430 currState->vaddr_tainted,
1431 (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) +
1432 currState->longDesc.lookupLevel,
1433 isStage2,
1434 ArmFault::LpaeTran);
1435 else
1436 currState->fault = new DataAbort(
1437 currState->vaddr_tainted,
1438 TlbEntry::DomainType::NoAccess, currState->isWrite,
1439 (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) +
1440 currState->longDesc.lookupLevel,
1441 isStage2,
1442 ArmFault::LpaeTran);
1443 } else {
1444 insertTableEntry(currState->longDesc, true);
1445 }
1446 }
1447 return;
1448 case LongDescriptor::Table:
1449 {
1450 // Set hierarchical permission flags
1451 currState->secureLookup = currState->secureLookup &&
1452 currState->longDesc.secureTable();
1453 currState->rwTable = currState->rwTable &&
1454 currState->longDesc.rwTable();
1455 currState->userTable = currState->userTable &&
1456 currState->longDesc.userTable();
1457 currState->xnTable = currState->xnTable ||
1458 currState->longDesc.xnTable();
1459 currState->pxnTable = currState->pxnTable ||
1460 currState->longDesc.pxnTable();
629
1461
630 // Trickbox address check
631 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr,
632 sizeof(uint32_t), currState->isFetch, currState->isWrite,
633 currState->l1Desc.domain(), false);
1462 // Set up next level lookup
1463 Addr next_desc_addr = currState->longDesc.nextDescAddr(
1464 currState->vaddr);
634
1465
635 if (currState->fault) {
636 if (!currState->timing) {
637 currState->tc = NULL;
638 currState->req = NULL;
1466 DPRINTF(TLB, "L%d descriptor points to L%d descriptor at: %#x (%s)\n",
1467 currState->longDesc.lookupLevel,
1468 currState->longDesc.lookupLevel + 1,
1469 next_desc_addr,
1470 currState->secureLookup ? "s" : "ns");
1471
1472 // Check for address size fault
1473 if (currState->aarch64 && checkAddrSizeFaultAArch64(
1474 next_desc_addr, currState->physAddrRange)) {
1475 DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n",
1476 currState->longDesc.lookupLevel);
1477 if (currState->isFetch)
1478 currState->fault = new PrefetchAbort(
1479 currState->vaddr_tainted,
1480 ArmFault::AddressSizeLL
1481 + currState->longDesc.lookupLevel,
1482 isStage2,
1483 ArmFault::LpaeTran);
1484 else
1485 currState->fault = new DataAbort(
1486 currState->vaddr_tainted,
1487 TlbEntry::DomainType::NoAccess, currState->isWrite,
1488 ArmFault::AddressSizeLL
1489 + currState->longDesc.lookupLevel,
1490 isStage2,
1491 ArmFault::LpaeTran);
1492 return;
639 }
1493 }
640 return;
641 }
642
1494
1495 // Trickbox address check
1496 currState->fault = tlb->walkTrickBoxCheck(
1497 next_desc_addr, currState->vaddr,
1498 currState->vaddr, sizeof(uint64_t),
1499 currState->isFetch, currState->isWrite,
1500 TlbEntry::DomainType::Client,
1501 toLookupLevel(currState->longDesc.lookupLevel +1));
643
1502
644 if (currState->timing) {
645 currState->delayed = true;
646 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
647 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
648 currState->tc->getCpuPtr()->clockPeriod());
649 } else if (!currState->functional) {
650 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
651 NULL, (uint8_t*)&currState->l2Desc.data,
652 currState->tc->getCpuPtr()->clockPeriod());
653 doL2Descriptor();
654 } else {
655 RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0,
656 masterId);
657 req->taskId(ContextSwitchTaskId::DMA);
658 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
659 pkt->dataStatic((uint8_t*)&currState->l2Desc.data);
660 port.sendFunctional(pkt);
661 doL2Descriptor();
662 delete req;
663 delete pkt;
1503 if (currState->fault) {
1504 if (!currState->timing) {
1505 currState->tc = NULL;
1506 currState->req = NULL;
1507 }
1508 return;
1509 }
1510
1511 Request::Flags flag = 0;
1512 if (currState->secureLookup)
1513 flag.set(Request::SECURE);
1514
1515 currState->longDesc.lookupLevel =
1516 (LookupLevel) (currState->longDesc.lookupLevel + 1);
1517 Event *event = NULL;
1518 switch (currState->longDesc.lookupLevel) {
1519 case L1:
1520 assert(currState->aarch64);
1521 event = &doL1LongDescEvent;
1522 break;
1523 case L2:
1524 event = &doL2LongDescEvent;
1525 break;
1526 case L3:
1527 event = &doL3LongDescEvent;
1528 break;
1529 default:
1530 panic("Wrong lookup level in table walk\n");
1531 break;
1532 }
1533
1534 bool delayed;
1535 delayed = fetchDescriptor(next_desc_addr, (uint8_t*)&currState->longDesc.data,
1536 sizeof(uint64_t), flag, -1, event,
1537 &TableWalker::doLongDescriptor);
1538 if (delayed) {
1539 currState->delayed = true;
1540 }
664 }
665 return;
666 default:
667 panic("A new type in a 2 bit field?\n");
668 }
669}
670
671void
672TableWalker::doL2Descriptor()
673{
1541 }
1542 return;
1543 default:
1544 panic("A new type in a 2 bit field?\n");
1545 }
1546}
1547
1548void
1549TableWalker::doL2Descriptor()
1550{
1551 if (currState->fault != NoFault) {
1552 return;
1553 }
1554
674 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
1555 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
675 currState->vaddr, currState->l2Desc.data);
1556 currState->vaddr_tainted, currState->l2Desc.data);
676 TlbEntry te;
677
678 if (currState->l2Desc.invalid()) {
679 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
680 if (!currState->timing) {
681 currState->tc = NULL;
682 currState->req = NULL;
683 }
684 if (currState->isFetch)
685 currState->fault =
1557 TlbEntry te;
1558
1559 if (currState->l2Desc.invalid()) {
1560 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
1561 if (!currState->timing) {
1562 currState->tc = NULL;
1563 currState->req = NULL;
1564 }
1565 if (currState->isFetch)
1566 currState->fault =
686 new PrefetchAbort(currState->vaddr, ArmFault::Translation1);
1567 new PrefetchAbort(currState->vaddr_tainted,
1568 ArmFault::TranslationLL + L2,
1569 isStage2,
1570 ArmFault::VmsaTran);
687 else
688 currState->fault =
1571 else
1572 currState->fault =
689 new DataAbort(currState->vaddr, currState->l1Desc.domain(),
690 currState->isWrite, ArmFault::Translation1);
1573 new DataAbort(currState->vaddr_tainted, currState->l1Desc.domain(),
1574 currState->isWrite, ArmFault::TranslationLL + L2,
1575 isStage2,
1576 ArmFault::VmsaTran);
691 return;
692 }
693
694 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
695 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
696 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
697 */
1577 return;
1578 }
1579
1580 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
1581 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
1582 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
1583 */
1584 DPRINTF(TLB, "Generating access fault at L2, afe: %d, ap: %d\n",
1585 currState->sctlr.afe, currState->l2Desc.ap());
698
699 currState->fault =
1586
1587 currState->fault =
700 new DataAbort(currState->vaddr, 0, currState->isWrite,
701 ArmFault::AccessFlag1);
702
1588 new DataAbort(currState->vaddr_tainted,
1589 TlbEntry::DomainType::NoAccess, currState->isWrite,
1590 ArmFault::AccessFlagLL + L2, isStage2,
1591 ArmFault::VmsaTran);
703 }
704
1592 }
1593
705 if (currState->l2Desc.large()) {
706 te.N = 16;
707 te.pfn = currState->l2Desc.pfn();
708 } else {
709 te.N = 12;
710 te.pfn = currState->l2Desc.pfn();
711 }
712
713 te.valid = true;
714 te.size = (1 << te.N) - 1;
715 te.asid = currState->contextId;
716 te.sNp = false;
717 te.vpn = currState->vaddr >> te.N;
718 te.global = currState->l2Desc.global();
719 te.xn = currState->l2Desc.xn();
720 te.ap = currState->l2Desc.ap();
721 te.domain = currState->l1Desc.domain();
722 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(),
723 currState->l2Desc.shareable());
724
725 if (!currState->timing) {
726 currState->tc = NULL;
727 currState->req = NULL;
728 }
729 tlb->insert(currState->vaddr, te);
1594 insertTableEntry(currState->l2Desc, false);
730}
731
732void
733TableWalker::doL1DescriptorWrapper()
734{
1595}
1596
1597void
1598TableWalker::doL1DescriptorWrapper()
1599{
735 currState = stateQueueL1.front();
1600 currState = stateQueues[L1].front();
736 currState->delayed = false;
1601 currState->delayed = false;
1602 // if there's a stage2 translation object we don't need it any more
1603 if (currState->stage2Tran) {
1604 delete currState->stage2Tran;
1605 currState->stage2Tran = NULL;
1606 }
737
1607
1608
738 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
739 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data);
740
1609 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
1610 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data);
1611
741 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr);
1612 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr_tainted);
742 doL1Descriptor();
743
1613 doL1Descriptor();
1614
744 stateQueueL1.pop_front();
1615 stateQueues[L1].pop_front();
745 completeDrain();
746 // Check if fault was generated
747 if (currState->fault != NoFault) {
748 currState->transState->finish(currState->fault, currState->req,
749 currState->tc, currState->mode);
750
751 pending = false;
752 nextWalk(currState->tc);
753
754 currState->req = NULL;
755 currState->tc = NULL;
756 currState->delayed = false;
757 delete currState;
758 }
759 else if (!currState->delayed) {
760 // delay is not set so there is no L2 to do
1616 completeDrain();
1617 // Check if fault was generated
1618 if (currState->fault != NoFault) {
1619 currState->transState->finish(currState->fault, currState->req,
1620 currState->tc, currState->mode);
1621
1622 pending = false;
1623 nextWalk(currState->tc);
1624
1625 currState->req = NULL;
1626 currState->tc = NULL;
1627 currState->delayed = false;
1628 delete currState;
1629 }
1630 else if (!currState->delayed) {
1631 // delay is not set so there is no L2 to do
761 DPRINTF(TLBVerbose, "calling translateTiming again\n");
762 currState->fault = tlb->translateTiming(currState->req, currState->tc,
763 currState->transState, currState->mode);
1632 // Don't finish the translation if a stage 2 look up is underway
1633 if (!currState->doingStage2) {
1634 DPRINTF(TLBVerbose, "calling translateTiming again\n");
1635 currState->fault = tlb->translateTiming(currState->req, currState->tc,
1636 currState->transState, currState->mode);
1637 }
764
765 pending = false;
766 nextWalk(currState->tc);
767
768 currState->req = NULL;
769 currState->tc = NULL;
770 currState->delayed = false;
771 delete currState;
772 } else {
773 // need to do L2 descriptor
1638
1639 pending = false;
1640 nextWalk(currState->tc);
1641
1642 currState->req = NULL;
1643 currState->tc = NULL;
1644 currState->delayed = false;
1645 delete currState;
1646 } else {
1647 // need to do L2 descriptor
774 stateQueueL2.push_back(currState);
1648 stateQueues[L2].push_back(currState);
775 }
776 currState = NULL;
777}
778
779void
780TableWalker::doL2DescriptorWrapper()
781{
1649 }
1650 currState = NULL;
1651}
1652
1653void
1654TableWalker::doL2DescriptorWrapper()
1655{
782 currState = stateQueueL2.front();
1656 currState = stateQueues[L2].front();
783 assert(currState->delayed);
1657 assert(currState->delayed);
1658 // if there's a stage2 translation object we don't need it any more
1659 if (currState->stage2Tran) {
1660 delete currState->stage2Tran;
1661 currState->stage2Tran = NULL;
1662 }
784
785 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
1663
1664 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
786 currState->vaddr);
1665 currState->vaddr_tainted);
787 doL2Descriptor();
788
789 // Check if fault was generated
790 if (currState->fault != NoFault) {
791 currState->transState->finish(currState->fault, currState->req,
792 currState->tc, currState->mode);
793 }
794 else {
1666 doL2Descriptor();
1667
1668 // Check if fault was generated
1669 if (currState->fault != NoFault) {
1670 currState->transState->finish(currState->fault, currState->req,
1671 currState->tc, currState->mode);
1672 }
1673 else {
795 DPRINTF(TLBVerbose, "calling translateTiming again\n");
796 currState->fault = tlb->translateTiming(currState->req, currState->tc,
797 currState->transState, currState->mode);
1674 // Don't finish the translation if a stage 2 look up is underway
1675 if (!currState->doingStage2) {
1676 DPRINTF(TLBVerbose, "calling translateTiming again\n");
1677 currState->fault = tlb->translateTiming(currState->req,
1678 currState->tc, currState->transState, currState->mode);
1679 }
798 }
799
800
1680 }
1681
1682
801 stateQueueL2.pop_front();
1683 stateQueues[L2].pop_front();
802 completeDrain();
803 pending = false;
804 nextWalk(currState->tc);
805
806 currState->req = NULL;
807 currState->tc = NULL;
808 currState->delayed = false;
809
810 delete currState;
811 currState = NULL;
812}
813
814void
1684 completeDrain();
1685 pending = false;
1686 nextWalk(currState->tc);
1687
1688 currState->req = NULL;
1689 currState->tc = NULL;
1690 currState->delayed = false;
1691
1692 delete currState;
1693 currState = NULL;
1694}
1695
1696void
1697TableWalker::doL0LongDescriptorWrapper()
1698{
1699 doLongDescriptorWrapper(L0);
1700}
1701
1702void
1703TableWalker::doL1LongDescriptorWrapper()
1704{
1705 doLongDescriptorWrapper(L1);
1706}
1707
1708void
1709TableWalker::doL2LongDescriptorWrapper()
1710{
1711 doLongDescriptorWrapper(L2);
1712}
1713
1714void
1715TableWalker::doL3LongDescriptorWrapper()
1716{
1717 doLongDescriptorWrapper(L3);
1718}
1719
1720void
1721TableWalker::doLongDescriptorWrapper(LookupLevel curr_lookup_level)
1722{
1723 currState = stateQueues[curr_lookup_level].front();
1724 assert(curr_lookup_level == currState->longDesc.lookupLevel);
1725 currState->delayed = false;
1726
1727 // if there's a stage2 translation object we don't need it any more
1728 if (currState->stage2Tran) {
1729 delete currState->stage2Tran;
1730 currState->stage2Tran = NULL;
1731 }
1732
1733 DPRINTF(TLBVerbose, "calling doLongDescriptor for vaddr:%#x\n",
1734 currState->vaddr_tainted);
1735 doLongDescriptor();
1736
1737 stateQueues[curr_lookup_level].pop_front();
1738
1739 if (currState->fault != NoFault) {
1740 // A fault was generated
1741 currState->transState->finish(currState->fault, currState->req,
1742 currState->tc, currState->mode);
1743
1744 pending = false;
1745 nextWalk(currState->tc);
1746
1747 currState->req = NULL;
1748 currState->tc = NULL;
1749 currState->delayed = false;
1750 delete currState;
1751 } else if (!currState->delayed) {
1752 // No additional lookups required
1753 // Don't finish the translation if a stage 2 look up is underway
1754 if (!currState->doingStage2) {
1755 DPRINTF(TLBVerbose, "calling translateTiming again\n");
1756 currState->fault = tlb->translateTiming(currState->req, currState->tc,
1757 currState->transState,
1758 currState->mode);
1759 }
1760
1761 pending = false;
1762 nextWalk(currState->tc);
1763
1764 currState->req = NULL;
1765 currState->tc = NULL;
1766 currState->delayed = false;
1767 delete currState;
1768 } else {
1769 if (curr_lookup_level >= MAX_LOOKUP_LEVELS - 1)
1770 panic("Max. number of lookups already reached in table walk\n");
1771 // Need to perform additional lookups
1772 stateQueues[currState->longDesc.lookupLevel].push_back(currState);
1773 }
1774 currState = NULL;
1775}
1776
1777
1778void
815TableWalker::nextWalk(ThreadContext *tc)
816{
817 if (pendingQueue.size())
818 schedule(doProcessEvent, clockEdge(Cycles(1)));
819}
820
1779TableWalker::nextWalk(ThreadContext *tc)
1780{
1781 if (pendingQueue.size())
1782 schedule(doProcessEvent, clockEdge(Cycles(1)));
1783}
1784
1785bool
1786TableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes,
1787 Request::Flags flags, int queueIndex, Event *event,
1788 void (TableWalker::*doDescriptor)())
1789{
1790 bool isTiming = currState->timing;
821
1791
1792 // do the requests for the page table descriptors have to go through the
1793 // second stage MMU
1794 if (currState->stage2Req) {
1795 Fault fault;
1796 flags = flags | TLB::MustBeOne;
822
1797
1798 if (isTiming) {
1799 Stage2MMU::Stage2Translation *tran = new
1800 Stage2MMU::Stage2Translation(*stage2Mmu, data, event,
1801 currState->vaddr);
1802 currState->stage2Tran = tran;
1803 stage2Mmu->readDataTimed(currState->tc, descAddr, tran, numBytes,
1804 flags, masterId);
1805 fault = tran->fault;
1806 } else {
1807 fault = stage2Mmu->readDataUntimed(currState->tc,
1808 currState->vaddr, descAddr, data, numBytes, flags, masterId,
1809 currState->functional);
1810 }
1811
1812 if (fault != NoFault) {
1813 currState->fault = fault;
1814 }
1815 if (isTiming) {
1816 if (queueIndex >= 0) {
1817 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
1818 stateQueues[queueIndex].size());
1819 stateQueues[queueIndex].push_back(currState);
1820 currState = NULL;
1821 }
1822 } else {
1823 (this->*doDescriptor)();
1824 }
1825 } else {
1826 if (isTiming) {
1827 port.dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data,
1828 currState->tc->getCpuPtr()->clockPeriod(), flags);
1829 if (queueIndex >= 0) {
1830 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
1831 stateQueues[queueIndex].size());
1832 stateQueues[queueIndex].push_back(currState);
1833 currState = NULL;
1834 }
1835 } else if (!currState->functional) {
1836 port.dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data,
1837 currState->tc->getCpuPtr()->clockPeriod(), flags);
1838 (this->*doDescriptor)();
1839 } else {
1840 RequestPtr req = new Request(descAddr, numBytes, flags, masterId);
1841 req->taskId(ContextSwitchTaskId::DMA);
1842 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
1843 pkt->dataStatic(data);
1844 port.sendFunctional(pkt);
1845 (this->*doDescriptor)();
1846 delete req;
1847 delete pkt;
1848 }
1849 }
1850 return (isTiming);
1851}
1852
1853void
1854TableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor)
1855{
1856 TlbEntry te;
1857
1858 // Create and fill a new page table entry
1859 te.valid = true;
1860 te.longDescFormat = longDescriptor;
1861 te.isHyp = currState->isHyp;
1862 te.asid = currState->asid;
1863 te.vmid = currState->vmid;
1864 te.N = descriptor.offsetBits();
1865 te.vpn = currState->vaddr >> te.N;
1866 te.size = (1<<te.N) - 1;
1867 te.pfn = descriptor.pfn();
1868 te.domain = descriptor.domain();
1869 te.lookupLevel = descriptor.lookupLevel;
1870 te.ns = !descriptor.secure(haveSecurity, currState) || isStage2;
1871 te.nstid = !currState->isSecure;
1872 te.xn = descriptor.xn();
1873 if (currState->aarch64)
1874 te.el = currState->el;
1875 else
1876 te.el = 1;
1877
1878 // ASID has no meaning for stage 2 TLB entries, so mark all stage 2 entries
1879 // as global
1880 te.global = descriptor.global(currState) || isStage2;
1881 if (longDescriptor) {
1882 LongDescriptor lDescriptor =
1883 dynamic_cast<LongDescriptor &>(descriptor);
1884
1885 te.xn |= currState->xnTable;
1886 te.pxn = currState->pxnTable || lDescriptor.pxn();
1887 if (isStage2) {
1888 // this is actually the HAP field, but its stored in the same bit
1889 // possitions as the AP field in a stage 1 translation.
1890 te.hap = lDescriptor.ap();
1891 } else {
1892 te.ap = ((!currState->rwTable || descriptor.ap() >> 1) << 1) |
1893 (currState->userTable && (descriptor.ap() & 0x1));
1894 }
1895 if (currState->aarch64)
1896 memAttrsAArch64(currState->tc, te, currState->longDesc.attrIndx(),
1897 currState->longDesc.sh());
1898 else
1899 memAttrsLPAE(currState->tc, te, lDescriptor);
1900 } else {
1901 te.ap = descriptor.ap();
1902 memAttrs(currState->tc, te, currState->sctlr, descriptor.texcb(),
1903 descriptor.shareable());
1904 }
1905
1906 // Debug output
1907 DPRINTF(TLB, descriptor.dbgHeader().c_str());
1908 DPRINTF(TLB, " - N:%d pfn:%#x size:%#x global:%d valid:%d\n",
1909 te.N, te.pfn, te.size, te.global, te.valid);
1910 DPRINTF(TLB, " - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d "
1911 "vmid:%d hyp:%d nc:%d ns:%d\n", te.vpn, te.xn, te.pxn,
1912 te.ap, static_cast<uint8_t>(te.domain), te.asid, te.vmid, te.isHyp,
1913 te.nonCacheable, te.ns);
1914 DPRINTF(TLB, " - domain from L%d desc:%d data:%#x\n",
1915 descriptor.lookupLevel, static_cast<uint8_t>(descriptor.domain()),
1916 descriptor.getRawData());
1917
1918 // Insert the entry into the TLB
1919 tlb->insert(currState->vaddr, te);
1920 if (!currState->timing) {
1921 currState->tc = NULL;
1922 currState->req = NULL;
1923 }
1924}
1925
823ArmISA::TableWalker *
824ArmTableWalkerParams::create()
825{
826 return new ArmISA::TableWalker(this);
827}
828
1926ArmISA::TableWalker *
1927ArmTableWalkerParams::create()
1928{
1929 return new ArmISA::TableWalker(this);
1930}
1931
1932LookupLevel
1933TableWalker::toLookupLevel(uint8_t lookup_level_as_int)
1934{
1935 switch (lookup_level_as_int) {
1936 case L1:
1937 return L1;
1938 case L2:
1939 return L2;
1940 case L3:
1941 return L3;
1942 default:
1943 panic("Invalid lookup level conversion");
1944 }
1945}