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
->getMemoryMode() == Enums::timing
) && 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();
190 if (!currState
->transState
->squashed()) {
191 // We've got a valid request, lets process it
193 pendingQueue
.pop_front();
199 // If the instruction that we were translating for has been
200 // squashed we shouldn't bother.
201 unsigned num_squashed
= 0;
202 ThreadContext
*tc
= currState
->tc
;
203 assert(currState
->transState
->squashed());
204 while ((num_squashed
< numSquashable
) && currState
&&
205 currState
->transState
->squashed()) {
206 pendingQueue
.pop_front();
209 DPRINTF(TLB
, "Squashing table walk for address %#x\n", currState
->vaddr
);
211 // finish the translation which will delete the translation object
212 currState
->transState
->finish(new UnimpFault("Squashed Inst"),
213 currState
->req
, currState
->tc
, currState
->mode
);
215 // delete the current request
218 // peak at the next one
219 if (pendingQueue
.size())
220 currState
= pendingQueue
.front();
225 // if we've still got pending translations schedule more work
231 TableWalker::processWalk()
235 // If translation isn't enabled, we shouldn't be here
236 assert(currState
->sctlr
.m
);
238 DPRINTF(TLB
, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
239 currState
->vaddr
, currState
->N
, mbits(currState
->vaddr
, 31,
242 if (currState
->N
== 0 || !mbits(currState
->vaddr
, 31, 32-currState
->N
)) {
243 DPRINTF(TLB
, " - Selecting TTBR0\n");
244 ttbr
= currState
->tc
->readMiscReg(MISCREG_TTBR0
);
246 DPRINTF(TLB
, " - Selecting TTBR1\n");
247 ttbr
= currState
->tc
->readMiscReg(MISCREG_TTBR1
);
251 Addr l1desc_addr
= mbits(ttbr
, 31, 14-currState
->N
) |
252 (bits(currState
->vaddr
,31-currState
->N
,20) << 2);
253 DPRINTF(TLB
, " - Descriptor at address %#x\n", l1desc_addr
);
256 // Trickbox address check
258 f
= tlb
->walkTrickBoxCheck(l1desc_addr
, currState
->vaddr
, sizeof(uint32_t),
259 currState
->isFetch
, currState
->isWrite
, 0, true);
261 DPRINTF(TLB
, "Trickbox check caused fault on %#x\n", currState
->vaddr
);
262 if (currState
->timing
) {
264 nextWalk(currState
->tc
);
267 currState
->tc
= NULL
;
268 currState
->req
= NULL
;
273 Request::Flags flag
= 0;
274 if (currState
->sctlr
.c
== 0) {
275 flag
= Request::UNCACHEABLE
;
278 if (currState
->timing
) {
279 port
.dmaAction(MemCmd::ReadReq
, l1desc_addr
, sizeof(uint32_t),
280 &doL1DescEvent
, (uint8_t*)&currState
->l1Desc
.data
,
281 currState
->tc
->getCpuPtr()->clockPeriod(), flag
);
282 DPRINTF(TLBVerbose
, "Adding to walker fifo: queue size before "
284 stateQueueL1
.size());
285 stateQueueL1
.push_back(currState
);
287 } else if (!currState
->functional
) {
288 port
.dmaAction(MemCmd::ReadReq
, l1desc_addr
, sizeof(uint32_t),
289 NULL
, (uint8_t*)&currState
->l1Desc
.data
,
290 currState
->tc
->getCpuPtr()->clockPeriod(), flag
);
292 f
= currState
->fault
;
294 RequestPtr req
= new Request(l1desc_addr
, sizeof(uint32_t), flag
, masterId
);
295 PacketPtr pkt
= new Packet(req
, MemCmd::ReadReq
);
296 pkt
->dataStatic((uint8_t*)&currState
->l1Desc
.data
);
297 port
.sendFunctional(pkt
);
301 f
= currState
->fault
;
308 TableWalker::memAttrs(ThreadContext
*tc
, TlbEntry
&te
, SCTLR sctlr
,
309 uint8_t texcb
, bool s
)
311 // Note: tc and sctlr local variables are hiding tc and sctrl class
313 DPRINTF(TLBVerbose
, "memAttrs texcb:%d s:%d\n", texcb
, s
);
314 te
.shareable
= false; // default value
315 te
.nonCacheable
= false;
316 bool outer_shareable
= false;
317 if (sctlr
.tre
== 0 || ((sctlr
.tre
== 1) && (sctlr
.m
== 0))) {
319 case 0: // Stongly-ordered
320 te
.nonCacheable
= true;
321 te
.mtype
= TlbEntry::StronglyOrdered
;
326 case 1: // Shareable Device
327 te
.nonCacheable
= true;
328 te
.mtype
= TlbEntry::Device
;
333 case 2: // Outer and Inner Write-Through, no Write-Allocate
334 te
.mtype
= TlbEntry::Normal
;
337 te
.outerAttrs
= bits(texcb
, 1, 0);
339 case 3: // Outer and Inner Write-Back, no Write-Allocate
340 te
.mtype
= TlbEntry::Normal
;
343 te
.outerAttrs
= bits(texcb
, 1, 0);
345 case 4: // Outer and Inner Non-cacheable
346 te
.nonCacheable
= true;
347 te
.mtype
= TlbEntry::Normal
;
350 te
.outerAttrs
= bits(texcb
, 1, 0);
353 panic("Reserved texcb value!\n");
355 case 6: // Implementation Defined
356 panic("Implementation-defined texcb value!\n");
358 case 7: // Outer and Inner Write-Back, Write-Allocate
359 te
.mtype
= TlbEntry::Normal
;
364 case 8: // Non-shareable Device
365 te
.nonCacheable
= true;
366 te
.mtype
= TlbEntry::Device
;
367 te
.shareable
= false;
371 case 9 ... 15: // Reserved
372 panic("Reserved texcb value!\n");
374 case 16 ... 31: // Cacheable Memory
375 te
.mtype
= TlbEntry::Normal
;
377 if (bits(texcb
, 1,0) == 0 || bits(texcb
, 3,2) == 0)
378 te
.nonCacheable
= true;
379 te
.innerAttrs
= bits(texcb
, 1, 0);
380 te
.outerAttrs
= bits(texcb
, 3, 2);
383 panic("More than 32 states for 5 bits?\n");
387 PRRR prrr
= tc
->readMiscReg(MISCREG_PRRR
);
388 NMRR nmrr
= tc
->readMiscReg(MISCREG_NMRR
);
389 DPRINTF(TLBVerbose
, "memAttrs PRRR:%08x NMRR:%08x\n", prrr
, nmrr
);
390 uint8_t curr_tr
= 0, curr_ir
= 0, curr_or
= 0;
391 switch(bits(texcb
, 2,0)) {
396 outer_shareable
= (prrr
.nos0
== 0);
402 outer_shareable
= (prrr
.nos1
== 0);
408 outer_shareable
= (prrr
.nos2
== 0);
414 outer_shareable
= (prrr
.nos3
== 0);
420 outer_shareable
= (prrr
.nos4
== 0);
426 outer_shareable
= (prrr
.nos5
== 0);
429 panic("Imp defined type\n");
434 outer_shareable
= (prrr
.nos7
== 0);
440 DPRINTF(TLBVerbose
, "StronglyOrdered\n");
441 te
.mtype
= TlbEntry::StronglyOrdered
;
442 te
.nonCacheable
= true;
448 DPRINTF(TLBVerbose
, "Device ds1:%d ds0:%d s:%d\n",
449 prrr
.ds1
, prrr
.ds0
, s
);
450 te
.mtype
= TlbEntry::Device
;
451 te
.nonCacheable
= true;
460 DPRINTF(TLBVerbose
, "Normal ns1:%d ns0:%d s:%d\n",
461 prrr
.ns1
, prrr
.ns0
, s
);
462 te
.mtype
= TlbEntry::Normal
;
469 panic("Reserved type");
472 if (te
.mtype
== TlbEntry::Normal
){
475 te
.nonCacheable
= true;
491 te
.nonCacheable
= true;
506 DPRINTF(TLBVerbose
, "memAttrs: shareable: %d, innerAttrs: %d, \
508 te
.shareable
, te
.innerAttrs
, te
.outerAttrs
);
510 /** Formatting for Physical Address Register (PAR)
511 * Only including lower bits (TLB info here)
516 * NOS [10] (Not Outer Sharable)
517 * NS [9] (Non-Secure)
518 * -- [8] (Implementation Defined)
520 * Inner[6:4](Inner memory attributes)
521 * Outer[3:2](Outer memory attributes)
522 * SS [1] (SuperSection)
523 * F [0] (Fault, Fault Status in [6:1] if faulted)
526 ((outer_shareable
? 0:1) << 10) |
528 ((te
.shareable
? 1:0) << 7) |
529 (te
.innerAttrs
<< 4) |
531 // TODO: Supersection bit
539 TableWalker::doL1Descriptor()
541 DPRINTF(TLB
, "L1 descriptor for %#x is %#x\n",
542 currState
->vaddr
, currState
->l1Desc
.data
);
545 switch (currState
->l1Desc
.type()) {
546 case L1Descriptor::Ignore
:
547 case L1Descriptor::Reserved
:
548 if (!currState
->timing
) {
549 currState
->tc
= NULL
;
550 currState
->req
= NULL
;
552 DPRINTF(TLB
, "L1 Descriptor Reserved/Ignore, causing fault\n");
553 if (currState
->isFetch
)
555 new PrefetchAbort(currState
->vaddr
, ArmFault::Translation0
);
558 new DataAbort(currState
->vaddr
, 0, currState
->isWrite
,
559 ArmFault::Translation0
);
561 case L1Descriptor::Section
:
562 if (currState
->sctlr
.afe
&& bits(currState
->l1Desc
.ap(), 0) == 0) {
563 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
564 * enabled if set, do l1.Desc.setAp0() instead of generating
568 currState
->fault
= new DataAbort(currState
->vaddr
,
569 currState
->l1Desc
.domain(), currState
->isWrite
,
570 ArmFault::AccessFlag0
);
572 if (currState
->l1Desc
.supersection()) {
573 panic("Haven't implemented supersections\n");
576 te
.pfn
= currState
->l1Desc
.pfn();
577 te
.size
= (1<<te
.N
) - 1;
578 te
.global
= !currState
->l1Desc
.global();
580 te
.vpn
= currState
->vaddr
>> te
.N
;
582 te
.xn
= currState
->l1Desc
.xn();
583 te
.ap
= currState
->l1Desc
.ap();
584 te
.domain
= currState
->l1Desc
.domain();
585 te
.asid
= currState
->contextId
;
586 memAttrs(currState
->tc
, te
, currState
->sctlr
,
587 currState
->l1Desc
.texcb(), currState
->l1Desc
.shareable());
589 DPRINTF(TLB
, "Inserting Section Descriptor into TLB\n");
590 DPRINTF(TLB
, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n",
591 te
.N
, te
.pfn
, te
.size
, te
.global
, te
.valid
);
592 DPRINTF(TLB
, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n",
593 te
.vpn
, te
.sNp
, te
.xn
, te
.ap
, te
.domain
, te
.asid
,
595 DPRINTF(TLB
, " - domain from l1 desc: %d data: %#x bits:%d\n",
596 currState
->l1Desc
.domain(), currState
->l1Desc
.data
,
597 (currState
->l1Desc
.data
>> 5) & 0xF );
599 if (!currState
->timing
) {
600 currState
->tc
= NULL
;
601 currState
->req
= NULL
;
603 tlb
->insert(currState
->vaddr
, te
);
606 case L1Descriptor::PageTable
:
608 l2desc_addr
= currState
->l1Desc
.l2Addr() |
609 (bits(currState
->vaddr
, 19,12) << 2);
610 DPRINTF(TLB
, "L1 descriptor points to page table at: %#x\n",
613 // Trickbox address check
614 currState
->fault
= tlb
->walkTrickBoxCheck(l2desc_addr
, currState
->vaddr
,
615 sizeof(uint32_t), currState
->isFetch
, currState
->isWrite
,
616 currState
->l1Desc
.domain(), false);
618 if (currState
->fault
) {
619 if (!currState
->timing
) {
620 currState
->tc
= NULL
;
621 currState
->req
= NULL
;
627 if (currState
->timing
) {
628 currState
->delayed
= true;
629 port
.dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
630 &doL2DescEvent
, (uint8_t*)&currState
->l2Desc
.data
,
631 currState
->tc
->getCpuPtr()->clockPeriod());
632 } else if (!currState
->functional
) {
633 port
.dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
634 NULL
, (uint8_t*)&currState
->l2Desc
.data
,
635 currState
->tc
->getCpuPtr()->clockPeriod());
638 RequestPtr req
= new Request(l2desc_addr
, sizeof(uint32_t), 0,
640 PacketPtr pkt
= new Packet(req
, MemCmd::ReadReq
);
641 pkt
->dataStatic((uint8_t*)&currState
->l2Desc
.data
);
642 port
.sendFunctional(pkt
);
649 panic("A new type in a 2 bit field?\n");
654 TableWalker::doL2Descriptor()
656 DPRINTF(TLB
, "L2 descriptor for %#x is %#x\n",
657 currState
->vaddr
, currState
->l2Desc
.data
);
660 if (currState
->l2Desc
.invalid()) {
661 DPRINTF(TLB
, "L2 descriptor invalid, causing fault\n");
662 if (!currState
->timing
) {
663 currState
->tc
= NULL
;
664 currState
->req
= NULL
;
666 if (currState
->isFetch
)
668 new PrefetchAbort(currState
->vaddr
, ArmFault::Translation1
);
671 new DataAbort(currState
->vaddr
, currState
->l1Desc
.domain(),
672 currState
->isWrite
, ArmFault::Translation1
);
676 if (currState
->sctlr
.afe
&& bits(currState
->l2Desc
.ap(), 0) == 0) {
677 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
678 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
682 new DataAbort(currState
->vaddr
, 0, currState
->isWrite
,
683 ArmFault::AccessFlag1
);
687 if (currState
->l2Desc
.large()) {
689 te
.pfn
= currState
->l2Desc
.pfn();
692 te
.pfn
= currState
->l2Desc
.pfn();
696 te
.size
= (1 << te
.N
) - 1;
697 te
.asid
= currState
->contextId
;
699 te
.vpn
= currState
->vaddr
>> te
.N
;
700 te
.global
= currState
->l2Desc
.global();
701 te
.xn
= currState
->l2Desc
.xn();
702 te
.ap
= currState
->l2Desc
.ap();
703 te
.domain
= currState
->l1Desc
.domain();
704 memAttrs(currState
->tc
, te
, currState
->sctlr
, currState
->l2Desc
.texcb(),
705 currState
->l2Desc
.shareable());
707 if (!currState
->timing
) {
708 currState
->tc
= NULL
;
709 currState
->req
= NULL
;
711 tlb
->insert(currState
->vaddr
, te
);
715 TableWalker::doL1DescriptorWrapper()
717 currState
= stateQueueL1
.front();
718 currState
->delayed
= false;
720 DPRINTF(TLBVerbose
, "L1 Desc object host addr: %p\n",&currState
->l1Desc
.data
);
721 DPRINTF(TLBVerbose
, "L1 Desc object data: %08x\n",currState
->l1Desc
.data
);
723 DPRINTF(TLBVerbose
, "calling doL1Descriptor for vaddr:%#x\n", currState
->vaddr
);
726 stateQueueL1
.pop_front();
728 // Check if fault was generated
729 if (currState
->fault
!= NoFault
) {
730 currState
->transState
->finish(currState
->fault
, currState
->req
,
731 currState
->tc
, currState
->mode
);
734 nextWalk(currState
->tc
);
736 currState
->req
= NULL
;
737 currState
->tc
= NULL
;
738 currState
->delayed
= false;
741 else if (!currState
->delayed
) {
742 // delay is not set so there is no L2 to do
743 DPRINTF(TLBVerbose
, "calling translateTiming again\n");
744 currState
->fault
= tlb
->translateTiming(currState
->req
, currState
->tc
,
745 currState
->transState
, currState
->mode
);
748 nextWalk(currState
->tc
);
750 currState
->req
= NULL
;
751 currState
->tc
= NULL
;
752 currState
->delayed
= false;
755 // need to do L2 descriptor
756 stateQueueL2
.push_back(currState
);
762 TableWalker::doL2DescriptorWrapper()
764 currState
= stateQueueL2
.front();
765 assert(currState
->delayed
);
767 DPRINTF(TLBVerbose
, "calling doL2Descriptor for vaddr:%#x\n",
771 // Check if fault was generated
772 if (currState
->fault
!= NoFault
) {
773 currState
->transState
->finish(currState
->fault
, currState
->req
,
774 currState
->tc
, currState
->mode
);
777 DPRINTF(TLBVerbose
, "calling translateTiming again\n");
778 currState
->fault
= tlb
->translateTiming(currState
->req
, currState
->tc
,
779 currState
->transState
, currState
->mode
);
783 stateQueueL2
.pop_front();
786 nextWalk(currState
->tc
);
788 currState
->req
= NULL
;
789 currState
->tc
= NULL
;
790 currState
->delayed
= false;
797 TableWalker::nextWalk(ThreadContext
*tc
)
799 if (pendingQueue
.size())
800 schedule(doProcessEvent
, clockEdge(Cycles(1)));
805 ArmISA::TableWalker
*
806 ArmTableWalkerParams::create()
808 return new ArmISA::TableWalker(this);