Deleted Added
sdiff udiff text old ( 10024:fc10e1f9f124 ) new ( 10037:5cac77888310 )
full compact
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

--- 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 */
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"
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), drainManager(NULL),
55 tlb(NULL), currState(NULL), pending(false),
56 masterId(p->sys->getMasterId(name())),
57 numSquashable(p->num_squash_per_cycle),
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 (drainManager && stateQueueL1.empty() && stateQueueL2.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
85 if (stateQueueL1.empty() && stateQueueL2.empty() &&
86 pendingQueue.empty()) {
87 setDrainState(Drainable::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 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;
99
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
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
189 // Check if a previous walk filled this request already
190 TlbEntry* te = tlb->lookup(currState->vaddr, currState->contextId, true);
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();
201 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
215 DPRINTF(TLB, "Squashing table walk for address %#x\n", currState->vaddr);
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
223 currState->fault = tlb->translateTiming(currState->req, currState->tc,
224 currState->transState, currState->mode);
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();
233 te = tlb->lookup(currState->vaddr, currState->contextId, true);
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
252 assert(currState->sctlr.m);
253
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));
257
258 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) {
259 DPRINTF(TLB, " - Selecting TTBR0\n");
260 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0);
261 } else {
262 DPRINTF(TLB, " - Selecting TTBR1\n");
263 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1);
264 currState->N = 0;
265 }
266
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);
270
271
272 // Trickbox address check
273 Fault f;
274 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t),
275 currState->isFetch, currState->isWrite, 0, true);
276 if (f) {
277 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr);
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
294 if (currState->timing) {
295 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
296 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data,
297 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);
302 currState = NULL;
303 } else if (!currState->functional) {
304 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
305 NULL, (uint8_t*)&currState->l1Desc.data,
306 currState->tc->getCpuPtr()->clockPeriod(), flag);
307 doL1Descriptor();
308 f = currState->fault;
309 } else {
310 RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId);
311 req->taskId(ContextSwitchTaskId::DMA);
312 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
313 pkt->dataStatic((uint8_t*)&currState->l1Desc.data);
314 port.sendFunctional(pkt);
315 doL1Descriptor();
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;
333 bool outer_shareable = false;
334 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
335 switch(texcb) {
336 case 0: // Stongly-ordered
337 te.nonCacheable = true;
338 te.mtype = TlbEntry::StronglyOrdered;
339 te.shareable = true;
340 te.innerAttrs = 1;
341 te.outerAttrs = 0;
342 break;
343 case 1: // Shareable Device
344 te.nonCacheable = true;
345 te.mtype = TlbEntry::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
351 te.mtype = TlbEntry::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
357 te.mtype = TlbEntry::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;
364 te.mtype = TlbEntry::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
376 te.mtype = TlbEntry::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;
383 te.mtype = TlbEntry::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
392 te.mtype = TlbEntry::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);
404 PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
405 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
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;
413 outer_shareable = (prrr.nos0 == 0);
414 break;
415 case 1:
416 curr_tr = prrr.tr1;
417 curr_ir = nmrr.ir1;
418 curr_or = nmrr.or1;
419 outer_shareable = (prrr.nos1 == 0);
420 break;
421 case 2:
422 curr_tr = prrr.tr2;
423 curr_ir = nmrr.ir2;
424 curr_or = nmrr.or2;
425 outer_shareable = (prrr.nos2 == 0);
426 break;
427 case 3:
428 curr_tr = prrr.tr3;
429 curr_ir = nmrr.ir3;
430 curr_or = nmrr.or3;
431 outer_shareable = (prrr.nos3 == 0);
432 break;
433 case 4:
434 curr_tr = prrr.tr4;
435 curr_ir = nmrr.ir4;
436 curr_or = nmrr.or4;
437 outer_shareable = (prrr.nos4 == 0);
438 break;
439 case 5:
440 curr_tr = prrr.tr5;
441 curr_ir = nmrr.ir5;
442 curr_or = nmrr.or5;
443 outer_shareable = (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;
451 outer_shareable = (prrr.nos7 == 0);
452 break;
453 }
454
455 switch(curr_tr) {
456 case 0:
457 DPRINTF(TLBVerbose, "StronglyOrdered\n");
458 te.mtype = TlbEntry::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);
467 te.mtype = TlbEntry::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);
479 te.mtype = TlbEntry::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
489 if (te.mtype == TlbEntry::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);
526
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 );
551
552
553}
554
555void
556TableWalker::doL1Descriptor()
557{
558 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
559 currState->vaddr, 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 =
572 new PrefetchAbort(currState->vaddr, ArmFault::Translation0);
573 else
574 currState->fault =
575 new DataAbort(currState->vaddr, 0, currState->isWrite,
576 ArmFault::Translation0);
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
585 currState->fault = new DataAbort(currState->vaddr,
586 currState->l1Desc.domain(), currState->isWrite,
587 ArmFault::AccessFlag0);
588 }
589 if (currState->l1Desc.supersection()) {
590 panic("Haven't implemented supersections\n");
591 }
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());
605
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 );
615
616 if (!currState->timing) {
617 currState->tc = NULL;
618 currState->req = NULL;
619 }
620 tlb->insert(currState->vaddr, te);
621
622 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);
629
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);
634
635 if (currState->fault) {
636 if (!currState->timing) {
637 currState->tc = NULL;
638 currState->req = NULL;
639 }
640 return;
641 }
642
643
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;
664 }
665 return;
666 default:
667 panic("A new type in a 2 bit field?\n");
668 }
669}
670
671void
672TableWalker::doL2Descriptor()
673{
674 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
675 currState->vaddr, 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 =
686 new PrefetchAbort(currState->vaddr, ArmFault::Translation1);
687 else
688 currState->fault =
689 new DataAbort(currState->vaddr, currState->l1Desc.domain(),
690 currState->isWrite, ArmFault::Translation1);
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 */
698
699 currState->fault =
700 new DataAbort(currState->vaddr, 0, currState->isWrite,
701 ArmFault::AccessFlag1);
702
703 }
704
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);
730}
731
732void
733TableWalker::doL1DescriptorWrapper()
734{
735 currState = stateQueueL1.front();
736 currState->delayed = false;
737
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
741 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr);
742 doL1Descriptor();
743
744 stateQueueL1.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
761 DPRINTF(TLBVerbose, "calling translateTiming again\n");
762 currState->fault = tlb->translateTiming(currState->req, currState->tc,
763 currState->transState, currState->mode);
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
774 stateQueueL2.push_back(currState);
775 }
776 currState = NULL;
777}
778
779void
780TableWalker::doL2DescriptorWrapper()
781{
782 currState = stateQueueL2.front();
783 assert(currState->delayed);
784
785 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
786 currState->vaddr);
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 {
795 DPRINTF(TLBVerbose, "calling translateTiming again\n");
796 currState->fault = tlb->translateTiming(currState->req, currState->tc,
797 currState->transState, currState->mode);
798 }
799
800
801 stateQueueL2.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
815TableWalker::nextWalk(ThreadContext *tc)
816{
817 if (pendingQueue.size())
818 schedule(doProcessEvent, clockEdge(Cycles(1)));
819}
820
821
822
823ArmISA::TableWalker *
824ArmTableWalkerParams::create()
825{
826 return new ArmISA::TableWalker(this);
827}
828