9bf067b81db9f08ffba6e98e7781544c92907544
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 #define NUM_WALKERS 2 // 2 should be enough to handle crossing page boundaries
48 using namespace ArmISA
;
50 TableWalker::TableWalker(const Params
*p
)
51 : MemObject(p
), stateQueue(NUM_WALKERS
), port(NULL
), tlb(NULL
),
52 currState(NULL
), doL1DescEvent(this), doL2DescEvent(this)
57 TableWalker::~TableWalker()
66 panic("Not implemented\n");
70 TableWalker::getPort(const std::string
&if_name
, int idx
)
72 if (if_name
== "port") {
74 fatal("%s: port already connected to %s",
75 name(), port
->getPeer()->name());
76 System
*sys
= params()->sys
;
77 Tick minb
= params()->min_backoff
;
78 Tick maxb
= params()->max_backoff
;
79 port
= new DmaPort(this, sys
, minb
, maxb
);
86 TableWalker::walk(RequestPtr _req
, ThreadContext
*_tc
, uint8_t _cid
, TLB::Mode _mode
,
87 TLB::Translation
*_trans
, bool _timing
)
90 // For atomic mode, a new WalkerState instance should be only created
91 // once per TLB. For timing mode, a new instance is generated for every
93 DPRINTF(TLBVerbose
, "creating new instance of WalkerState\n");
95 currState
= new WalkerState();
96 currState
->tableWalker
= this;
99 panic("currState should always be empty in timing mode!\n");
103 currState
->transState
= _trans
;
104 currState
->req
= _req
;
105 currState
->fault
= NoFault
;
106 currState
->contextId
= _cid
;
107 currState
->timing
= _timing
;
108 currState
->mode
= _mode
;
110 /** @todo These should be cached or grabbed from cached copies in
111 the TLB, all these miscreg reads are expensive */
112 currState
->vaddr
= currState
->req
->getVaddr() & ~PcModeMask
;
113 currState
->sctlr
= currState
->tc
->readMiscReg(MISCREG_SCTLR
);
114 sctlr
= currState
->sctlr
;
115 currState
->cpsr
= currState
->tc
->readMiscReg(MISCREG_CPSR
);
116 currState
->N
= currState
->tc
->readMiscReg(MISCREG_TTBCR
);
118 currState
->isFetch
= (currState
->mode
== TLB::Execute
);
119 currState
->isWrite
= (currState
->mode
== TLB::Write
);
120 currState
->isPriv
= (currState
->cpsr
.mode
!= MODE_USER
);
124 // If translation isn't enabled, we shouldn't be here
125 assert(currState
->sctlr
.m
);
127 DPRINTF(TLB
, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
128 currState
->vaddr
, currState
->N
, mbits(currState
->vaddr
, 31,
131 if (currState
->N
== 0 || !mbits(currState
->vaddr
, 31, 32-currState
->N
)) {
132 DPRINTF(TLB
, " - Selecting TTBR0\n");
133 ttbr
= currState
->tc
->readMiscReg(MISCREG_TTBR0
);
135 DPRINTF(TLB
, " - Selecting TTBR1\n");
136 ttbr
= currState
->tc
->readMiscReg(MISCREG_TTBR1
);
140 Addr l1desc_addr
= mbits(ttbr
, 31, 14-currState
->N
) |
141 (bits(currState
->vaddr
,31-currState
->N
,20) << 2);
142 DPRINTF(TLB
, " - Descriptor at address %#x\n", l1desc_addr
);
145 // Trickbox address check
147 f
= tlb
->walkTrickBoxCheck(l1desc_addr
, currState
->vaddr
, sizeof(uint32_t),
148 currState
->isFetch
, currState
->isWrite
, 0, true);
150 currState
->tc
= NULL
;
151 currState
->req
= NULL
;
155 if (currState
->timing
) {
156 port
->dmaAction(MemCmd::ReadReq
, l1desc_addr
, sizeof(uint32_t),
157 &doL1DescEvent
, (uint8_t*)&currState
->l1Desc
.data
, (Tick
)0);
158 DPRINTF(TLBVerbose
, "Adding to walker fifo: %d free before adding\n",
159 stateQueue
.free_slots());
160 stateQueue
.add(*currState
);
163 port
->dmaAction(MemCmd::ReadReq
, l1desc_addr
, sizeof(uint32_t),
164 NULL
, (uint8_t*)&currState
->l1Desc
.data
, (Tick
)0);
166 f
= currState
->fault
;
173 TableWalker::memAttrs(ThreadContext
*tc
, TlbEntry
&te
, SCTLR sctlr
,
174 uint8_t texcb
, bool s
)
176 // Note: tc and sctlr local variables are hiding tc and sctrl class
178 DPRINTF(TLBVerbose
, "memAttrs texcb:%d s:%d\n", texcb
, s
);
179 te
.shareable
= false; // default value
180 bool outer_shareable
= false;
181 if (sctlr
.tre
== 0 || ((sctlr
.tre
== 1) && (sctlr
.m
== 0))) {
183 case 0: // Stongly-ordered
184 te
.nonCacheable
= true;
185 te
.mtype
= TlbEntry::StronglyOrdered
;
190 case 1: // Shareable Device
191 te
.nonCacheable
= true;
192 te
.mtype
= TlbEntry::Device
;
197 case 2: // Outer and Inner Write-Through, no Write-Allocate
198 te
.mtype
= TlbEntry::Normal
;
201 te
.outerAttrs
= bits(texcb
, 1, 0);
203 case 3: // Outer and Inner Write-Back, no Write-Allocate
204 te
.mtype
= TlbEntry::Normal
;
207 te
.outerAttrs
= bits(texcb
, 1, 0);
209 case 4: // Outer and Inner Non-cacheable
210 te
.nonCacheable
= true;
211 te
.mtype
= TlbEntry::Normal
;
214 te
.outerAttrs
= bits(texcb
, 1, 0);
217 panic("Reserved texcb value!\n");
219 case 6: // Implementation Defined
220 panic("Implementation-defined texcb value!\n");
222 case 7: // Outer and Inner Write-Back, Write-Allocate
223 te
.mtype
= TlbEntry::Normal
;
228 case 8: // Non-shareable Device
229 te
.nonCacheable
= true;
230 te
.mtype
= TlbEntry::Device
;
231 te
.shareable
= false;
235 case 9 ... 15: // Reserved
236 panic("Reserved texcb value!\n");
238 case 16 ... 31: // Cacheable Memory
239 te
.mtype
= TlbEntry::Normal
;
241 if (bits(texcb
, 1,0) == 0 || bits(texcb
, 3,2) == 0)
242 te
.nonCacheable
= true;
243 te
.innerAttrs
= bits(texcb
, 1, 0);
244 te
.outerAttrs
= bits(texcb
, 3, 2);
247 panic("More than 32 states for 5 bits?\n");
251 PRRR prrr
= tc
->readMiscReg(MISCREG_PRRR
);
252 NMRR nmrr
= tc
->readMiscReg(MISCREG_NMRR
);
253 DPRINTF(TLBVerbose
, "memAttrs PRRR:%08x NMRR:%08x\n", prrr
, nmrr
);
254 uint8_t curr_tr
, curr_ir
, curr_or
;
255 switch(bits(texcb
, 2,0)) {
260 outer_shareable
= (prrr
.nos0
== 0);
266 outer_shareable
= (prrr
.nos1
== 0);
272 outer_shareable
= (prrr
.nos2
== 0);
278 outer_shareable
= (prrr
.nos3
== 0);
284 outer_shareable
= (prrr
.nos4
== 0);
290 outer_shareable
= (prrr
.nos5
== 0);
293 panic("Imp defined type\n");
298 outer_shareable
= (prrr
.nos7
== 0);
304 DPRINTF(TLBVerbose
, "StronglyOrdered\n");
305 te
.mtype
= TlbEntry::StronglyOrdered
;
306 te
.nonCacheable
= true;
312 DPRINTF(TLBVerbose
, "Device ds1:%d ds0:%d s:%d\n",
313 prrr
.ds1
, prrr
.ds0
, s
);
314 te
.mtype
= TlbEntry::Device
;
315 te
.nonCacheable
= true;
324 DPRINTF(TLBVerbose
, "Normal ns1:%d ns0:%d s:%d\n",
325 prrr
.ns1
, prrr
.ns0
, s
);
326 te
.mtype
= TlbEntry::Normal
;
333 panic("Reserved type");
336 if (te
.mtype
== TlbEntry::Normal
){
339 te
.nonCacheable
= true;
355 te
.nonCacheable
= true;
370 DPRINTF(TLBVerbose
, "memAttrs: shareable: %d, innerAttrs: %d, \
372 te
.shareable
, te
.innerAttrs
, te
.outerAttrs
);
374 /** Formatting for Physical Address Register (PAR)
375 * Only including lower bits (TLB info here)
380 * NOS [10] (Not Outer Sharable)
381 * NS [9] (Non-Secure)
382 * -- [8] (Implementation Defined)
384 * Inner[6:4](Inner memory attributes)
385 * Outer[3:2](Outer memory attributes)
386 * SS [1] (SuperSection)
387 * F [0] (Fault, Fault Status in [6:1] if faulted)
390 ((outer_shareable
? 0:1) << 10) |
392 ((te
.shareable
? 1:0) << 7) |
393 (te
.innerAttrs
<< 4) |
395 // TODO: Supersection bit
403 TableWalker::doL1Descriptor()
405 DPRINTF(TLB
, "L1 descriptor for %#x is %#x\n",
406 currState
->vaddr
, currState
->l1Desc
.data
);
409 switch (currState
->l1Desc
.type()) {
410 case L1Descriptor::Ignore
:
411 case L1Descriptor::Reserved
:
412 if (!currState
->delayed
) {
413 currState
->tc
= NULL
;
414 currState
->req
= NULL
;
416 DPRINTF(TLB
, "L1 Descriptor Reserved/Ignore, causing fault\n");
417 if (currState
->isFetch
)
419 new PrefetchAbort(currState
->vaddr
, ArmFault::Translation0
);
422 new DataAbort(currState
->vaddr
, 0, currState
->isWrite
,
423 ArmFault::Translation0
);
425 case L1Descriptor::Section
:
426 if (currState
->sctlr
.afe
&& bits(currState
->l1Desc
.ap(), 0) == 0) {
427 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
428 * enabled if set, do l1.Desc.setAp0() instead of generating
433 new DataAbort(currState
->vaddr
, NULL
, currState
->isWrite
,
434 ArmFault::AccessFlag0
);
437 if (currState
->l1Desc
.supersection()) {
438 panic("Haven't implemented supersections\n");
441 te
.pfn
= currState
->l1Desc
.pfn();
442 te
.size
= (1<<te
.N
) - 1;
443 te
.global
= !currState
->l1Desc
.global();
445 te
.vpn
= currState
->vaddr
>> te
.N
;
447 te
.xn
= currState
->l1Desc
.xn();
448 te
.ap
= currState
->l1Desc
.ap();
449 te
.domain
= currState
->l1Desc
.domain();
450 te
.asid
= currState
->contextId
;
451 memAttrs(currState
->tc
, te
, currState
->sctlr
,
452 currState
->l1Desc
.texcb(), currState
->l1Desc
.shareable());
454 DPRINTF(TLB
, "Inserting Section Descriptor into TLB\n");
455 DPRINTF(TLB
, " - N%d pfn:%#x size: %#x global:%d valid: %d\n",
456 te
.N
, te
.pfn
, te
.size
, te
.global
, te
.valid
);
457 DPRINTF(TLB
, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d\n",
458 te
.vpn
, te
.sNp
, te
.xn
, te
.ap
, te
.domain
, te
.asid
);
459 DPRINTF(TLB
, " - domain from l1 desc: %d data: %#x bits:%d\n",
460 currState
->l1Desc
.domain(), currState
->l1Desc
.data
,
461 (currState
->l1Desc
.data
>> 5) & 0xF );
463 if (!currState
->timing
) {
464 currState
->tc
= NULL
;
465 currState
->req
= NULL
;
467 tlb
->insert(currState
->vaddr
, te
);
470 case L1Descriptor::PageTable
:
472 l2desc_addr
= currState
->l1Desc
.l2Addr() |
473 (bits(currState
->vaddr
, 19,12) << 2);
474 DPRINTF(TLB
, "L1 descriptor points to page table at: %#x\n",
477 // Trickbox address check
478 currState
->fault
= tlb
->walkTrickBoxCheck(l2desc_addr
, currState
->vaddr
,
479 sizeof(uint32_t), currState
->isFetch
, currState
->isWrite
,
480 currState
->l1Desc
.domain(), false);
482 if (currState
->fault
) {
483 if (!currState
->timing
) {
484 currState
->tc
= NULL
;
485 currState
->req
= NULL
;
491 if (currState
->timing
) {
492 currState
->delayed
= true;
493 port
->dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
494 &doL2DescEvent
, (uint8_t*)&currState
->l2Desc
.data
, 0);
496 port
->dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
497 NULL
, (uint8_t*)&currState
->l2Desc
.data
, 0);
502 panic("A new type in a 2 bit field?\n");
507 TableWalker::doL2Descriptor()
509 DPRINTF(TLB
, "L2 descriptor for %#x is %#x\n",
510 currState
->vaddr
, currState
->l2Desc
.data
);
513 if (currState
->l2Desc
.invalid()) {
514 DPRINTF(TLB
, "L2 descriptor invalid, causing fault\n");
515 if (!currState
->delayed
) {
516 currState
->tc
= NULL
;
517 currState
->req
= NULL
;
519 if (currState
->isFetch
)
521 new PrefetchAbort(currState
->vaddr
, ArmFault::Translation1
);
524 new DataAbort(currState
->vaddr
, currState
->l1Desc
.domain(),
525 currState
->isWrite
, ArmFault::Translation1
);
529 if (currState
->sctlr
.afe
&& bits(currState
->l2Desc
.ap(), 0) == 0) {
530 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
531 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
535 new DataAbort(currState
->vaddr
, 0, currState
->isWrite
,
536 ArmFault::AccessFlag1
);
540 if (currState
->l2Desc
.large()) {
542 te
.pfn
= currState
->l2Desc
.pfn();
545 te
.pfn
= currState
->l2Desc
.pfn();
549 te
.size
= (1 << te
.N
) - 1;
550 te
.asid
= currState
->contextId
;
552 te
.vpn
= currState
->vaddr
>> te
.N
;
553 te
.global
= currState
->l2Desc
.global();
554 te
.xn
= currState
->l2Desc
.xn();
555 te
.ap
= currState
->l2Desc
.ap();
556 te
.domain
= currState
->l1Desc
.domain();
557 memAttrs(currState
->tc
, te
, currState
->sctlr
, currState
->l2Desc
.texcb(),
558 currState
->l2Desc
.shareable());
560 if (!currState
->delayed
) {
561 currState
->tc
= NULL
;
562 currState
->req
= NULL
;
564 tlb
->insert(currState
->vaddr
, te
);
568 TableWalker::doL1DescriptorWrapper()
570 currState
= stateQueue
.peek();
571 currState
->delayed
= false;
573 DPRINTF(TLBVerbose
, "calling doL1Descriptor for vaddr:%#x\n", currState
->vaddr
);
576 // Check if fault was generated
577 if (currState
->fault
!= NoFault
) {
578 currState
->transState
->finish(currState
->fault
, currState
->req
,
579 currState
->tc
, currState
->mode
);
581 currState
->req
= NULL
;
582 currState
->tc
= NULL
;
583 currState
->delayed
= false;
587 else if (!currState
->delayed
) {
588 DPRINTF(TLBVerbose
, "calling translateTiming again\n");
589 currState
->fault
= tlb
->translateTiming(currState
->req
, currState
->tc
,
590 currState
->transState
, currState
->mode
);
592 currState
->req
= NULL
;
593 currState
->tc
= NULL
;
594 currState
->delayed
= false;
602 TableWalker::doL2DescriptorWrapper()
604 currState
= stateQueue
.peek();
605 assert(currState
->delayed
);
607 DPRINTF(TLBVerbose
, "calling doL2Descriptor for vaddr:%#x\n",
611 // Check if fault was generated
612 if (currState
->fault
!= NoFault
) {
613 currState
->transState
->finish(currState
->fault
, currState
->req
,
614 currState
->tc
, currState
->mode
);
617 DPRINTF(TLBVerbose
, "calling translateTiming again\n");
618 currState
->fault
= tlb
->translateTiming(currState
->req
, currState
->tc
,
619 currState
->transState
, currState
->mode
);
622 currState
->req
= NULL
;
623 currState
->tc
= NULL
;
624 currState
->delayed
= false;
630 ArmISA::TableWalker
*
631 ArmTableWalkerParams::create()
633 return new ArmISA::TableWalker(this);