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