e3ecb7ddd6d95ea0a25f506fa848b0928c5a949c
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"
47 using namespace ArmISA
;
49 TableWalker::TableWalker(const Params
*p
)
50 : MemObject(p
), port(NULL
), tlb(NULL
), tc(NULL
), req(NULL
),
51 doL1DescEvent(this), doL2DescEvent(this)
54 TableWalker::~TableWalker()
63 panic("Not implemented\n");
67 TableWalker::getPort(const std::string
&if_name
, int idx
)
69 if (if_name
== "port") {
71 fatal("%s: port already connected to %s",
72 name(), port
->getPeer()->name());
73 System
*sys
= params()->sys
;
74 Tick minb
= params()->min_backoff
;
75 Tick maxb
= params()->max_backoff
;
76 port
= new DmaPort(this, sys
, minb
, maxb
);
83 TableWalker::walk(RequestPtr _req
, ThreadContext
*_tc
, uint8_t _cid
, TLB::Mode mode
,
84 TLB::Translation
*_trans
, bool _timing
)
86 // Right now 1 CPU == 1 TLB == 1 TLB walker
87 // In the future we might want to change this as multiple
88 // threads/contexts could share a walker and/or a TLB
90 panic("Overlapping TLB walks attempted\n");
99 // XXX These should be cached or grabbed from cached copies in
100 // the TLB, all these miscreg reads are expensive
101 vaddr
= req
->getVaddr() & ~PcModeMask
;
102 sctlr
= tc
->readMiscReg(MISCREG_SCTLR
);
103 cpsr
= tc
->readMiscReg(MISCREG_CPSR
);
104 N
= tc
->readMiscReg(MISCREG_TTBCR
);
107 isFetch
= (mode
== TLB::Execute
);
108 isWrite
= (mode
== TLB::Write
);
109 isPriv
= (cpsr
.mode
!= MODE_USER
);
111 // If translation isn't enabled, we shouldn't be here
114 DPRINTF(TLB
, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
115 vaddr
, N
, mbits(vaddr
, 31, 32-N
));
117 if (N
== 0 || !mbits(vaddr
, 31, 32-N
)) {
118 DPRINTF(TLB
, " - Selecting TTBR0\n");
119 ttbr
= tc
->readMiscReg(MISCREG_TTBR0
);
121 DPRINTF(TLB
, " - Selecting TTBR1\n");
122 ttbr
= tc
->readMiscReg(MISCREG_TTBR1
);
126 Addr l1desc_addr
= mbits(ttbr
, 31, 14-N
) | (bits(vaddr
,31-N
,20) << 2);
127 DPRINTF(TLB
, " - Descriptor at address %#x\n", l1desc_addr
);
130 // Trickbox address check
131 fault
= tlb
->walkTrickBoxCheck(l1desc_addr
, vaddr
, sizeof(uint32_t),
132 isFetch
, isWrite
, 0, true);
140 port
->dmaAction(MemCmd::ReadReq
, l1desc_addr
, sizeof(uint32_t),
141 &doL1DescEvent
, (uint8_t*)&l1Desc
.data
, (Tick
)0);
143 port
->dmaAction(MemCmd::ReadReq
, l1desc_addr
, sizeof(uint32_t),
144 NULL
, (uint8_t*)&l1Desc
.data
, (Tick
)0);
152 TableWalker::memAttrs(TlbEntry
&te
, uint8_t texcb
)
155 if (sctlr
.tre
== 0) {
161 te
.nonCacheable
= true;
164 if (bits(texcb
, 1,0) == 0 || bits(texcb
, 3,2) == 0)
165 te
.nonCacheable
= true;
169 PRRR prrr
= tc
->readMiscReg(MISCREG_PRRR
);
170 NMRR nmrr
= tc
->readMiscReg(MISCREG_NMRR
);
171 switch(bits(texcb
, 2,0)) {
173 if (nmrr
.ir0
== 0 || nmrr
.or0
== 0 || prrr
.tr0
!= 0x2)
174 te
.nonCacheable
= true;
177 if (nmrr
.ir1
== 0 || nmrr
.or1
== 0 || prrr
.tr1
!= 0x2)
178 te
.nonCacheable
= true;
181 if (nmrr
.ir2
== 0 || nmrr
.or2
== 0 || prrr
.tr2
!= 0x2)
182 te
.nonCacheable
= true;
185 if (nmrr
.ir3
== 0 || nmrr
.or3
== 0 || prrr
.tr3
!= 0x2)
186 te
.nonCacheable
= true;
189 if (nmrr
.ir4
== 0 || nmrr
.or4
== 0 || prrr
.tr4
!= 0x2)
190 te
.nonCacheable
= true;
193 if (nmrr
.ir5
== 0 || nmrr
.or5
== 0 || prrr
.tr5
!= 0x2)
194 te
.nonCacheable
= true;
197 panic("Imp defined type\n");
199 if (nmrr
.ir7
== 0 || nmrr
.or7
== 0 || prrr
.tr7
!= 0x2)
200 te
.nonCacheable
= true;
207 TableWalker::doL1Descriptor()
209 DPRINTF(TLB
, "L1 descriptor for %#x is %#x\n", vaddr
, l1Desc
.data
);
212 switch (l1Desc
.type()) {
213 case L1Descriptor::Ignore
:
214 case L1Descriptor::Reserved
:
217 DPRINTF(TLB
, "L1 Descriptor Reserved/Ignore, causing fault\n");
219 fault
= new PrefetchAbort(vaddr
, ArmFault::Translation0
);
221 fault
= new DataAbort(vaddr
, NULL
, isWrite
, ArmFault::Translation0
);
223 case L1Descriptor::Section
:
224 if (sctlr
.afe
&& bits(l1Desc
.ap(), 0) == 0)
225 panic("Haven't implemented AFE\n");
227 if (l1Desc
.supersection()) {
228 panic("Haven't implemented supersections\n");
231 te
.pfn
= l1Desc
.pfn();
232 te
.size
= (1<<te
.N
) - 1;
233 te
.global
= !l1Desc
.global();
235 te
.vpn
= vaddr
>> te
.N
;
239 te
.domain
= l1Desc
.domain();
241 memAttrs(te
, l1Desc
.texcb());
243 DPRINTF(TLB
, "Inserting Section Descriptor into TLB\n");
244 DPRINTF(TLB
, " - N%d pfn:%#x size: %#x global:%d valid: %d\n",
245 te
.N
, te
.pfn
, te
.size
, te
.global
, te
.valid
);
246 DPRINTF(TLB
, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d\n",
247 te
.vpn
, te
.sNp
, te
.xn
, te
.ap
, te
.domain
, te
.asid
);
248 DPRINTF(TLB
, " - domain from l1 desc: %d data: %#x bits:%d\n",
249 l1Desc
.domain(), l1Desc
.data
, (l1Desc
.data
>> 5) & 0xF );
253 tlb
->insert(vaddr
, te
);
256 case L1Descriptor::PageTable
:
258 l2desc_addr
= l1Desc
.l2Addr() | (bits(vaddr
, 19,12) << 2);
259 DPRINTF(TLB
, "L1 descriptor points to page table at: %#x\n", l2desc_addr
);
261 // Trickbox address check
262 fault
= tlb
->walkTrickBoxCheck(l2desc_addr
, vaddr
, sizeof(uint32_t),
263 isFetch
, isWrite
, l1Desc
.domain(), false);
272 port
->dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
273 &doL2DescEvent
, (uint8_t*)&l2Desc
.data
, 0);
275 port
->dmaAction(MemCmd::ReadReq
, l2desc_addr
, sizeof(uint32_t),
276 NULL
, (uint8_t*)&l2Desc
.data
, 0);
281 panic("A new type in a 2 bit field?\n");
286 TableWalker::doL2Descriptor()
288 DPRINTF(TLB
, "L2 descriptor for %#x is %#x\n", vaddr
, l2Desc
.data
);
291 if (sctlr
.afe
&& bits(l1Desc
.ap(), 0) == 0)
292 panic("Haven't implemented AFE\n");
294 if (l2Desc
.invalid()) {
295 DPRINTF(TLB
, "L2 descriptor invalid, causing fault\n");
299 fault
= new PrefetchAbort(vaddr
, ArmFault::Translation1
);
301 fault
= new DataAbort(vaddr
, l1Desc
.domain(), isWrite
, ArmFault::Translation1
);
305 if (l2Desc
.large()) {
307 te
.pfn
= l2Desc
.pfn();
310 te
.pfn
= l2Desc
.pfn();
314 te
.size
= (1 << te
.N
) - 1;
317 te
.vpn
= vaddr
>> te
.N
;
318 te
.global
= l2Desc
.global();
321 te
.domain
= l1Desc
.domain();
322 memAttrs(te
, l2Desc
.texcb());
326 tlb
->insert(vaddr
, te
);
329 ArmISA::TableWalker
*
330 ArmTableWalkerParams::create()
332 return new ArmISA::TableWalker(this);