table_walker.cc (9015:7f4d25789dc4) table_walker.cc (9152:86c0e6ca5e7c)
1/*
2 * Copyright (c) 2010 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 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
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 */
39
40#include "arch/arm/faults.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"
1/*
2 * Copyright (c) 2010 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 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
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 */
39
40#include "arch/arm/faults.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"
46#include "debug/TLB.hh"
47#include "debug/TLBVerbose.hh"
48#include "sim/system.hh"
49
50using namespace ArmISA;
51
52TableWalker::TableWalker(const Params *p)
53 : MemObject(p), port(this, params()->sys, params()->min_backoff,
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)
54 : MemObject(p), port(this, params()->sys, params()->min_backoff,
54 params()->max_backoff),
55 params()->max_backoff), drainEvent(NULL),
55 tlb(NULL), currState(NULL), pending(false),
56 masterId(p->sys->getMasterId(name())),
57 doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this)
58{
59 sctlr = 0;
60}
61
62TableWalker::~TableWalker()
63{
64 ;
65}
66
56 tlb(NULL), currState(NULL), pending(false),
57 masterId(p->sys->getMasterId(name())),
58 doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this)
59{
60 sctlr = 0;
61}
62
63TableWalker::~TableWalker()
64{
65 ;
66}
67
68void
69TableWalker::completeDrain()
70{
71 if (drainEvent && stateQueueL1.empty() && stateQueueL2.empty() &&
72 pendingQueue.empty()) {
73 changeState(Drained);
74 DPRINTF(Drain, "TableWalker done draining, processing drain event\n");
75 drainEvent->process();
76 drainEvent = NULL;
77 }
78}
79
67unsigned int
68TableWalker::drain(Event *de)
69{
80unsigned int
81TableWalker::drain(Event *de)
82{
70 if (stateQueueL1.size() || stateQueueL2.size() || pendingQueue.size())
71 {
83 unsigned int count = port.drain(de);
84
85 if (stateQueueL1.empty() && stateQueueL2.empty() &&
86 pendingQueue.empty()) {
87 changeState(Drained);
88 DPRINTF(Drain, "TableWalker free, no need to drain\n");
89
90 // table walker is drained, but its ports may still need to be drained
91 return count;
92 } else {
93 drainEvent = de;
72 changeState(Draining);
94 changeState(Draining);
73 DPRINTF(Checkpoint, "TableWalker busy, wait to drain\n");
74 return 1;
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;
99
75 }
100 }
76 else
77 {
78 changeState(Drained);
79 DPRINTF(Checkpoint, "TableWalker free, no need to drain\n");
80 return 0;
81 }
82}
83
84void
85TableWalker::resume()
86{
87 MemObject::resume();
88 if ((params()->sys->getMemoryMode() == Enums::timing) && currState) {
101}
102
103void
104TableWalker::resume()
105{
106 MemObject::resume();
107 if ((params()->sys->getMemoryMode() == Enums::timing) && currState) {
89 delete currState;
90 currState = NULL;
108 delete currState;
109 currState = NULL;
91 }
92}
93
94MasterPort&
95TableWalker::getMasterPort(const std::string &if_name, int idx)
96{
97 if (if_name == "port") {
98 return port;
99 }
100 return MemObject::getMasterPort(if_name, idx);
101}
102
103Fault
104TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode,
105 TLB::Translation *_trans, bool _timing, bool _functional)
106{
107 assert(!(_functional && _timing));
108 if (!currState) {
109 // For atomic mode, a new WalkerState instance should be only created
110 // once per TLB. For timing mode, a new instance is generated for every
111 // TLB miss.
112 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
113
114 currState = new WalkerState();
115 currState->tableWalker = this;
116 } else if (_timing) {
117 // This is a translation that was completed and then faulted again
118 // because some underlying parameters that affect the translation
119 // changed out from under us (e.g. asid). It will either be a
120 // misprediction, in which case nothing will happen or we'll use
121 // this fault to re-execute the faulting instruction which should clean
122 // up everything.
123 if (currState->vaddr == _req->getVaddr()) {
124 return new ReExec;
125 }
126 panic("currState should always be empty in timing mode!\n");
127 }
128
129 currState->tc = _tc;
130 currState->transState = _trans;
131 currState->req = _req;
132 currState->fault = NoFault;
133 currState->contextId = _cid;
134 currState->timing = _timing;
135 currState->functional = _functional;
136 currState->mode = _mode;
137
138 /** @todo These should be cached or grabbed from cached copies in
139 the TLB, all these miscreg reads are expensive */
140 currState->vaddr = currState->req->getVaddr();
141 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR);
142 sctlr = currState->sctlr;
143 currState->N = currState->tc->readMiscReg(MISCREG_TTBCR);
144
145 currState->isFetch = (currState->mode == TLB::Execute);
146 currState->isWrite = (currState->mode == TLB::Write);
147
148
149 if (!currState->timing)
150 return processWalk();
151
152 if (pending || pendingQueue.size()) {
153 pendingQueue.push_back(currState);
154 currState = NULL;
155 } else {
156 pending = true;
157 return processWalk();
158 }
159
160 return NoFault;
161}
162
163void
164TableWalker::processWalkWrapper()
165{
166 assert(!currState);
167 assert(pendingQueue.size());
168 currState = pendingQueue.front();
169 pendingQueue.pop_front();
170 pending = true;
171 processWalk();
172}
173
174Fault
175TableWalker::processWalk()
176{
177 Addr ttbr = 0;
178
179 // If translation isn't enabled, we shouldn't be here
180 assert(currState->sctlr.m);
181
182 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
183 currState->vaddr, currState->N, mbits(currState->vaddr, 31,
184 32-currState->N));
185
186 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) {
187 DPRINTF(TLB, " - Selecting TTBR0\n");
188 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0);
189 } else {
190 DPRINTF(TLB, " - Selecting TTBR1\n");
191 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1);
192 currState->N = 0;
193 }
194
195 Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) |
196 (bits(currState->vaddr,31-currState->N,20) << 2);
197 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr);
198
199
200 // Trickbox address check
201 Fault f;
202 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t),
203 currState->isFetch, currState->isWrite, 0, true);
204 if (f) {
205 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr);
206 if (currState->timing) {
207 pending = false;
208 nextWalk(currState->tc);
209 currState = NULL;
210 } else {
211 currState->tc = NULL;
212 currState->req = NULL;
213 }
214 return f;
215 }
216
217 Request::Flags flag = 0;
218 if (currState->sctlr.c == 0) {
219 flag = Request::UNCACHEABLE;
220 }
221
222 if (currState->timing) {
223 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
224 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data,
225 currState->tc->getCpuPtr()->ticks(1), flag);
226 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
227 stateQueueL1.size());
228 stateQueueL1.push_back(currState);
229 currState = NULL;
230 } else if (!currState->functional) {
231 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
232 NULL, (uint8_t*)&currState->l1Desc.data,
233 currState->tc->getCpuPtr()->ticks(1), flag);
234 doL1Descriptor();
235 f = currState->fault;
236 } else {
237 RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId);
238 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
239 pkt->dataStatic((uint8_t*)&currState->l1Desc.data);
240 port.sendFunctional(pkt);
241 doL1Descriptor();
242 delete req;
243 delete pkt;
244 f = currState->fault;
245 }
246
247 return f;
248}
249
250void
251TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
252 uint8_t texcb, bool s)
253{
254 // Note: tc and sctlr local variables are hiding tc and sctrl class
255 // variables
256 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
257 te.shareable = false; // default value
258 te.nonCacheable = false;
259 bool outer_shareable = false;
260 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
261 switch(texcb) {
262 case 0: // Stongly-ordered
263 te.nonCacheable = true;
264 te.mtype = TlbEntry::StronglyOrdered;
265 te.shareable = true;
266 te.innerAttrs = 1;
267 te.outerAttrs = 0;
268 break;
269 case 1: // Shareable Device
270 te.nonCacheable = true;
271 te.mtype = TlbEntry::Device;
272 te.shareable = true;
273 te.innerAttrs = 3;
274 te.outerAttrs = 0;
275 break;
276 case 2: // Outer and Inner Write-Through, no Write-Allocate
277 te.mtype = TlbEntry::Normal;
278 te.shareable = s;
279 te.innerAttrs = 6;
280 te.outerAttrs = bits(texcb, 1, 0);
281 break;
282 case 3: // Outer and Inner Write-Back, no Write-Allocate
283 te.mtype = TlbEntry::Normal;
284 te.shareable = s;
285 te.innerAttrs = 7;
286 te.outerAttrs = bits(texcb, 1, 0);
287 break;
288 case 4: // Outer and Inner Non-cacheable
289 te.nonCacheable = true;
290 te.mtype = TlbEntry::Normal;
291 te.shareable = s;
292 te.innerAttrs = 0;
293 te.outerAttrs = bits(texcb, 1, 0);
294 break;
295 case 5: // Reserved
296 panic("Reserved texcb value!\n");
297 break;
298 case 6: // Implementation Defined
299 panic("Implementation-defined texcb value!\n");
300 break;
301 case 7: // Outer and Inner Write-Back, Write-Allocate
302 te.mtype = TlbEntry::Normal;
303 te.shareable = s;
304 te.innerAttrs = 5;
305 te.outerAttrs = 1;
306 break;
307 case 8: // Non-shareable Device
308 te.nonCacheable = true;
309 te.mtype = TlbEntry::Device;
310 te.shareable = false;
311 te.innerAttrs = 3;
312 te.outerAttrs = 0;
313 break;
314 case 9 ... 15: // Reserved
315 panic("Reserved texcb value!\n");
316 break;
317 case 16 ... 31: // Cacheable Memory
318 te.mtype = TlbEntry::Normal;
319 te.shareable = s;
320 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
321 te.nonCacheable = true;
322 te.innerAttrs = bits(texcb, 1, 0);
323 te.outerAttrs = bits(texcb, 3, 2);
324 break;
325 default:
326 panic("More than 32 states for 5 bits?\n");
327 }
328 } else {
329 assert(tc);
330 PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
331 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
332 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
333 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
334 switch(bits(texcb, 2,0)) {
335 case 0:
336 curr_tr = prrr.tr0;
337 curr_ir = nmrr.ir0;
338 curr_or = nmrr.or0;
339 outer_shareable = (prrr.nos0 == 0);
340 break;
341 case 1:
342 curr_tr = prrr.tr1;
343 curr_ir = nmrr.ir1;
344 curr_or = nmrr.or1;
345 outer_shareable = (prrr.nos1 == 0);
346 break;
347 case 2:
348 curr_tr = prrr.tr2;
349 curr_ir = nmrr.ir2;
350 curr_or = nmrr.or2;
351 outer_shareable = (prrr.nos2 == 0);
352 break;
353 case 3:
354 curr_tr = prrr.tr3;
355 curr_ir = nmrr.ir3;
356 curr_or = nmrr.or3;
357 outer_shareable = (prrr.nos3 == 0);
358 break;
359 case 4:
360 curr_tr = prrr.tr4;
361 curr_ir = nmrr.ir4;
362 curr_or = nmrr.or4;
363 outer_shareable = (prrr.nos4 == 0);
364 break;
365 case 5:
366 curr_tr = prrr.tr5;
367 curr_ir = nmrr.ir5;
368 curr_or = nmrr.or5;
369 outer_shareable = (prrr.nos5 == 0);
370 break;
371 case 6:
372 panic("Imp defined type\n");
373 case 7:
374 curr_tr = prrr.tr7;
375 curr_ir = nmrr.ir7;
376 curr_or = nmrr.or7;
377 outer_shareable = (prrr.nos7 == 0);
378 break;
379 }
380
381 switch(curr_tr) {
382 case 0:
383 DPRINTF(TLBVerbose, "StronglyOrdered\n");
384 te.mtype = TlbEntry::StronglyOrdered;
385 te.nonCacheable = true;
386 te.innerAttrs = 1;
387 te.outerAttrs = 0;
388 te.shareable = true;
389 break;
390 case 1:
391 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
392 prrr.ds1, prrr.ds0, s);
393 te.mtype = TlbEntry::Device;
394 te.nonCacheable = true;
395 te.innerAttrs = 3;
396 te.outerAttrs = 0;
397 if (prrr.ds1 && s)
398 te.shareable = true;
399 if (prrr.ds0 && !s)
400 te.shareable = true;
401 break;
402 case 2:
403 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
404 prrr.ns1, prrr.ns0, s);
405 te.mtype = TlbEntry::Normal;
406 if (prrr.ns1 && s)
407 te.shareable = true;
408 if (prrr.ns0 && !s)
409 te.shareable = true;
410 break;
411 case 3:
412 panic("Reserved type");
413 }
414
415 if (te.mtype == TlbEntry::Normal){
416 switch(curr_ir) {
417 case 0:
418 te.nonCacheable = true;
419 te.innerAttrs = 0;
420 break;
421 case 1:
422 te.innerAttrs = 5;
423 break;
424 case 2:
425 te.innerAttrs = 6;
426 break;
427 case 3:
428 te.innerAttrs = 7;
429 break;
430 }
431
432 switch(curr_or) {
433 case 0:
434 te.nonCacheable = true;
435 te.outerAttrs = 0;
436 break;
437 case 1:
438 te.outerAttrs = 1;
439 break;
440 case 2:
441 te.outerAttrs = 2;
442 break;
443 case 3:
444 te.outerAttrs = 3;
445 break;
446 }
447 }
448 }
449 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \
450 outerAttrs: %d\n",
451 te.shareable, te.innerAttrs, te.outerAttrs);
452
453 /** Formatting for Physical Address Register (PAR)
454 * Only including lower bits (TLB info here)
455 * PAR:
456 * PA [31:12]
457 * Reserved [11]
458 * TLB info [10:1]
459 * NOS [10] (Not Outer Sharable)
460 * NS [9] (Non-Secure)
461 * -- [8] (Implementation Defined)
462 * SH [7] (Sharable)
463 * Inner[6:4](Inner memory attributes)
464 * Outer[3:2](Outer memory attributes)
465 * SS [1] (SuperSection)
466 * F [0] (Fault, Fault Status in [6:1] if faulted)
467 */
468 te.attributes = (
469 ((outer_shareable ? 0:1) << 10) |
470 // TODO: NS Bit
471 ((te.shareable ? 1:0) << 7) |
472 (te.innerAttrs << 4) |
473 (te.outerAttrs << 2)
474 // TODO: Supersection bit
475 // TODO: Fault bit
476 );
477
478
479}
480
481void
482TableWalker::doL1Descriptor()
483{
484 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
485 currState->vaddr, currState->l1Desc.data);
486 TlbEntry te;
487
488 switch (currState->l1Desc.type()) {
489 case L1Descriptor::Ignore:
490 case L1Descriptor::Reserved:
491 if (!currState->timing) {
492 currState->tc = NULL;
493 currState->req = NULL;
494 }
495 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
496 if (currState->isFetch)
497 currState->fault =
498 new PrefetchAbort(currState->vaddr, ArmFault::Translation0);
499 else
500 currState->fault =
501 new DataAbort(currState->vaddr, 0, currState->isWrite,
502 ArmFault::Translation0);
503 return;
504 case L1Descriptor::Section:
505 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
506 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
507 * enabled if set, do l1.Desc.setAp0() instead of generating
508 * AccessFlag0
509 */
510
511 currState->fault = new DataAbort(currState->vaddr,
512 currState->l1Desc.domain(), currState->isWrite,
513 ArmFault::AccessFlag0);
514 }
515 if (currState->l1Desc.supersection()) {
516 panic("Haven't implemented supersections\n");
517 }
518 te.N = 20;
519 te.pfn = currState->l1Desc.pfn();
520 te.size = (1<<te.N) - 1;
521 te.global = !currState->l1Desc.global();
522 te.valid = true;
523 te.vpn = currState->vaddr >> te.N;
524 te.sNp = true;
525 te.xn = currState->l1Desc.xn();
526 te.ap = currState->l1Desc.ap();
527 te.domain = currState->l1Desc.domain();
528 te.asid = currState->contextId;
529 memAttrs(currState->tc, te, currState->sctlr,
530 currState->l1Desc.texcb(), currState->l1Desc.shareable());
531
532 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n");
533 DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n",
534 te.N, te.pfn, te.size, te.global, te.valid);
535 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n",
536 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid,
537 te.nonCacheable);
538 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
539 currState->l1Desc.domain(), currState->l1Desc.data,
540 (currState->l1Desc.data >> 5) & 0xF );
541
542 if (!currState->timing) {
543 currState->tc = NULL;
544 currState->req = NULL;
545 }
546 tlb->insert(currState->vaddr, te);
547
548 return;
549 case L1Descriptor::PageTable:
550 Addr l2desc_addr;
551 l2desc_addr = currState->l1Desc.l2Addr() |
552 (bits(currState->vaddr, 19,12) << 2);
553 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n",
554 l2desc_addr);
555
556 // Trickbox address check
557 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr,
558 sizeof(uint32_t), currState->isFetch, currState->isWrite,
559 currState->l1Desc.domain(), false);
560
561 if (currState->fault) {
562 if (!currState->timing) {
563 currState->tc = NULL;
564 currState->req = NULL;
565 }
566 return;
567 }
568
569
570 if (currState->timing) {
571 currState->delayed = true;
572 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
573 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
574 currState->tc->getCpuPtr()->ticks(1));
575 } else if (!currState->functional) {
576 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
577 NULL, (uint8_t*)&currState->l2Desc.data,
578 currState->tc->getCpuPtr()->ticks(1));
579 doL2Descriptor();
580 } else {
581 RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0,
582 masterId);
583 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
584 pkt->dataStatic((uint8_t*)&currState->l2Desc.data);
585 port.sendFunctional(pkt);
586 doL2Descriptor();
587 delete req;
588 delete pkt;
589 }
590 return;
591 default:
592 panic("A new type in a 2 bit field?\n");
593 }
594}
595
596void
597TableWalker::doL2Descriptor()
598{
599 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
600 currState->vaddr, currState->l2Desc.data);
601 TlbEntry te;
602
603 if (currState->l2Desc.invalid()) {
604 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
605 if (!currState->timing) {
606 currState->tc = NULL;
607 currState->req = NULL;
608 }
609 if (currState->isFetch)
610 currState->fault =
611 new PrefetchAbort(currState->vaddr, ArmFault::Translation1);
612 else
613 currState->fault =
614 new DataAbort(currState->vaddr, currState->l1Desc.domain(),
615 currState->isWrite, ArmFault::Translation1);
616 return;
617 }
618
619 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
620 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
621 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
622 */
623
624 currState->fault =
625 new DataAbort(currState->vaddr, 0, currState->isWrite,
626 ArmFault::AccessFlag1);
627
628 }
629
630 if (currState->l2Desc.large()) {
631 te.N = 16;
632 te.pfn = currState->l2Desc.pfn();
633 } else {
634 te.N = 12;
635 te.pfn = currState->l2Desc.pfn();
636 }
637
638 te.valid = true;
639 te.size = (1 << te.N) - 1;
640 te.asid = currState->contextId;
641 te.sNp = false;
642 te.vpn = currState->vaddr >> te.N;
643 te.global = currState->l2Desc.global();
644 te.xn = currState->l2Desc.xn();
645 te.ap = currState->l2Desc.ap();
646 te.domain = currState->l1Desc.domain();
647 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(),
648 currState->l2Desc.shareable());
649
650 if (!currState->timing) {
651 currState->tc = NULL;
652 currState->req = NULL;
653 }
654 tlb->insert(currState->vaddr, te);
655}
656
657void
658TableWalker::doL1DescriptorWrapper()
659{
660 currState = stateQueueL1.front();
661 currState->delayed = false;
662
663 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
664 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data);
665
666 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr);
667 doL1Descriptor();
668
669 stateQueueL1.pop_front();
110 }
111}
112
113MasterPort&
114TableWalker::getMasterPort(const std::string &if_name, int idx)
115{
116 if (if_name == "port") {
117 return port;
118 }
119 return MemObject::getMasterPort(if_name, idx);
120}
121
122Fault
123TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode,
124 TLB::Translation *_trans, bool _timing, bool _functional)
125{
126 assert(!(_functional && _timing));
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.
142 if (currState->vaddr == _req->getVaddr()) {
143 return new ReExec;
144 }
145 panic("currState should always be empty in timing mode!\n");
146 }
147
148 currState->tc = _tc;
149 currState->transState = _trans;
150 currState->req = _req;
151 currState->fault = NoFault;
152 currState->contextId = _cid;
153 currState->timing = _timing;
154 currState->functional = _functional;
155 currState->mode = _mode;
156
157 /** @todo These should be cached or grabbed from cached copies in
158 the TLB, all these miscreg reads are expensive */
159 currState->vaddr = currState->req->getVaddr();
160 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR);
161 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
167
168 if (!currState->timing)
169 return processWalk();
170
171 if (pending || pendingQueue.size()) {
172 pendingQueue.push_back(currState);
173 currState = NULL;
174 } else {
175 pending = true;
176 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 pendingQueue.pop_front();
189 pending = true;
190 processWalk();
191}
192
193Fault
194TableWalker::processWalk()
195{
196 Addr ttbr = 0;
197
198 // If translation isn't enabled, we shouldn't be here
199 assert(currState->sctlr.m);
200
201 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
202 currState->vaddr, currState->N, mbits(currState->vaddr, 31,
203 32-currState->N));
204
205 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) {
206 DPRINTF(TLB, " - Selecting TTBR0\n");
207 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0);
208 } else {
209 DPRINTF(TLB, " - Selecting TTBR1\n");
210 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1);
211 currState->N = 0;
212 }
213
214 Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) |
215 (bits(currState->vaddr,31-currState->N,20) << 2);
216 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr);
217
218
219 // Trickbox address check
220 Fault f;
221 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t),
222 currState->isFetch, currState->isWrite, 0, true);
223 if (f) {
224 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr);
225 if (currState->timing) {
226 pending = false;
227 nextWalk(currState->tc);
228 currState = NULL;
229 } else {
230 currState->tc = NULL;
231 currState->req = NULL;
232 }
233 return f;
234 }
235
236 Request::Flags flag = 0;
237 if (currState->sctlr.c == 0) {
238 flag = Request::UNCACHEABLE;
239 }
240
241 if (currState->timing) {
242 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
243 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data,
244 currState->tc->getCpuPtr()->ticks(1), flag);
245 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
246 stateQueueL1.size());
247 stateQueueL1.push_back(currState);
248 currState = NULL;
249 } else if (!currState->functional) {
250 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
251 NULL, (uint8_t*)&currState->l1Desc.data,
252 currState->tc->getCpuPtr()->ticks(1), flag);
253 doL1Descriptor();
254 f = currState->fault;
255 } else {
256 RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId);
257 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
258 pkt->dataStatic((uint8_t*)&currState->l1Desc.data);
259 port.sendFunctional(pkt);
260 doL1Descriptor();
261 delete req;
262 delete pkt;
263 f = currState->fault;
264 }
265
266 return f;
267}
268
269void
270TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
271 uint8_t texcb, bool s)
272{
273 // Note: tc and sctlr local variables are hiding tc and sctrl class
274 // variables
275 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
276 te.shareable = false; // default value
277 te.nonCacheable = false;
278 bool outer_shareable = false;
279 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
280 switch(texcb) {
281 case 0: // Stongly-ordered
282 te.nonCacheable = true;
283 te.mtype = TlbEntry::StronglyOrdered;
284 te.shareable = true;
285 te.innerAttrs = 1;
286 te.outerAttrs = 0;
287 break;
288 case 1: // Shareable Device
289 te.nonCacheable = true;
290 te.mtype = TlbEntry::Device;
291 te.shareable = true;
292 te.innerAttrs = 3;
293 te.outerAttrs = 0;
294 break;
295 case 2: // Outer and Inner Write-Through, no Write-Allocate
296 te.mtype = TlbEntry::Normal;
297 te.shareable = s;
298 te.innerAttrs = 6;
299 te.outerAttrs = bits(texcb, 1, 0);
300 break;
301 case 3: // Outer and Inner Write-Back, no Write-Allocate
302 te.mtype = TlbEntry::Normal;
303 te.shareable = s;
304 te.innerAttrs = 7;
305 te.outerAttrs = bits(texcb, 1, 0);
306 break;
307 case 4: // Outer and Inner Non-cacheable
308 te.nonCacheable = true;
309 te.mtype = TlbEntry::Normal;
310 te.shareable = s;
311 te.innerAttrs = 0;
312 te.outerAttrs = bits(texcb, 1, 0);
313 break;
314 case 5: // Reserved
315 panic("Reserved texcb value!\n");
316 break;
317 case 6: // Implementation Defined
318 panic("Implementation-defined texcb value!\n");
319 break;
320 case 7: // Outer and Inner Write-Back, Write-Allocate
321 te.mtype = TlbEntry::Normal;
322 te.shareable = s;
323 te.innerAttrs = 5;
324 te.outerAttrs = 1;
325 break;
326 case 8: // Non-shareable Device
327 te.nonCacheable = true;
328 te.mtype = TlbEntry::Device;
329 te.shareable = false;
330 te.innerAttrs = 3;
331 te.outerAttrs = 0;
332 break;
333 case 9 ... 15: // Reserved
334 panic("Reserved texcb value!\n");
335 break;
336 case 16 ... 31: // Cacheable Memory
337 te.mtype = TlbEntry::Normal;
338 te.shareable = s;
339 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
340 te.nonCacheable = true;
341 te.innerAttrs = bits(texcb, 1, 0);
342 te.outerAttrs = bits(texcb, 3, 2);
343 break;
344 default:
345 panic("More than 32 states for 5 bits?\n");
346 }
347 } else {
348 assert(tc);
349 PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
350 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
351 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
352 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
353 switch(bits(texcb, 2,0)) {
354 case 0:
355 curr_tr = prrr.tr0;
356 curr_ir = nmrr.ir0;
357 curr_or = nmrr.or0;
358 outer_shareable = (prrr.nos0 == 0);
359 break;
360 case 1:
361 curr_tr = prrr.tr1;
362 curr_ir = nmrr.ir1;
363 curr_or = nmrr.or1;
364 outer_shareable = (prrr.nos1 == 0);
365 break;
366 case 2:
367 curr_tr = prrr.tr2;
368 curr_ir = nmrr.ir2;
369 curr_or = nmrr.or2;
370 outer_shareable = (prrr.nos2 == 0);
371 break;
372 case 3:
373 curr_tr = prrr.tr3;
374 curr_ir = nmrr.ir3;
375 curr_or = nmrr.or3;
376 outer_shareable = (prrr.nos3 == 0);
377 break;
378 case 4:
379 curr_tr = prrr.tr4;
380 curr_ir = nmrr.ir4;
381 curr_or = nmrr.or4;
382 outer_shareable = (prrr.nos4 == 0);
383 break;
384 case 5:
385 curr_tr = prrr.tr5;
386 curr_ir = nmrr.ir5;
387 curr_or = nmrr.or5;
388 outer_shareable = (prrr.nos5 == 0);
389 break;
390 case 6:
391 panic("Imp defined type\n");
392 case 7:
393 curr_tr = prrr.tr7;
394 curr_ir = nmrr.ir7;
395 curr_or = nmrr.or7;
396 outer_shareable = (prrr.nos7 == 0);
397 break;
398 }
399
400 switch(curr_tr) {
401 case 0:
402 DPRINTF(TLBVerbose, "StronglyOrdered\n");
403 te.mtype = TlbEntry::StronglyOrdered;
404 te.nonCacheable = true;
405 te.innerAttrs = 1;
406 te.outerAttrs = 0;
407 te.shareable = true;
408 break;
409 case 1:
410 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
411 prrr.ds1, prrr.ds0, s);
412 te.mtype = TlbEntry::Device;
413 te.nonCacheable = true;
414 te.innerAttrs = 3;
415 te.outerAttrs = 0;
416 if (prrr.ds1 && s)
417 te.shareable = true;
418 if (prrr.ds0 && !s)
419 te.shareable = true;
420 break;
421 case 2:
422 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
423 prrr.ns1, prrr.ns0, s);
424 te.mtype = TlbEntry::Normal;
425 if (prrr.ns1 && s)
426 te.shareable = true;
427 if (prrr.ns0 && !s)
428 te.shareable = true;
429 break;
430 case 3:
431 panic("Reserved type");
432 }
433
434 if (te.mtype == TlbEntry::Normal){
435 switch(curr_ir) {
436 case 0:
437 te.nonCacheable = true;
438 te.innerAttrs = 0;
439 break;
440 case 1:
441 te.innerAttrs = 5;
442 break;
443 case 2:
444 te.innerAttrs = 6;
445 break;
446 case 3:
447 te.innerAttrs = 7;
448 break;
449 }
450
451 switch(curr_or) {
452 case 0:
453 te.nonCacheable = true;
454 te.outerAttrs = 0;
455 break;
456 case 1:
457 te.outerAttrs = 1;
458 break;
459 case 2:
460 te.outerAttrs = 2;
461 break;
462 case 3:
463 te.outerAttrs = 3;
464 break;
465 }
466 }
467 }
468 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \
469 outerAttrs: %d\n",
470 te.shareable, te.innerAttrs, te.outerAttrs);
471
472 /** Formatting for Physical Address Register (PAR)
473 * Only including lower bits (TLB info here)
474 * PAR:
475 * PA [31:12]
476 * Reserved [11]
477 * TLB info [10:1]
478 * NOS [10] (Not Outer Sharable)
479 * NS [9] (Non-Secure)
480 * -- [8] (Implementation Defined)
481 * SH [7] (Sharable)
482 * Inner[6:4](Inner memory attributes)
483 * Outer[3:2](Outer memory attributes)
484 * SS [1] (SuperSection)
485 * F [0] (Fault, Fault Status in [6:1] if faulted)
486 */
487 te.attributes = (
488 ((outer_shareable ? 0:1) << 10) |
489 // TODO: NS Bit
490 ((te.shareable ? 1:0) << 7) |
491 (te.innerAttrs << 4) |
492 (te.outerAttrs << 2)
493 // TODO: Supersection bit
494 // TODO: Fault bit
495 );
496
497
498}
499
500void
501TableWalker::doL1Descriptor()
502{
503 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
504 currState->vaddr, currState->l1Desc.data);
505 TlbEntry te;
506
507 switch (currState->l1Desc.type()) {
508 case L1Descriptor::Ignore:
509 case L1Descriptor::Reserved:
510 if (!currState->timing) {
511 currState->tc = NULL;
512 currState->req = NULL;
513 }
514 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
515 if (currState->isFetch)
516 currState->fault =
517 new PrefetchAbort(currState->vaddr, ArmFault::Translation0);
518 else
519 currState->fault =
520 new DataAbort(currState->vaddr, 0, currState->isWrite,
521 ArmFault::Translation0);
522 return;
523 case L1Descriptor::Section:
524 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
525 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
526 * enabled if set, do l1.Desc.setAp0() instead of generating
527 * AccessFlag0
528 */
529
530 currState->fault = new DataAbort(currState->vaddr,
531 currState->l1Desc.domain(), currState->isWrite,
532 ArmFault::AccessFlag0);
533 }
534 if (currState->l1Desc.supersection()) {
535 panic("Haven't implemented supersections\n");
536 }
537 te.N = 20;
538 te.pfn = currState->l1Desc.pfn();
539 te.size = (1<<te.N) - 1;
540 te.global = !currState->l1Desc.global();
541 te.valid = true;
542 te.vpn = currState->vaddr >> te.N;
543 te.sNp = true;
544 te.xn = currState->l1Desc.xn();
545 te.ap = currState->l1Desc.ap();
546 te.domain = currState->l1Desc.domain();
547 te.asid = currState->contextId;
548 memAttrs(currState->tc, te, currState->sctlr,
549 currState->l1Desc.texcb(), currState->l1Desc.shareable());
550
551 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n");
552 DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n",
553 te.N, te.pfn, te.size, te.global, te.valid);
554 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n",
555 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid,
556 te.nonCacheable);
557 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
558 currState->l1Desc.domain(), currState->l1Desc.data,
559 (currState->l1Desc.data >> 5) & 0xF );
560
561 if (!currState->timing) {
562 currState->tc = NULL;
563 currState->req = NULL;
564 }
565 tlb->insert(currState->vaddr, te);
566
567 return;
568 case L1Descriptor::PageTable:
569 Addr l2desc_addr;
570 l2desc_addr = currState->l1Desc.l2Addr() |
571 (bits(currState->vaddr, 19,12) << 2);
572 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n",
573 l2desc_addr);
574
575 // Trickbox address check
576 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr,
577 sizeof(uint32_t), currState->isFetch, currState->isWrite,
578 currState->l1Desc.domain(), false);
579
580 if (currState->fault) {
581 if (!currState->timing) {
582 currState->tc = NULL;
583 currState->req = NULL;
584 }
585 return;
586 }
587
588
589 if (currState->timing) {
590 currState->delayed = true;
591 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
592 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
593 currState->tc->getCpuPtr()->ticks(1));
594 } else if (!currState->functional) {
595 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
596 NULL, (uint8_t*)&currState->l2Desc.data,
597 currState->tc->getCpuPtr()->ticks(1));
598 doL2Descriptor();
599 } else {
600 RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0,
601 masterId);
602 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
603 pkt->dataStatic((uint8_t*)&currState->l2Desc.data);
604 port.sendFunctional(pkt);
605 doL2Descriptor();
606 delete req;
607 delete pkt;
608 }
609 return;
610 default:
611 panic("A new type in a 2 bit field?\n");
612 }
613}
614
615void
616TableWalker::doL2Descriptor()
617{
618 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
619 currState->vaddr, currState->l2Desc.data);
620 TlbEntry te;
621
622 if (currState->l2Desc.invalid()) {
623 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
624 if (!currState->timing) {
625 currState->tc = NULL;
626 currState->req = NULL;
627 }
628 if (currState->isFetch)
629 currState->fault =
630 new PrefetchAbort(currState->vaddr, ArmFault::Translation1);
631 else
632 currState->fault =
633 new DataAbort(currState->vaddr, currState->l1Desc.domain(),
634 currState->isWrite, ArmFault::Translation1);
635 return;
636 }
637
638 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
639 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
640 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
641 */
642
643 currState->fault =
644 new DataAbort(currState->vaddr, 0, currState->isWrite,
645 ArmFault::AccessFlag1);
646
647 }
648
649 if (currState->l2Desc.large()) {
650 te.N = 16;
651 te.pfn = currState->l2Desc.pfn();
652 } else {
653 te.N = 12;
654 te.pfn = currState->l2Desc.pfn();
655 }
656
657 te.valid = true;
658 te.size = (1 << te.N) - 1;
659 te.asid = currState->contextId;
660 te.sNp = false;
661 te.vpn = currState->vaddr >> te.N;
662 te.global = currState->l2Desc.global();
663 te.xn = currState->l2Desc.xn();
664 te.ap = currState->l2Desc.ap();
665 te.domain = currState->l1Desc.domain();
666 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(),
667 currState->l2Desc.shareable());
668
669 if (!currState->timing) {
670 currState->tc = NULL;
671 currState->req = NULL;
672 }
673 tlb->insert(currState->vaddr, te);
674}
675
676void
677TableWalker::doL1DescriptorWrapper()
678{
679 currState = stateQueueL1.front();
680 currState->delayed = false;
681
682 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
683 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data);
684
685 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr);
686 doL1Descriptor();
687
688 stateQueueL1.pop_front();
689 completeDrain();
670 // Check if fault was generated
671 if (currState->fault != NoFault) {
672 currState->transState->finish(currState->fault, currState->req,
673 currState->tc, currState->mode);
674
675 pending = false;
676 nextWalk(currState->tc);
677
678 currState->req = NULL;
679 currState->tc = NULL;
680 currState->delayed = false;
681 delete currState;
682 }
683 else if (!currState->delayed) {
684 // delay is not set so there is no L2 to do
685 DPRINTF(TLBVerbose, "calling translateTiming again\n");
686 currState->fault = tlb->translateTiming(currState->req, currState->tc,
687 currState->transState, currState->mode);
688
689 pending = false;
690 nextWalk(currState->tc);
691
692 currState->req = NULL;
693 currState->tc = NULL;
694 currState->delayed = false;
695 delete currState;
696 } else {
697 // need to do L2 descriptor
698 stateQueueL2.push_back(currState);
699 }
700 currState = NULL;
701}
702
703void
704TableWalker::doL2DescriptorWrapper()
705{
706 currState = stateQueueL2.front();
707 assert(currState->delayed);
708
709 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
710 currState->vaddr);
711 doL2Descriptor();
712
713 // Check if fault was generated
714 if (currState->fault != NoFault) {
715 currState->transState->finish(currState->fault, currState->req,
716 currState->tc, currState->mode);
717 }
718 else {
719 DPRINTF(TLBVerbose, "calling translateTiming again\n");
720 currState->fault = tlb->translateTiming(currState->req, currState->tc,
721 currState->transState, currState->mode);
722 }
723
724
725 stateQueueL2.pop_front();
690 // Check if fault was generated
691 if (currState->fault != NoFault) {
692 currState->transState->finish(currState->fault, currState->req,
693 currState->tc, currState->mode);
694
695 pending = false;
696 nextWalk(currState->tc);
697
698 currState->req = NULL;
699 currState->tc = NULL;
700 currState->delayed = false;
701 delete currState;
702 }
703 else if (!currState->delayed) {
704 // delay is not set so there is no L2 to do
705 DPRINTF(TLBVerbose, "calling translateTiming again\n");
706 currState->fault = tlb->translateTiming(currState->req, currState->tc,
707 currState->transState, currState->mode);
708
709 pending = false;
710 nextWalk(currState->tc);
711
712 currState->req = NULL;
713 currState->tc = NULL;
714 currState->delayed = false;
715 delete currState;
716 } else {
717 // need to do L2 descriptor
718 stateQueueL2.push_back(currState);
719 }
720 currState = NULL;
721}
722
723void
724TableWalker::doL2DescriptorWrapper()
725{
726 currState = stateQueueL2.front();
727 assert(currState->delayed);
728
729 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
730 currState->vaddr);
731 doL2Descriptor();
732
733 // Check if fault was generated
734 if (currState->fault != NoFault) {
735 currState->transState->finish(currState->fault, currState->req,
736 currState->tc, currState->mode);
737 }
738 else {
739 DPRINTF(TLBVerbose, "calling translateTiming again\n");
740 currState->fault = tlb->translateTiming(currState->req, currState->tc,
741 currState->transState, currState->mode);
742 }
743
744
745 stateQueueL2.pop_front();
746 completeDrain();
726 pending = false;
727 nextWalk(currState->tc);
728
729 currState->req = NULL;
730 currState->tc = NULL;
731 currState->delayed = false;
732
733 delete currState;
734 currState = NULL;
735}
736
737void
738TableWalker::nextWalk(ThreadContext *tc)
739{
740 if (pendingQueue.size())
741 schedule(doProcessEvent, tc->getCpuPtr()->nextCycle(curTick()+1));
742}
743
744
745
746ArmISA::TableWalker *
747ArmTableWalkerParams::create()
748{
749 return new ArmISA::TableWalker(this);
750}
751
747 pending = false;
748 nextWalk(currState->tc);
749
750 currState->req = NULL;
751 currState->tc = NULL;
752 currState->delayed = false;
753
754 delete currState;
755 currState = NULL;
756}
757
758void
759TableWalker::nextWalk(ThreadContext *tc)
760{
761 if (pendingQueue.size())
762 schedule(doProcessEvent, tc->getCpuPtr()->nextCycle(curTick()+1));
763}
764
765
766
767ArmISA::TableWalker *
768ArmTableWalkerParams::create()
769{
770 return new ArmISA::TableWalker(this);
771}
772