2 * Copyright (c) 2010 ARM Limited
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.
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.
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.
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"
51 using namespace ArmISA
;
53 TableWalker::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)
63 TableWalker::~TableWalker()
69 TableWalker::completeDrain()
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();
81 TableWalker::drain(DrainManager
*dm
)
83 unsigned int count
= port
.drain(dm
);
85 if (stateQueueL1
.empty() && stateQueueL2
.empty() &&
86 pendingQueue
.empty()) {
87 setDrainState(Drainable::Drained
);
88 DPRINTF(Drain
, "TableWalker free, no need to drain\n");
90 // table walker is drained, but its ports may still need to be drained
94 setDrainState(Drainable::Draining
);
95 DPRINTF(Drain
, "TableWalker not drained\n");
97 // return port drain count plus the table walker itself needs to drain
104 TableWalker::drainResume()
106 Drainable::drainResume();
107 if (params()->sys
->isTimingMode() && currState
) {
114 TableWalker::getMasterPort(const std::string
&if_name
, PortID idx
)
116 if (if_name
== "port") {
119 return MemObject::getMasterPort(if_name
, idx
);
123 TableWalker::walk(RequestPtr _req
, ThreadContext
*_tc
, uint8_t _cid
, TLB::Mode _mode
,
124 TLB::Translation
*_trans
, bool _timing
, bool _functional
)
126 assert(!(_functional
&& _timing
));
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
131 DPRINTF(TLBVerbose
, "creating new instance of WalkerState\n");
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
142 if (currState
->vaddr
== _req
->getVaddr()) {
145 panic("currState should always be empty in timing mode!\n");
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
;
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
);
164 currState
->isFetch
= (currState
->mode
== TLB::Execute
);
165 currState
->isWrite
= (currState
->mode
== TLB::Write
);
168 if (!currState
->timing
)
169 return processWalk();
171 if (pending
|| pendingQueue
.size()) {
172 pendingQueue
.push_back(currState
);
176 return processWalk();
183 TableWalker::processWalkWrapper()
186 assert(pendingQueue
.size());
187 currState
= pendingQueue
.front();
189 // Check if a previous walk filled this request already
190 TlbEntry
* te
= tlb
->lookup(currState
->vaddr
, currState
->contextId
, true);
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
200 pendingQueue
.pop_front();
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();
215 DPRINTF(TLB
, "Squashing table walk for address %#x\n", currState
->vaddr
);
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
);
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
);
227 // delete the current request
230 // peak at the next one
231 if (pendingQueue
.size()) {
232 currState
= pendingQueue
.front();
233 te
= tlb
->lookup(currState
->vaddr
, currState
->contextId
, true);
235 // Terminate the loop, nothing more to do
240 // if we've still got pending translations schedule more work
247 TableWalker::processWalk()
251 // If translation isn't enabled, we shouldn't be here
252 assert(currState
->sctlr
.m
);
254 DPRINTF(TLB
, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
255 currState
->vaddr
, currState
->N
, mbits(currState
->vaddr
, 31,
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
);
262 DPRINTF(TLB
, " - Selecting TTBR1\n");
263 ttbr
= currState
->tc
->readMiscReg(MISCREG_TTBR1
);
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
);
272 // Trickbox address check
274 f
= tlb
->walkTrickBoxCheck(l1desc_addr
, currState
->vaddr
, sizeof(uint32_t),
275 currState
->isFetch
, currState
->isWrite
, 0, true);
277 DPRINTF(TLB
, "Trickbox check caused fault on %#x\n", currState
->vaddr
);
278 if (currState
->timing
) {
280 nextWalk(currState
->tc
);
283 currState
->tc
= NULL
;
284 currState
->req
= NULL
;
289 Request::Flags flag
= 0;
290 if (currState
->sctlr
.c
== 0) {
291 flag
= Request::UNCACHEABLE
;
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 "
300 stateQueueL1
.size());
301 stateQueueL1
.push_back(currState
);
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
);
308 f
= currState
->fault
;
310 RequestPtr req
= new Request(l1desc_addr
, sizeof(uint32_t), flag
, masterId
);
311 PacketPtr pkt
= new Packet(req
, MemCmd::ReadReq
);
312 pkt
->dataStatic((uint8_t*)&currState
->l1Desc
.data
);
313 port
.sendFunctional(pkt
);
317 f
= currState
->fault
;
324 TableWalker::memAttrs(ThreadContext
*tc
, TlbEntry
&te
, SCTLR sctlr
,
325 uint8_t texcb
, bool s
)
327 // Note: tc and sctlr local variables are hiding tc and sctrl class
329 DPRINTF(TLBVerbose
, "memAttrs texcb:%d s:%d\n", texcb
, s
);
330 te
.shareable
= false; // default value
331 te
.nonCacheable
= false;
332 bool outer_shareable
= false;
333 if (sctlr
.tre
== 0 || ((sctlr
.tre
== 1) && (sctlr
.m
== 0))) {
335 case 0: // Stongly-ordered
336 te
.nonCacheable
= true;
337 te
.mtype
= TlbEntry::StronglyOrdered
;
342 case 1: // Shareable Device
343 te
.nonCacheable
= true;
344 te
.mtype
= TlbEntry::Device
;
349 case 2: // Outer and Inner Write-Through, no Write-Allocate
350 te
.mtype
= TlbEntry::Normal
;
353 te
.outerAttrs
= bits(texcb
, 1, 0);
355 case 3: // Outer and Inner Write-Back, no Write-Allocate
356 te
.mtype
= TlbEntry::Normal
;
359 te
.outerAttrs
= bits(texcb
, 1, 0);
361 case 4: // Outer and Inner Non-cacheable
362 te
.nonCacheable
= true;
363 te
.mtype
= TlbEntry::Normal
;
366 te
.outerAttrs
= bits(texcb
, 1, 0);
369 panic("Reserved texcb value!\n");
371 case 6: // Implementation Defined
372 panic("Implementation-defined texcb value!\n");
374 case 7: // Outer and Inner Write-Back, Write-Allocate
375 te
.mtype
= TlbEntry::Normal
;
380 case 8: // Non-shareable Device
381 te
.nonCacheable
= true;
382 te
.mtype
= TlbEntry::Device
;
383 te
.shareable
= false;
387 case 9 ... 15: // Reserved
388 panic("Reserved texcb value!\n");
390 case 16 ... 31: // Cacheable Memory
391 te
.mtype
= TlbEntry::Normal
;
393 if (bits(texcb
, 1,0) == 0 || bits(texcb
, 3,2) == 0)
394 te
.nonCacheable
= true;
395 te
.innerAttrs
= bits(texcb
, 1, 0);
396 te
.outerAttrs
= bits(texcb
, 3, 2);
399 panic("More than 32 states for 5 bits?\n");
403 PRRR prrr
= tc
->readMiscReg(MISCREG_PRRR
);
404 NMRR nmrr
= tc
->readMiscReg(MISCREG_NMRR
);
405 DPRINTF(TLBVerbose
, "memAttrs PRRR:%08x NMRR:%08x\n", prrr
, nmrr
);
406 uint8_t curr_tr
= 0, curr_ir
= 0, curr_or
= 0;
407 switch(bits(texcb
, 2,0)) {
412 outer_shareable
= (prrr
.nos0
== 0);
418 outer_shareable
= (prrr
.nos1
== 0);
424 outer_shareable
= (prrr
.nos2
== 0);
430 outer_shareable
= (prrr
.nos3
== 0);
436 outer_shareable
= (prrr
.nos4
== 0);
442 outer_shareable
= (prrr
.nos5
== 0);
445 panic("Imp defined type\n");
450 outer_shareable
= (prrr
.nos7
== 0);
456 DPRINTF(TLBVerbose
, "StronglyOrdered\n");
457 te
.mtype
= TlbEntry::StronglyOrdered
;
458 te
.nonCacheable
= true;
464 DPRINTF(TLBVerbose
, "Device ds1:%d ds0:%d s:%d\n",
465 prrr
.ds1
, prrr
.ds0
, s
);
466 te
.mtype
= TlbEntry::Device
;
467 te
.nonCacheable
= true;
476 DPRINTF(TLBVerbose
, "Normal ns1:%d ns0:%d s:%d\n",
477 prrr
.ns1
, prrr
.ns0
, s
);
478 te
.mtype
= TlbEntry::Normal
;
485 panic("Reserved type");
488 if (te
.mtype
== TlbEntry::Normal
){
491 te
.nonCacheable
= true;
507 te
.nonCacheable
= true;
522 DPRINTF(TLBVerbose
, "memAttrs: shareable: %d, innerAttrs: %d, \
524 te
.shareable
, te
.innerAttrs
, te
.outerAttrs
);
526 /** Formatting for Physical Address Register (PAR)
527 * Only including lower bits (TLB info here)
532 * NOS [10] (Not Outer Sharable)
533 * NS [9] (Non-Secure)
534 * -- [8] (Implementation Defined)
536 * Inner[6:4](Inner memory attributes)
537 * Outer[3:2](Outer memory attributes)
538 * SS [1] (SuperSection)
539 * F [0] (Fault, Fault Status in [6:1] if faulted)
542 ((outer_shareable
? 0:1) << 10) |
544 ((te
.shareable
? 1:0) << 7) |
545 (te
.innerAttrs
<< 4) |
547 // TODO: Supersection bit
555 TableWalker::doL1Descriptor()
557 DPRINTF(TLB
, "L1 descriptor for %#x is %#x\n",
558 currState
->vaddr
, currState
->l1Desc
.data
);
561 switch (currState
->l1Desc
.type()) {
562 case L1Descriptor::Ignore
:
563 case L1Descriptor::Reserved
:
564 if (!currState
->timing
) {
565 currState
->tc
= NULL
;
566 currState
->req
= NULL
;
568 DPRINTF(TLB
, "L1 Descriptor Reserved/Ignore, causing fault\n");
569 if (currState
->isFetch
)
571 new PrefetchAbort(currState
->vaddr
, ArmFault::Translation0
);
574 new DataAbort(currState
->vaddr
, 0, currState
->isWrite
,
575 ArmFault::Translation0
);
577 case L1Descriptor::Section
:
578 if (currState
->sctlr
.afe
&& bits(currState
->l1Desc
.ap(), 0) == 0) {
579 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
580 * enabled if set, do l1.Desc.setAp0() instead of generating
584 currState
->fault
= new DataAbort(currState
->vaddr
,
585 currState
->l1Desc
.domain(), currState
->isWrite
,
586 ArmFault::AccessFlag0
);
588 if (currState
->l1Desc
.supersection()) {
589 panic("Haven't implemented supersections\n");
592 te
.pfn
= currState
->l1Desc
.pfn();
593 te
.size
= (1<<te
.N
) - 1;
594 te
.global
= !currState
->l1Desc
.global();
596 te
.vpn
= currState
->vaddr
>> te
.N
;
598 te
.xn
= currState
->l1Desc
.xn();
599 te
.ap
= currState
->l1Desc
.ap();
600 te
.domain
= currState
->l1Desc
.domain();
601 te
.asid
= currState
->contextId
;
602 memAttrs(currState
->tc
, te
, currState
->sctlr
,
603 currState
->l1Desc
.texcb(), currState
->l1Desc
.shareable());
605 DPRINTF(TLB
, "Inserting Section Descriptor into TLB\n");
606 DPRINTF(TLB
, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n",
607 te
.N
, te
.pfn
, te
.size
, te
.global
, te
.valid
);
608 DPRINTF(TLB
, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n",
609 te
.vpn
, te
.sNp
, te
.xn
, te
.ap
, te
.domain
, te
.asid
,
611 DPRINTF(TLB
, " - domain from l1 desc: %d data: %#x bits:%d\n",
612 currState
->l1Desc
.domain(), currState
->l1Desc
.data
,
613 (currState
->l1Desc
.data
>> 5) & 0xF );
615 if (!currState
->timing
) {
616 currState
->tc
= NULL
;
617 currState
->req
= NULL
;
619 tlb
->insert(currState
->vaddr
, te
);
622 case L1Descriptor::PageTable
:
624 l2desc_addr
= currState
->l1Desc
.l2Addr() |
625 (bits(currState
->vaddr
, 19,12) << 2);
626 DPRINTF(TLB
, "L1 descriptor points to page table at: %#x\n",
629 // Trickbox address check
630 currState
->fault
= tlb
->walkTrickBoxCheck(l2desc_addr
, currState
->vaddr
,
631 sizeof(uint32_t), currState
->isFetch
, currState
->isWrite
,
632 currState
->l1Desc
.domain(), false);
634 if (currState
->fault
) {
635 if (!currState
->timing
) {
636 currState
->tc
= NULL
;
637 currState
->req
= NULL
;
643 if (currState
->timing
) {
644 currState
->delayed
= true;
645 port
.dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
646 &doL2DescEvent
, (uint8_t*)&currState
->l2Desc
.data
,
647 currState
->tc
->getCpuPtr()->clockPeriod());
648 } else if (!currState
->functional
) {
649 port
.dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
650 NULL
, (uint8_t*)&currState
->l2Desc
.data
,
651 currState
->tc
->getCpuPtr()->clockPeriod());
654 RequestPtr req
= new Request(l2desc_addr
, sizeof(uint32_t), 0,
656 PacketPtr pkt
= new Packet(req
, MemCmd::ReadReq
);
657 pkt
->dataStatic((uint8_t*)&currState
->l2Desc
.data
);
658 port
.sendFunctional(pkt
);
665 panic("A new type in a 2 bit field?\n");
670 TableWalker::doL2Descriptor()
672 DPRINTF(TLB
, "L2 descriptor for %#x is %#x\n",
673 currState
->vaddr
, currState
->l2Desc
.data
);
676 if (currState
->l2Desc
.invalid()) {
677 DPRINTF(TLB
, "L2 descriptor invalid, causing fault\n");
678 if (!currState
->timing
) {
679 currState
->tc
= NULL
;
680 currState
->req
= NULL
;
682 if (currState
->isFetch
)
684 new PrefetchAbort(currState
->vaddr
, ArmFault::Translation1
);
687 new DataAbort(currState
->vaddr
, currState
->l1Desc
.domain(),
688 currState
->isWrite
, ArmFault::Translation1
);
692 if (currState
->sctlr
.afe
&& bits(currState
->l2Desc
.ap(), 0) == 0) {
693 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
694 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
698 new DataAbort(currState
->vaddr
, 0, currState
->isWrite
,
699 ArmFault::AccessFlag1
);
703 if (currState
->l2Desc
.large()) {
705 te
.pfn
= currState
->l2Desc
.pfn();
708 te
.pfn
= currState
->l2Desc
.pfn();
712 te
.size
= (1 << te
.N
) - 1;
713 te
.asid
= currState
->contextId
;
715 te
.vpn
= currState
->vaddr
>> te
.N
;
716 te
.global
= currState
->l2Desc
.global();
717 te
.xn
= currState
->l2Desc
.xn();
718 te
.ap
= currState
->l2Desc
.ap();
719 te
.domain
= currState
->l1Desc
.domain();
720 memAttrs(currState
->tc
, te
, currState
->sctlr
, currState
->l2Desc
.texcb(),
721 currState
->l2Desc
.shareable());
723 if (!currState
->timing
) {
724 currState
->tc
= NULL
;
725 currState
->req
= NULL
;
727 tlb
->insert(currState
->vaddr
, te
);
731 TableWalker::doL1DescriptorWrapper()
733 currState
= stateQueueL1
.front();
734 currState
->delayed
= false;
736 DPRINTF(TLBVerbose
, "L1 Desc object host addr: %p\n",&currState
->l1Desc
.data
);
737 DPRINTF(TLBVerbose
, "L1 Desc object data: %08x\n",currState
->l1Desc
.data
);
739 DPRINTF(TLBVerbose
, "calling doL1Descriptor for vaddr:%#x\n", currState
->vaddr
);
742 stateQueueL1
.pop_front();
744 // Check if fault was generated
745 if (currState
->fault
!= NoFault
) {
746 currState
->transState
->finish(currState
->fault
, currState
->req
,
747 currState
->tc
, currState
->mode
);
750 nextWalk(currState
->tc
);
752 currState
->req
= NULL
;
753 currState
->tc
= NULL
;
754 currState
->delayed
= false;
757 else if (!currState
->delayed
) {
758 // delay is not set so there is no L2 to do
759 DPRINTF(TLBVerbose
, "calling translateTiming again\n");
760 currState
->fault
= tlb
->translateTiming(currState
->req
, currState
->tc
,
761 currState
->transState
, currState
->mode
);
764 nextWalk(currState
->tc
);
766 currState
->req
= NULL
;
767 currState
->tc
= NULL
;
768 currState
->delayed
= false;
771 // need to do L2 descriptor
772 stateQueueL2
.push_back(currState
);
778 TableWalker::doL2DescriptorWrapper()
780 currState
= stateQueueL2
.front();
781 assert(currState
->delayed
);
783 DPRINTF(TLBVerbose
, "calling doL2Descriptor for vaddr:%#x\n",
787 // Check if fault was generated
788 if (currState
->fault
!= NoFault
) {
789 currState
->transState
->finish(currState
->fault
, currState
->req
,
790 currState
->tc
, currState
->mode
);
793 DPRINTF(TLBVerbose
, "calling translateTiming again\n");
794 currState
->fault
= tlb
->translateTiming(currState
->req
, currState
->tc
,
795 currState
->transState
, currState
->mode
);
799 stateQueueL2
.pop_front();
802 nextWalk(currState
->tc
);
804 currState
->req
= NULL
;
805 currState
->tc
= NULL
;
806 currState
->delayed
= false;
813 TableWalker::nextWalk(ThreadContext
*tc
)
815 if (pendingQueue
.size())
816 schedule(doProcessEvent
, clockEdge(Cycles(1)));
821 ArmISA::TableWalker
*
822 ArmTableWalkerParams::create()
824 return new ArmISA::TableWalker(this);