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 "dev/io_device.hh"
44 #include "cpu/thread_context.hh"
46 using namespace ArmISA
;
48 TableWalker::TableWalker(const Params
*p
)
49 : MemObject(p
), port(NULL
), tlb(NULL
),
50 currState(NULL
), doL1DescEvent(this), doL2DescEvent(this)
55 TableWalker::~TableWalker()
64 panic("Not implemented\n");
68 TableWalker::getPort(const std::string
&if_name
, int idx
)
70 if (if_name
== "port") {
72 fatal("%s: port already connected to %s",
73 name(), port
->getPeer()->name());
74 System
*sys
= params()->sys
;
75 Tick minb
= params()->min_backoff
;
76 Tick maxb
= params()->max_backoff
;
77 port
= new DmaPort(this, sys
, minb
, maxb
);
84 TableWalker::walk(RequestPtr _req
, ThreadContext
*_tc
, uint8_t _cid
, TLB::Mode _mode
,
85 TLB::Translation
*_trans
, bool _timing
)
88 // For atomic mode, a new WalkerState instance should be only created
89 // once per TLB. For timing mode, a new instance is generated for every
91 DPRINTF(TLBVerbose
, "creating new instance of WalkerState\n");
93 currState
= new WalkerState();
94 currState
->tableWalker
= this;
97 panic("currState should always be empty in timing mode!\n");
101 currState
->transState
= _trans
;
102 currState
->req
= _req
;
103 currState
->fault
= NoFault
;
104 currState
->contextId
= _cid
;
105 currState
->timing
= _timing
;
106 currState
->mode
= _mode
;
108 /** @todo These should be cached or grabbed from cached copies in
109 the TLB, all these miscreg reads are expensive */
110 currState
->vaddr
= currState
->req
->getVaddr() & ~PcModeMask
;
111 currState
->sctlr
= currState
->tc
->readMiscReg(MISCREG_SCTLR
);
112 sctlr
= currState
->sctlr
;
113 currState
->N
= currState
->tc
->readMiscReg(MISCREG_TTBCR
);
115 currState
->isFetch
= (currState
->mode
== TLB::Execute
);
116 currState
->isWrite
= (currState
->mode
== TLB::Write
);
120 // If translation isn't enabled, we shouldn't be here
121 assert(currState
->sctlr
.m
);
123 DPRINTF(TLB
, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
124 currState
->vaddr
, currState
->N
, mbits(currState
->vaddr
, 31,
127 if (currState
->N
== 0 || !mbits(currState
->vaddr
, 31, 32-currState
->N
)) {
128 DPRINTF(TLB
, " - Selecting TTBR0\n");
129 ttbr
= currState
->tc
->readMiscReg(MISCREG_TTBR0
);
131 DPRINTF(TLB
, " - Selecting TTBR1\n");
132 ttbr
= currState
->tc
->readMiscReg(MISCREG_TTBR1
);
136 Addr l1desc_addr
= mbits(ttbr
, 31, 14-currState
->N
) |
137 (bits(currState
->vaddr
,31-currState
->N
,20) << 2);
138 DPRINTF(TLB
, " - Descriptor at address %#x\n", l1desc_addr
);
141 // Trickbox address check
143 f
= tlb
->walkTrickBoxCheck(l1desc_addr
, currState
->vaddr
, sizeof(uint32_t),
144 currState
->isFetch
, currState
->isWrite
, 0, true);
146 if (currState
->timing
) {
147 currState
->transState
->finish(f
, currState
->req
,
148 currState
->tc
, currState
->mode
);
151 currState
->tc
= NULL
;
152 currState
->req
= NULL
;
157 if (currState
->timing
) {
158 port
->dmaAction(MemCmd::ReadReq
, l1desc_addr
, sizeof(uint32_t),
159 &doL1DescEvent
, (uint8_t*)&currState
->l1Desc
.data
, (Tick
)0);
160 DPRINTF(TLBVerbose
, "Adding to walker fifo: queue size before adding: %d\n",
161 stateQueueL1
.size());
162 stateQueueL1
.push_back(currState
);
165 Request::Flags flag
= 0;
166 if (currState
->sctlr
.c
== 0){
167 flag
= Request::UNCACHEABLE
;
169 port
->dmaAction(MemCmd::ReadReq
, l1desc_addr
, sizeof(uint32_t),
170 NULL
, (uint8_t*)&currState
->l1Desc
.data
, (Tick
)0, flag
);
172 f
= currState
->fault
;
179 TableWalker::memAttrs(ThreadContext
*tc
, TlbEntry
&te
, SCTLR sctlr
,
180 uint8_t texcb
, bool s
)
182 // Note: tc and sctlr local variables are hiding tc and sctrl class
184 DPRINTF(TLBVerbose
, "memAttrs texcb:%d s:%d\n", texcb
, s
);
185 te
.shareable
= false; // default value
186 te
.nonCacheable
= false;
187 bool outer_shareable
= false;
188 if (sctlr
.tre
== 0 || ((sctlr
.tre
== 1) && (sctlr
.m
== 0))) {
190 case 0: // Stongly-ordered
191 te
.nonCacheable
= true;
192 te
.mtype
= TlbEntry::StronglyOrdered
;
197 case 1: // Shareable Device
198 te
.nonCacheable
= true;
199 te
.mtype
= TlbEntry::Device
;
204 case 2: // Outer and Inner Write-Through, no Write-Allocate
205 te
.mtype
= TlbEntry::Normal
;
208 te
.outerAttrs
= bits(texcb
, 1, 0);
210 case 3: // Outer and Inner Write-Back, no Write-Allocate
211 te
.mtype
= TlbEntry::Normal
;
214 te
.outerAttrs
= bits(texcb
, 1, 0);
216 case 4: // Outer and Inner Non-cacheable
217 te
.nonCacheable
= true;
218 te
.mtype
= TlbEntry::Normal
;
221 te
.outerAttrs
= bits(texcb
, 1, 0);
224 panic("Reserved texcb value!\n");
226 case 6: // Implementation Defined
227 panic("Implementation-defined texcb value!\n");
229 case 7: // Outer and Inner Write-Back, Write-Allocate
230 te
.mtype
= TlbEntry::Normal
;
235 case 8: // Non-shareable Device
236 te
.nonCacheable
= true;
237 te
.mtype
= TlbEntry::Device
;
238 te
.shareable
= false;
242 case 9 ... 15: // Reserved
243 panic("Reserved texcb value!\n");
245 case 16 ... 31: // Cacheable Memory
246 te
.mtype
= TlbEntry::Normal
;
248 if (bits(texcb
, 1,0) == 0 || bits(texcb
, 3,2) == 0)
249 te
.nonCacheable
= true;
250 te
.innerAttrs
= bits(texcb
, 1, 0);
251 te
.outerAttrs
= bits(texcb
, 3, 2);
254 panic("More than 32 states for 5 bits?\n");
258 PRRR prrr
= tc
->readMiscReg(MISCREG_PRRR
);
259 NMRR nmrr
= tc
->readMiscReg(MISCREG_NMRR
);
260 DPRINTF(TLBVerbose
, "memAttrs PRRR:%08x NMRR:%08x\n", prrr
, nmrr
);
261 uint8_t curr_tr
= 0, curr_ir
= 0, curr_or
= 0;
262 switch(bits(texcb
, 2,0)) {
267 outer_shareable
= (prrr
.nos0
== 0);
273 outer_shareable
= (prrr
.nos1
== 0);
279 outer_shareable
= (prrr
.nos2
== 0);
285 outer_shareable
= (prrr
.nos3
== 0);
291 outer_shareable
= (prrr
.nos4
== 0);
297 outer_shareable
= (prrr
.nos5
== 0);
300 panic("Imp defined type\n");
305 outer_shareable
= (prrr
.nos7
== 0);
311 DPRINTF(TLBVerbose
, "StronglyOrdered\n");
312 te
.mtype
= TlbEntry::StronglyOrdered
;
313 te
.nonCacheable
= true;
319 DPRINTF(TLBVerbose
, "Device ds1:%d ds0:%d s:%d\n",
320 prrr
.ds1
, prrr
.ds0
, s
);
321 te
.mtype
= TlbEntry::Device
;
322 te
.nonCacheable
= true;
331 DPRINTF(TLBVerbose
, "Normal ns1:%d ns0:%d s:%d\n",
332 prrr
.ns1
, prrr
.ns0
, s
);
333 te
.mtype
= TlbEntry::Normal
;
340 panic("Reserved type");
343 if (te
.mtype
== TlbEntry::Normal
){
346 te
.nonCacheable
= true;
362 te
.nonCacheable
= true;
377 DPRINTF(TLBVerbose
, "memAttrs: shareable: %d, innerAttrs: %d, \
379 te
.shareable
, te
.innerAttrs
, te
.outerAttrs
);
381 /** Formatting for Physical Address Register (PAR)
382 * Only including lower bits (TLB info here)
387 * NOS [10] (Not Outer Sharable)
388 * NS [9] (Non-Secure)
389 * -- [8] (Implementation Defined)
391 * Inner[6:4](Inner memory attributes)
392 * Outer[3:2](Outer memory attributes)
393 * SS [1] (SuperSection)
394 * F [0] (Fault, Fault Status in [6:1] if faulted)
397 ((outer_shareable
? 0:1) << 10) |
399 ((te
.shareable
? 1:0) << 7) |
400 (te
.innerAttrs
<< 4) |
402 // TODO: Supersection bit
410 TableWalker::doL1Descriptor()
412 DPRINTF(TLB
, "L1 descriptor for %#x is %#x\n",
413 currState
->vaddr
, currState
->l1Desc
.data
);
416 switch (currState
->l1Desc
.type()) {
417 case L1Descriptor::Ignore
:
418 case L1Descriptor::Reserved
:
419 if (!currState
->delayed
) {
420 currState
->tc
= NULL
;
421 currState
->req
= NULL
;
423 DPRINTF(TLB
, "L1 Descriptor Reserved/Ignore, causing fault\n");
424 if (currState
->isFetch
)
426 new PrefetchAbort(currState
->vaddr
, ArmFault::Translation0
);
429 new DataAbort(currState
->vaddr
, 0, currState
->isWrite
,
430 ArmFault::Translation0
);
432 case L1Descriptor::Section
:
433 if (currState
->sctlr
.afe
&& bits(currState
->l1Desc
.ap(), 0) == 0) {
434 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
435 * enabled if set, do l1.Desc.setAp0() instead of generating
439 currState
->fault
= new DataAbort(currState
->vaddr
,
440 currState
->l1Desc
.domain(), currState
->isWrite
,
441 ArmFault::AccessFlag0
);
443 if (currState
->l1Desc
.supersection()) {
444 panic("Haven't implemented supersections\n");
447 te
.pfn
= currState
->l1Desc
.pfn();
448 te
.size
= (1<<te
.N
) - 1;
449 te
.global
= !currState
->l1Desc
.global();
451 te
.vpn
= currState
->vaddr
>> te
.N
;
453 te
.xn
= currState
->l1Desc
.xn();
454 te
.ap
= currState
->l1Desc
.ap();
455 te
.domain
= currState
->l1Desc
.domain();
456 te
.asid
= currState
->contextId
;
457 memAttrs(currState
->tc
, te
, currState
->sctlr
,
458 currState
->l1Desc
.texcb(), currState
->l1Desc
.shareable());
460 DPRINTF(TLB
, "Inserting Section Descriptor into TLB\n");
461 DPRINTF(TLB
, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n",
462 te
.N
, te
.pfn
, te
.size
, te
.global
, te
.valid
);
463 DPRINTF(TLB
, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n",
464 te
.vpn
, te
.sNp
, te
.xn
, te
.ap
, te
.domain
, te
.asid
,
466 DPRINTF(TLB
, " - domain from l1 desc: %d data: %#x bits:%d\n",
467 currState
->l1Desc
.domain(), currState
->l1Desc
.data
,
468 (currState
->l1Desc
.data
>> 5) & 0xF );
470 if (!currState
->timing
) {
471 currState
->tc
= NULL
;
472 currState
->req
= NULL
;
474 tlb
->insert(currState
->vaddr
, te
);
477 case L1Descriptor::PageTable
:
479 l2desc_addr
= currState
->l1Desc
.l2Addr() |
480 (bits(currState
->vaddr
, 19,12) << 2);
481 DPRINTF(TLB
, "L1 descriptor points to page table at: %#x\n",
484 // Trickbox address check
485 currState
->fault
= tlb
->walkTrickBoxCheck(l2desc_addr
, currState
->vaddr
,
486 sizeof(uint32_t), currState
->isFetch
, currState
->isWrite
,
487 currState
->l1Desc
.domain(), false);
489 if (currState
->fault
) {
490 if (!currState
->timing
) {
491 currState
->tc
= NULL
;
492 currState
->req
= NULL
;
498 if (currState
->timing
) {
499 currState
->delayed
= true;
500 port
->dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
501 &doL2DescEvent
, (uint8_t*)&currState
->l2Desc
.data
, 0);
503 port
->dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
504 NULL
, (uint8_t*)&currState
->l2Desc
.data
, 0);
509 panic("A new type in a 2 bit field?\n");
514 TableWalker::doL2Descriptor()
516 DPRINTF(TLB
, "L2 descriptor for %#x is %#x\n",
517 currState
->vaddr
, currState
->l2Desc
.data
);
520 if (currState
->l2Desc
.invalid()) {
521 DPRINTF(TLB
, "L2 descriptor invalid, causing fault\n");
522 if (!currState
->delayed
) {
523 currState
->tc
= NULL
;
524 currState
->req
= NULL
;
526 if (currState
->isFetch
)
528 new PrefetchAbort(currState
->vaddr
, ArmFault::Translation1
);
531 new DataAbort(currState
->vaddr
, currState
->l1Desc
.domain(),
532 currState
->isWrite
, ArmFault::Translation1
);
536 if (currState
->sctlr
.afe
&& bits(currState
->l2Desc
.ap(), 0) == 0) {
537 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
538 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
542 new DataAbort(currState
->vaddr
, 0, currState
->isWrite
,
543 ArmFault::AccessFlag1
);
547 if (currState
->l2Desc
.large()) {
549 te
.pfn
= currState
->l2Desc
.pfn();
552 te
.pfn
= currState
->l2Desc
.pfn();
556 te
.size
= (1 << te
.N
) - 1;
557 te
.asid
= currState
->contextId
;
559 te
.vpn
= currState
->vaddr
>> te
.N
;
560 te
.global
= currState
->l2Desc
.global();
561 te
.xn
= currState
->l2Desc
.xn();
562 te
.ap
= currState
->l2Desc
.ap();
563 te
.domain
= currState
->l1Desc
.domain();
564 memAttrs(currState
->tc
, te
, currState
->sctlr
, currState
->l2Desc
.texcb(),
565 currState
->l2Desc
.shareable());
567 if (!currState
->delayed
) {
568 currState
->tc
= NULL
;
569 currState
->req
= NULL
;
571 tlb
->insert(currState
->vaddr
, te
);
575 TableWalker::doL1DescriptorWrapper()
577 currState
= stateQueueL1
.front();
578 currState
->delayed
= false;
580 DPRINTF(TLBVerbose
, "L1 Desc object host addr: %p\n",&currState
->l1Desc
.data
);
581 DPRINTF(TLBVerbose
, "L1 Desc object data: %08x\n",currState
->l1Desc
.data
);
583 DPRINTF(TLBVerbose
, "calling doL1Descriptor for vaddr:%#x\n", currState
->vaddr
);
586 stateQueueL1
.pop_front();
587 // Check if fault was generated
588 if (currState
->fault
!= NoFault
) {
589 currState
->transState
->finish(currState
->fault
, currState
->req
,
590 currState
->tc
, currState
->mode
);
592 currState
->req
= NULL
;
593 currState
->tc
= NULL
;
594 currState
->delayed
= false;
597 else if (!currState
->delayed
) {
598 // delay is not set so there is no L2 to do
599 DPRINTF(TLBVerbose
, "calling translateTiming again\n");
600 currState
->fault
= tlb
->translateTiming(currState
->req
, currState
->tc
,
601 currState
->transState
, currState
->mode
);
603 currState
->req
= NULL
;
604 currState
->tc
= NULL
;
605 currState
->delayed
= false;
609 // need to do L2 descriptor
610 stateQueueL2
.push_back(currState
);
616 TableWalker::doL2DescriptorWrapper()
618 currState
= stateQueueL2
.front();
619 assert(currState
->delayed
);
621 DPRINTF(TLBVerbose
, "calling doL2Descriptor for vaddr:%#x\n",
625 // Check if fault was generated
626 if (currState
->fault
!= NoFault
) {
627 currState
->transState
->finish(currState
->fault
, currState
->req
,
628 currState
->tc
, currState
->mode
);
631 DPRINTF(TLBVerbose
, "calling translateTiming again\n");
632 currState
->fault
= tlb
->translateTiming(currState
->req
, currState
->tc
,
633 currState
->transState
, currState
->mode
);
636 currState
->req
= NULL
;
637 currState
->tc
= NULL
;
638 currState
->delayed
= false;
640 stateQueueL2
.pop_front();
645 ArmISA::TableWalker
*
646 ArmTableWalkerParams::create()
648 return new ArmISA::TableWalker(this);