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