table_walker.cc (8630:05580a8506c7) table_walker.cc (8733:64a7bf8fa56c)
1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
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.
13 *
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.
24 *
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.
36 *
37 * Authors: Ali Saidi
38 */
39
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/TLB.hh"
47#include "debug/TLBVerbose.hh"
48#include "dev/io_device.hh"
49#include "sim/system.hh"
50
51using namespace ArmISA;
52
53TableWalker::TableWalker(const Params *p)
54 : MemObject(p), port(NULL), tlb(NULL), currState(NULL), pending(false),
55 doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this)
56{
57 sctlr = 0;
58}
59
60TableWalker::~TableWalker()
61{
62 ;
63}
64
65
66unsigned int
67TableWalker::drain(Event *de)
68{
69 if (stateQueueL1.size() || stateQueueL2.size() || pendingQueue.size())
70 {
71 changeState(Draining);
72 DPRINTF(Checkpoint, "TableWalker busy, wait to drain\n");
73 return 1;
74 }
75 else
76 {
77 changeState(Drained);
78 DPRINTF(Checkpoint, "TableWalker free, no need to drain\n");
79 return 0;
80 }
81}
82
83void
84TableWalker::resume()
85{
86 MemObject::resume();
87 if ((params()->sys->getMemoryMode() == Enums::timing) && currState) {
88 delete currState;
89 currState = NULL;
90 }
91}
92
93Port*
94TableWalker::getPort(const std::string &if_name, int idx)
95{
96 if (if_name == "port") {
97 if (port != NULL)
98 return port;
99 System *sys = params()->sys;
100 Tick minb = params()->min_backoff;
101 Tick maxb = params()->max_backoff;
102 port = new DmaPort(this, sys, minb, maxb, true);
103 return port;
104 }
105 return NULL;
106}
107
108Fault
109TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode,
1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
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.
13 *
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.
24 *
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.
36 *
37 * Authors: Ali Saidi
38 */
39
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/TLB.hh"
47#include "debug/TLBVerbose.hh"
48#include "dev/io_device.hh"
49#include "sim/system.hh"
50
51using namespace ArmISA;
52
53TableWalker::TableWalker(const Params *p)
54 : MemObject(p), port(NULL), tlb(NULL), currState(NULL), pending(false),
55 doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this)
56{
57 sctlr = 0;
58}
59
60TableWalker::~TableWalker()
61{
62 ;
63}
64
65
66unsigned int
67TableWalker::drain(Event *de)
68{
69 if (stateQueueL1.size() || stateQueueL2.size() || pendingQueue.size())
70 {
71 changeState(Draining);
72 DPRINTF(Checkpoint, "TableWalker busy, wait to drain\n");
73 return 1;
74 }
75 else
76 {
77 changeState(Drained);
78 DPRINTF(Checkpoint, "TableWalker free, no need to drain\n");
79 return 0;
80 }
81}
82
83void
84TableWalker::resume()
85{
86 MemObject::resume();
87 if ((params()->sys->getMemoryMode() == Enums::timing) && currState) {
88 delete currState;
89 currState = NULL;
90 }
91}
92
93Port*
94TableWalker::getPort(const std::string &if_name, int idx)
95{
96 if (if_name == "port") {
97 if (port != NULL)
98 return port;
99 System *sys = params()->sys;
100 Tick minb = params()->min_backoff;
101 Tick maxb = params()->max_backoff;
102 port = new DmaPort(this, sys, minb, maxb, true);
103 return port;
104 }
105 return NULL;
106}
107
108Fault
109TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode,
110 TLB::Translation *_trans, bool _timing)
110 TLB::Translation *_trans, bool _timing, bool _functional)
111{
111{
112 assert(!(_functional && _timing));
112 if (!currState) {
113 // For atomic mode, a new WalkerState instance should be only created
114 // once per TLB. For timing mode, a new instance is generated for every
115 // TLB miss.
116 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
117
118 currState = new WalkerState();
119 currState->tableWalker = this;
120 } else if (_timing) {
121 // This is a translation that was completed and then faulted again
122 // because some underlying parameters that affect the translation
123 // changed out from under us (e.g. asid). It will either be a
124 // misprediction, in which case nothing will happen or we'll use
125 // this fault to re-execute the faulting instruction which should clean
126 // up everything.
127 if (currState->vaddr == _req->getVaddr()) {
128 return new ReExec;
129 }
130 panic("currState should always be empty in timing mode!\n");
131 }
132
133 currState->tc = _tc;
134 currState->transState = _trans;
135 currState->req = _req;
136 currState->fault = NoFault;
137 currState->contextId = _cid;
138 currState->timing = _timing;
113 if (!currState) {
114 // For atomic mode, a new WalkerState instance should be only created
115 // once per TLB. For timing mode, a new instance is generated for every
116 // TLB miss.
117 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n");
118
119 currState = new WalkerState();
120 currState->tableWalker = this;
121 } else if (_timing) {
122 // This is a translation that was completed and then faulted again
123 // because some underlying parameters that affect the translation
124 // changed out from under us (e.g. asid). It will either be a
125 // misprediction, in which case nothing will happen or we'll use
126 // this fault to re-execute the faulting instruction which should clean
127 // up everything.
128 if (currState->vaddr == _req->getVaddr()) {
129 return new ReExec;
130 }
131 panic("currState should always be empty in timing mode!\n");
132 }
133
134 currState->tc = _tc;
135 currState->transState = _trans;
136 currState->req = _req;
137 currState->fault = NoFault;
138 currState->contextId = _cid;
139 currState->timing = _timing;
140 currState->functional = _functional;
139 currState->mode = _mode;
140
141 /** @todo These should be cached or grabbed from cached copies in
142 the TLB, all these miscreg reads are expensive */
143 currState->vaddr = currState->req->getVaddr();
144 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR);
145 sctlr = currState->sctlr;
146 currState->N = currState->tc->readMiscReg(MISCREG_TTBCR);
147
148 currState->isFetch = (currState->mode == TLB::Execute);
149 currState->isWrite = (currState->mode == TLB::Write);
150
151
152 if (!currState->timing)
153 return processWalk();
154
155 if (pending || pendingQueue.size()) {
156 pendingQueue.push_back(currState);
157 currState = NULL;
158 } else {
159 pending = true;
160 return processWalk();
161 }
162
163 return NoFault;
164}
165
166void
167TableWalker::processWalkWrapper()
168{
169 assert(!currState);
170 assert(pendingQueue.size());
171 currState = pendingQueue.front();
172 pendingQueue.pop_front();
173 pending = true;
174 processWalk();
175}
176
177Fault
178TableWalker::processWalk()
179{
180 Addr ttbr = 0;
181
182 // If translation isn't enabled, we shouldn't be here
183 assert(currState->sctlr.m);
184
185 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
186 currState->vaddr, currState->N, mbits(currState->vaddr, 31,
187 32-currState->N));
188
189 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) {
190 DPRINTF(TLB, " - Selecting TTBR0\n");
191 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0);
192 } else {
193 DPRINTF(TLB, " - Selecting TTBR1\n");
194 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1);
195 currState->N = 0;
196 }
197
198 Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) |
199 (bits(currState->vaddr,31-currState->N,20) << 2);
200 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr);
201
202
203 // Trickbox address check
204 Fault f;
205 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t),
206 currState->isFetch, currState->isWrite, 0, true);
207 if (f) {
208 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr);
209 if (currState->timing) {
210 pending = false;
211 nextWalk(currState->tc);
212 currState = NULL;
213 } else {
214 currState->tc = NULL;
215 currState->req = NULL;
216 }
217 return f;
218 }
219
220 Request::Flags flag = 0;
221 if (currState->sctlr.c == 0) {
222 flag = Request::UNCACHEABLE;
223 }
224
225 if (currState->timing) {
226 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
227 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data,
228 currState->tc->getCpuPtr()->ticks(1), flag);
229 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
230 stateQueueL1.size());
231 stateQueueL1.push_back(currState);
232 currState = NULL;
141 currState->mode = _mode;
142
143 /** @todo These should be cached or grabbed from cached copies in
144 the TLB, all these miscreg reads are expensive */
145 currState->vaddr = currState->req->getVaddr();
146 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR);
147 sctlr = currState->sctlr;
148 currState->N = currState->tc->readMiscReg(MISCREG_TTBCR);
149
150 currState->isFetch = (currState->mode == TLB::Execute);
151 currState->isWrite = (currState->mode == TLB::Write);
152
153
154 if (!currState->timing)
155 return processWalk();
156
157 if (pending || pendingQueue.size()) {
158 pendingQueue.push_back(currState);
159 currState = NULL;
160 } else {
161 pending = true;
162 return processWalk();
163 }
164
165 return NoFault;
166}
167
168void
169TableWalker::processWalkWrapper()
170{
171 assert(!currState);
172 assert(pendingQueue.size());
173 currState = pendingQueue.front();
174 pendingQueue.pop_front();
175 pending = true;
176 processWalk();
177}
178
179Fault
180TableWalker::processWalk()
181{
182 Addr ttbr = 0;
183
184 // If translation isn't enabled, we shouldn't be here
185 assert(currState->sctlr.m);
186
187 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
188 currState->vaddr, currState->N, mbits(currState->vaddr, 31,
189 32-currState->N));
190
191 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) {
192 DPRINTF(TLB, " - Selecting TTBR0\n");
193 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0);
194 } else {
195 DPRINTF(TLB, " - Selecting TTBR1\n");
196 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1);
197 currState->N = 0;
198 }
199
200 Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) |
201 (bits(currState->vaddr,31-currState->N,20) << 2);
202 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr);
203
204
205 // Trickbox address check
206 Fault f;
207 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t),
208 currState->isFetch, currState->isWrite, 0, true);
209 if (f) {
210 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr);
211 if (currState->timing) {
212 pending = false;
213 nextWalk(currState->tc);
214 currState = NULL;
215 } else {
216 currState->tc = NULL;
217 currState->req = NULL;
218 }
219 return f;
220 }
221
222 Request::Flags flag = 0;
223 if (currState->sctlr.c == 0) {
224 flag = Request::UNCACHEABLE;
225 }
226
227 if (currState->timing) {
228 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
229 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data,
230 currState->tc->getCpuPtr()->ticks(1), flag);
231 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n",
232 stateQueueL1.size());
233 stateQueueL1.push_back(currState);
234 currState = NULL;
233 } else {
235 } else if (!currState->functional) {
234 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
235 NULL, (uint8_t*)&currState->l1Desc.data,
236 currState->tc->getCpuPtr()->ticks(1), flag);
237 doL1Descriptor();
238 f = currState->fault;
236 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
237 NULL, (uint8_t*)&currState->l1Desc.data,
238 currState->tc->getCpuPtr()->ticks(1), flag);
239 doL1Descriptor();
240 f = currState->fault;
241 } else {
242 RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag);
243 PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
244 pkt->dataStatic((uint8_t*)&currState->l1Desc.data);
245 port->sendFunctional(pkt);
246 doL1Descriptor();
247 delete req;
248 delete pkt;
249 f = currState->fault;
239 }
240
241 return f;
242}
243
244void
245TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
246 uint8_t texcb, bool s)
247{
248 // Note: tc and sctlr local variables are hiding tc and sctrl class
249 // variables
250 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
251 te.shareable = false; // default value
252 te.nonCacheable = false;
253 bool outer_shareable = false;
254 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
255 switch(texcb) {
256 case 0: // Stongly-ordered
257 te.nonCacheable = true;
258 te.mtype = TlbEntry::StronglyOrdered;
259 te.shareable = true;
260 te.innerAttrs = 1;
261 te.outerAttrs = 0;
262 break;
263 case 1: // Shareable Device
264 te.nonCacheable = true;
265 te.mtype = TlbEntry::Device;
266 te.shareable = true;
267 te.innerAttrs = 3;
268 te.outerAttrs = 0;
269 break;
270 case 2: // Outer and Inner Write-Through, no Write-Allocate
271 te.mtype = TlbEntry::Normal;
272 te.shareable = s;
273 te.innerAttrs = 6;
274 te.outerAttrs = bits(texcb, 1, 0);
275 break;
276 case 3: // Outer and Inner Write-Back, no Write-Allocate
277 te.mtype = TlbEntry::Normal;
278 te.shareable = s;
279 te.innerAttrs = 7;
280 te.outerAttrs = bits(texcb, 1, 0);
281 break;
282 case 4: // Outer and Inner Non-cacheable
283 te.nonCacheable = true;
284 te.mtype = TlbEntry::Normal;
285 te.shareable = s;
286 te.innerAttrs = 0;
287 te.outerAttrs = bits(texcb, 1, 0);
288 break;
289 case 5: // Reserved
290 panic("Reserved texcb value!\n");
291 break;
292 case 6: // Implementation Defined
293 panic("Implementation-defined texcb value!\n");
294 break;
295 case 7: // Outer and Inner Write-Back, Write-Allocate
296 te.mtype = TlbEntry::Normal;
297 te.shareable = s;
298 te.innerAttrs = 5;
299 te.outerAttrs = 1;
300 break;
301 case 8: // Non-shareable Device
302 te.nonCacheable = true;
303 te.mtype = TlbEntry::Device;
304 te.shareable = false;
305 te.innerAttrs = 3;
306 te.outerAttrs = 0;
307 break;
308 case 9 ... 15: // Reserved
309 panic("Reserved texcb value!\n");
310 break;
311 case 16 ... 31: // Cacheable Memory
312 te.mtype = TlbEntry::Normal;
313 te.shareable = s;
314 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
315 te.nonCacheable = true;
316 te.innerAttrs = bits(texcb, 1, 0);
317 te.outerAttrs = bits(texcb, 3, 2);
318 break;
319 default:
320 panic("More than 32 states for 5 bits?\n");
321 }
322 } else {
323 assert(tc);
324 PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
325 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
326 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
327 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
328 switch(bits(texcb, 2,0)) {
329 case 0:
330 curr_tr = prrr.tr0;
331 curr_ir = nmrr.ir0;
332 curr_or = nmrr.or0;
333 outer_shareable = (prrr.nos0 == 0);
334 break;
335 case 1:
336 curr_tr = prrr.tr1;
337 curr_ir = nmrr.ir1;
338 curr_or = nmrr.or1;
339 outer_shareable = (prrr.nos1 == 0);
340 break;
341 case 2:
342 curr_tr = prrr.tr2;
343 curr_ir = nmrr.ir2;
344 curr_or = nmrr.or2;
345 outer_shareable = (prrr.nos2 == 0);
346 break;
347 case 3:
348 curr_tr = prrr.tr3;
349 curr_ir = nmrr.ir3;
350 curr_or = nmrr.or3;
351 outer_shareable = (prrr.nos3 == 0);
352 break;
353 case 4:
354 curr_tr = prrr.tr4;
355 curr_ir = nmrr.ir4;
356 curr_or = nmrr.or4;
357 outer_shareable = (prrr.nos4 == 0);
358 break;
359 case 5:
360 curr_tr = prrr.tr5;
361 curr_ir = nmrr.ir5;
362 curr_or = nmrr.or5;
363 outer_shareable = (prrr.nos5 == 0);
364 break;
365 case 6:
366 panic("Imp defined type\n");
367 case 7:
368 curr_tr = prrr.tr7;
369 curr_ir = nmrr.ir7;
370 curr_or = nmrr.or7;
371 outer_shareable = (prrr.nos7 == 0);
372 break;
373 }
374
375 switch(curr_tr) {
376 case 0:
377 DPRINTF(TLBVerbose, "StronglyOrdered\n");
378 te.mtype = TlbEntry::StronglyOrdered;
379 te.nonCacheable = true;
380 te.innerAttrs = 1;
381 te.outerAttrs = 0;
382 te.shareable = true;
383 break;
384 case 1:
385 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
386 prrr.ds1, prrr.ds0, s);
387 te.mtype = TlbEntry::Device;
388 te.nonCacheable = true;
389 te.innerAttrs = 3;
390 te.outerAttrs = 0;
391 if (prrr.ds1 && s)
392 te.shareable = true;
393 if (prrr.ds0 && !s)
394 te.shareable = true;
395 break;
396 case 2:
397 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
398 prrr.ns1, prrr.ns0, s);
399 te.mtype = TlbEntry::Normal;
400 if (prrr.ns1 && s)
401 te.shareable = true;
402 if (prrr.ns0 && !s)
403 te.shareable = true;
404 break;
405 case 3:
406 panic("Reserved type");
407 }
408
409 if (te.mtype == TlbEntry::Normal){
410 switch(curr_ir) {
411 case 0:
412 te.nonCacheable = true;
413 te.innerAttrs = 0;
414 break;
415 case 1:
416 te.innerAttrs = 5;
417 break;
418 case 2:
419 te.innerAttrs = 6;
420 break;
421 case 3:
422 te.innerAttrs = 7;
423 break;
424 }
425
426 switch(curr_or) {
427 case 0:
428 te.nonCacheable = true;
429 te.outerAttrs = 0;
430 break;
431 case 1:
432 te.outerAttrs = 1;
433 break;
434 case 2:
435 te.outerAttrs = 2;
436 break;
437 case 3:
438 te.outerAttrs = 3;
439 break;
440 }
441 }
442 }
443 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \
444 outerAttrs: %d\n",
445 te.shareable, te.innerAttrs, te.outerAttrs);
446
447 /** Formatting for Physical Address Register (PAR)
448 * Only including lower bits (TLB info here)
449 * PAR:
450 * PA [31:12]
451 * Reserved [11]
452 * TLB info [10:1]
453 * NOS [10] (Not Outer Sharable)
454 * NS [9] (Non-Secure)
455 * -- [8] (Implementation Defined)
456 * SH [7] (Sharable)
457 * Inner[6:4](Inner memory attributes)
458 * Outer[3:2](Outer memory attributes)
459 * SS [1] (SuperSection)
460 * F [0] (Fault, Fault Status in [6:1] if faulted)
461 */
462 te.attributes = (
463 ((outer_shareable ? 0:1) << 10) |
464 // TODO: NS Bit
465 ((te.shareable ? 1:0) << 7) |
466 (te.innerAttrs << 4) |
467 (te.outerAttrs << 2)
468 // TODO: Supersection bit
469 // TODO: Fault bit
470 );
471
472
473}
474
475void
476TableWalker::doL1Descriptor()
477{
478 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
479 currState->vaddr, currState->l1Desc.data);
480 TlbEntry te;
481
482 switch (currState->l1Desc.type()) {
483 case L1Descriptor::Ignore:
484 case L1Descriptor::Reserved:
485 if (!currState->timing) {
486 currState->tc = NULL;
487 currState->req = NULL;
488 }
489 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
490 if (currState->isFetch)
491 currState->fault =
492 new PrefetchAbort(currState->vaddr, ArmFault::Translation0);
493 else
494 currState->fault =
495 new DataAbort(currState->vaddr, 0, currState->isWrite,
496 ArmFault::Translation0);
497 return;
498 case L1Descriptor::Section:
499 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
500 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
501 * enabled if set, do l1.Desc.setAp0() instead of generating
502 * AccessFlag0
503 */
504
505 currState->fault = new DataAbort(currState->vaddr,
506 currState->l1Desc.domain(), currState->isWrite,
507 ArmFault::AccessFlag0);
508 }
509 if (currState->l1Desc.supersection()) {
510 panic("Haven't implemented supersections\n");
511 }
512 te.N = 20;
513 te.pfn = currState->l1Desc.pfn();
514 te.size = (1<<te.N) - 1;
515 te.global = !currState->l1Desc.global();
516 te.valid = true;
517 te.vpn = currState->vaddr >> te.N;
518 te.sNp = true;
519 te.xn = currState->l1Desc.xn();
520 te.ap = currState->l1Desc.ap();
521 te.domain = currState->l1Desc.domain();
522 te.asid = currState->contextId;
523 memAttrs(currState->tc, te, currState->sctlr,
524 currState->l1Desc.texcb(), currState->l1Desc.shareable());
525
526 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n");
527 DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n",
528 te.N, te.pfn, te.size, te.global, te.valid);
529 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n",
530 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid,
531 te.nonCacheable);
532 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
533 currState->l1Desc.domain(), currState->l1Desc.data,
534 (currState->l1Desc.data >> 5) & 0xF );
535
536 if (!currState->timing) {
537 currState->tc = NULL;
538 currState->req = NULL;
539 }
540 tlb->insert(currState->vaddr, te);
541
542 return;
543 case L1Descriptor::PageTable:
544 Addr l2desc_addr;
545 l2desc_addr = currState->l1Desc.l2Addr() |
546 (bits(currState->vaddr, 19,12) << 2);
547 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n",
548 l2desc_addr);
549
550 // Trickbox address check
551 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr,
552 sizeof(uint32_t), currState->isFetch, currState->isWrite,
553 currState->l1Desc.domain(), false);
554
555 if (currState->fault) {
556 if (!currState->timing) {
557 currState->tc = NULL;
558 currState->req = NULL;
559 }
560 return;
561 }
562
563
564 if (currState->timing) {
565 currState->delayed = true;
566 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
567 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
568 currState->tc->getCpuPtr()->ticks(1));
250 }
251
252 return f;
253}
254
255void
256TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr,
257 uint8_t texcb, bool s)
258{
259 // Note: tc and sctlr local variables are hiding tc and sctrl class
260 // variables
261 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
262 te.shareable = false; // default value
263 te.nonCacheable = false;
264 bool outer_shareable = false;
265 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) {
266 switch(texcb) {
267 case 0: // Stongly-ordered
268 te.nonCacheable = true;
269 te.mtype = TlbEntry::StronglyOrdered;
270 te.shareable = true;
271 te.innerAttrs = 1;
272 te.outerAttrs = 0;
273 break;
274 case 1: // Shareable Device
275 te.nonCacheable = true;
276 te.mtype = TlbEntry::Device;
277 te.shareable = true;
278 te.innerAttrs = 3;
279 te.outerAttrs = 0;
280 break;
281 case 2: // Outer and Inner Write-Through, no Write-Allocate
282 te.mtype = TlbEntry::Normal;
283 te.shareable = s;
284 te.innerAttrs = 6;
285 te.outerAttrs = bits(texcb, 1, 0);
286 break;
287 case 3: // Outer and Inner Write-Back, no Write-Allocate
288 te.mtype = TlbEntry::Normal;
289 te.shareable = s;
290 te.innerAttrs = 7;
291 te.outerAttrs = bits(texcb, 1, 0);
292 break;
293 case 4: // Outer and Inner Non-cacheable
294 te.nonCacheable = true;
295 te.mtype = TlbEntry::Normal;
296 te.shareable = s;
297 te.innerAttrs = 0;
298 te.outerAttrs = bits(texcb, 1, 0);
299 break;
300 case 5: // Reserved
301 panic("Reserved texcb value!\n");
302 break;
303 case 6: // Implementation Defined
304 panic("Implementation-defined texcb value!\n");
305 break;
306 case 7: // Outer and Inner Write-Back, Write-Allocate
307 te.mtype = TlbEntry::Normal;
308 te.shareable = s;
309 te.innerAttrs = 5;
310 te.outerAttrs = 1;
311 break;
312 case 8: // Non-shareable Device
313 te.nonCacheable = true;
314 te.mtype = TlbEntry::Device;
315 te.shareable = false;
316 te.innerAttrs = 3;
317 te.outerAttrs = 0;
318 break;
319 case 9 ... 15: // Reserved
320 panic("Reserved texcb value!\n");
321 break;
322 case 16 ... 31: // Cacheable Memory
323 te.mtype = TlbEntry::Normal;
324 te.shareable = s;
325 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
326 te.nonCacheable = true;
327 te.innerAttrs = bits(texcb, 1, 0);
328 te.outerAttrs = bits(texcb, 3, 2);
329 break;
330 default:
331 panic("More than 32 states for 5 bits?\n");
332 }
333 } else {
334 assert(tc);
335 PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
336 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
337 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
338 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0;
339 switch(bits(texcb, 2,0)) {
340 case 0:
341 curr_tr = prrr.tr0;
342 curr_ir = nmrr.ir0;
343 curr_or = nmrr.or0;
344 outer_shareable = (prrr.nos0 == 0);
345 break;
346 case 1:
347 curr_tr = prrr.tr1;
348 curr_ir = nmrr.ir1;
349 curr_or = nmrr.or1;
350 outer_shareable = (prrr.nos1 == 0);
351 break;
352 case 2:
353 curr_tr = prrr.tr2;
354 curr_ir = nmrr.ir2;
355 curr_or = nmrr.or2;
356 outer_shareable = (prrr.nos2 == 0);
357 break;
358 case 3:
359 curr_tr = prrr.tr3;
360 curr_ir = nmrr.ir3;
361 curr_or = nmrr.or3;
362 outer_shareable = (prrr.nos3 == 0);
363 break;
364 case 4:
365 curr_tr = prrr.tr4;
366 curr_ir = nmrr.ir4;
367 curr_or = nmrr.or4;
368 outer_shareable = (prrr.nos4 == 0);
369 break;
370 case 5:
371 curr_tr = prrr.tr5;
372 curr_ir = nmrr.ir5;
373 curr_or = nmrr.or5;
374 outer_shareable = (prrr.nos5 == 0);
375 break;
376 case 6:
377 panic("Imp defined type\n");
378 case 7:
379 curr_tr = prrr.tr7;
380 curr_ir = nmrr.ir7;
381 curr_or = nmrr.or7;
382 outer_shareable = (prrr.nos7 == 0);
383 break;
384 }
385
386 switch(curr_tr) {
387 case 0:
388 DPRINTF(TLBVerbose, "StronglyOrdered\n");
389 te.mtype = TlbEntry::StronglyOrdered;
390 te.nonCacheable = true;
391 te.innerAttrs = 1;
392 te.outerAttrs = 0;
393 te.shareable = true;
394 break;
395 case 1:
396 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
397 prrr.ds1, prrr.ds0, s);
398 te.mtype = TlbEntry::Device;
399 te.nonCacheable = true;
400 te.innerAttrs = 3;
401 te.outerAttrs = 0;
402 if (prrr.ds1 && s)
403 te.shareable = true;
404 if (prrr.ds0 && !s)
405 te.shareable = true;
406 break;
407 case 2:
408 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
409 prrr.ns1, prrr.ns0, s);
410 te.mtype = TlbEntry::Normal;
411 if (prrr.ns1 && s)
412 te.shareable = true;
413 if (prrr.ns0 && !s)
414 te.shareable = true;
415 break;
416 case 3:
417 panic("Reserved type");
418 }
419
420 if (te.mtype == TlbEntry::Normal){
421 switch(curr_ir) {
422 case 0:
423 te.nonCacheable = true;
424 te.innerAttrs = 0;
425 break;
426 case 1:
427 te.innerAttrs = 5;
428 break;
429 case 2:
430 te.innerAttrs = 6;
431 break;
432 case 3:
433 te.innerAttrs = 7;
434 break;
435 }
436
437 switch(curr_or) {
438 case 0:
439 te.nonCacheable = true;
440 te.outerAttrs = 0;
441 break;
442 case 1:
443 te.outerAttrs = 1;
444 break;
445 case 2:
446 te.outerAttrs = 2;
447 break;
448 case 3:
449 te.outerAttrs = 3;
450 break;
451 }
452 }
453 }
454 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \
455 outerAttrs: %d\n",
456 te.shareable, te.innerAttrs, te.outerAttrs);
457
458 /** Formatting for Physical Address Register (PAR)
459 * Only including lower bits (TLB info here)
460 * PAR:
461 * PA [31:12]
462 * Reserved [11]
463 * TLB info [10:1]
464 * NOS [10] (Not Outer Sharable)
465 * NS [9] (Non-Secure)
466 * -- [8] (Implementation Defined)
467 * SH [7] (Sharable)
468 * Inner[6:4](Inner memory attributes)
469 * Outer[3:2](Outer memory attributes)
470 * SS [1] (SuperSection)
471 * F [0] (Fault, Fault Status in [6:1] if faulted)
472 */
473 te.attributes = (
474 ((outer_shareable ? 0:1) << 10) |
475 // TODO: NS Bit
476 ((te.shareable ? 1:0) << 7) |
477 (te.innerAttrs << 4) |
478 (te.outerAttrs << 2)
479 // TODO: Supersection bit
480 // TODO: Fault bit
481 );
482
483
484}
485
486void
487TableWalker::doL1Descriptor()
488{
489 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n",
490 currState->vaddr, currState->l1Desc.data);
491 TlbEntry te;
492
493 switch (currState->l1Desc.type()) {
494 case L1Descriptor::Ignore:
495 case L1Descriptor::Reserved:
496 if (!currState->timing) {
497 currState->tc = NULL;
498 currState->req = NULL;
499 }
500 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
501 if (currState->isFetch)
502 currState->fault =
503 new PrefetchAbort(currState->vaddr, ArmFault::Translation0);
504 else
505 currState->fault =
506 new DataAbort(currState->vaddr, 0, currState->isWrite,
507 ArmFault::Translation0);
508 return;
509 case L1Descriptor::Section:
510 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) {
511 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
512 * enabled if set, do l1.Desc.setAp0() instead of generating
513 * AccessFlag0
514 */
515
516 currState->fault = new DataAbort(currState->vaddr,
517 currState->l1Desc.domain(), currState->isWrite,
518 ArmFault::AccessFlag0);
519 }
520 if (currState->l1Desc.supersection()) {
521 panic("Haven't implemented supersections\n");
522 }
523 te.N = 20;
524 te.pfn = currState->l1Desc.pfn();
525 te.size = (1<<te.N) - 1;
526 te.global = !currState->l1Desc.global();
527 te.valid = true;
528 te.vpn = currState->vaddr >> te.N;
529 te.sNp = true;
530 te.xn = currState->l1Desc.xn();
531 te.ap = currState->l1Desc.ap();
532 te.domain = currState->l1Desc.domain();
533 te.asid = currState->contextId;
534 memAttrs(currState->tc, te, currState->sctlr,
535 currState->l1Desc.texcb(), currState->l1Desc.shareable());
536
537 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n");
538 DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n",
539 te.N, te.pfn, te.size, te.global, te.valid);
540 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n",
541 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid,
542 te.nonCacheable);
543 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
544 currState->l1Desc.domain(), currState->l1Desc.data,
545 (currState->l1Desc.data >> 5) & 0xF );
546
547 if (!currState->timing) {
548 currState->tc = NULL;
549 currState->req = NULL;
550 }
551 tlb->insert(currState->vaddr, te);
552
553 return;
554 case L1Descriptor::PageTable:
555 Addr l2desc_addr;
556 l2desc_addr = currState->l1Desc.l2Addr() |
557 (bits(currState->vaddr, 19,12) << 2);
558 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n",
559 l2desc_addr);
560
561 // Trickbox address check
562 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr,
563 sizeof(uint32_t), currState->isFetch, currState->isWrite,
564 currState->l1Desc.domain(), false);
565
566 if (currState->fault) {
567 if (!currState->timing) {
568 currState->tc = NULL;
569 currState->req = NULL;
570 }
571 return;
572 }
573
574
575 if (currState->timing) {
576 currState->delayed = true;
577 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
578 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data,
579 currState->tc->getCpuPtr()->ticks(1));
569 } else {
580 } else if (!currState->functional) {
570 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
571 NULL, (uint8_t*)&currState->l2Desc.data,
572 currState->tc->getCpuPtr()->ticks(1));
573 doL2Descriptor();
581 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
582 NULL, (uint8_t*)&currState->l2Desc.data,
583 currState->tc->getCpuPtr()->ticks(1));
584 doL2Descriptor();
585 } else {
586 RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0);
587 PacketPtr pkt = new Packet(req, MemCmd::ReadReq, Packet::Broadcast);
588 pkt->dataStatic((uint8_t*)&currState->l2Desc.data);
589 port->sendFunctional(pkt);
590 doL2Descriptor();
591 delete req;
592 delete pkt;
574 }
575 return;
576 default:
577 panic("A new type in a 2 bit field?\n");
578 }
579}
580
581void
582TableWalker::doL2Descriptor()
583{
584 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
585 currState->vaddr, currState->l2Desc.data);
586 TlbEntry te;
587
588 if (currState->l2Desc.invalid()) {
589 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
590 if (!currState->timing) {
591 currState->tc = NULL;
592 currState->req = NULL;
593 }
594 if (currState->isFetch)
595 currState->fault =
596 new PrefetchAbort(currState->vaddr, ArmFault::Translation1);
597 else
598 currState->fault =
599 new DataAbort(currState->vaddr, currState->l1Desc.domain(),
600 currState->isWrite, ArmFault::Translation1);
601 return;
602 }
603
604 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
605 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
606 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
607 */
608
609 currState->fault =
610 new DataAbort(currState->vaddr, 0, currState->isWrite,
611 ArmFault::AccessFlag1);
612
613 }
614
615 if (currState->l2Desc.large()) {
616 te.N = 16;
617 te.pfn = currState->l2Desc.pfn();
618 } else {
619 te.N = 12;
620 te.pfn = currState->l2Desc.pfn();
621 }
622
623 te.valid = true;
624 te.size = (1 << te.N) - 1;
625 te.asid = currState->contextId;
626 te.sNp = false;
627 te.vpn = currState->vaddr >> te.N;
628 te.global = currState->l2Desc.global();
629 te.xn = currState->l2Desc.xn();
630 te.ap = currState->l2Desc.ap();
631 te.domain = currState->l1Desc.domain();
632 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(),
633 currState->l2Desc.shareable());
634
635 if (!currState->timing) {
636 currState->tc = NULL;
637 currState->req = NULL;
638 }
639 tlb->insert(currState->vaddr, te);
640}
641
642void
643TableWalker::doL1DescriptorWrapper()
644{
645 currState = stateQueueL1.front();
646 currState->delayed = false;
647
648 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
649 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data);
650
651 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr);
652 doL1Descriptor();
653
654 stateQueueL1.pop_front();
655 // Check if fault was generated
656 if (currState->fault != NoFault) {
657 currState->transState->finish(currState->fault, currState->req,
658 currState->tc, currState->mode);
659
660 pending = false;
661 nextWalk(currState->tc);
662
663 currState->req = NULL;
664 currState->tc = NULL;
665 currState->delayed = false;
666 delete currState;
667 }
668 else if (!currState->delayed) {
669 // delay is not set so there is no L2 to do
670 DPRINTF(TLBVerbose, "calling translateTiming again\n");
671 currState->fault = tlb->translateTiming(currState->req, currState->tc,
672 currState->transState, currState->mode);
673
674 pending = false;
675 nextWalk(currState->tc);
676
677 currState->req = NULL;
678 currState->tc = NULL;
679 currState->delayed = false;
680 delete currState;
681 } else {
682 // need to do L2 descriptor
683 stateQueueL2.push_back(currState);
684 }
685 currState = NULL;
686}
687
688void
689TableWalker::doL2DescriptorWrapper()
690{
691 currState = stateQueueL2.front();
692 assert(currState->delayed);
693
694 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
695 currState->vaddr);
696 doL2Descriptor();
697
698 // Check if fault was generated
699 if (currState->fault != NoFault) {
700 currState->transState->finish(currState->fault, currState->req,
701 currState->tc, currState->mode);
702 }
703 else {
704 DPRINTF(TLBVerbose, "calling translateTiming again\n");
705 currState->fault = tlb->translateTiming(currState->req, currState->tc,
706 currState->transState, currState->mode);
707 }
708
709
710 stateQueueL2.pop_front();
711 pending = false;
712 nextWalk(currState->tc);
713
714 currState->req = NULL;
715 currState->tc = NULL;
716 currState->delayed = false;
717
718 delete currState;
719 currState = NULL;
720}
721
722void
723TableWalker::nextWalk(ThreadContext *tc)
724{
725 if (pendingQueue.size())
726 schedule(doProcessEvent, tc->getCpuPtr()->nextCycle(curTick()+1));
727}
728
729
730
731ArmISA::TableWalker *
732ArmTableWalkerParams::create()
733{
734 return new ArmISA::TableWalker(this);
735}
736
593 }
594 return;
595 default:
596 panic("A new type in a 2 bit field?\n");
597 }
598}
599
600void
601TableWalker::doL2Descriptor()
602{
603 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n",
604 currState->vaddr, currState->l2Desc.data);
605 TlbEntry te;
606
607 if (currState->l2Desc.invalid()) {
608 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
609 if (!currState->timing) {
610 currState->tc = NULL;
611 currState->req = NULL;
612 }
613 if (currState->isFetch)
614 currState->fault =
615 new PrefetchAbort(currState->vaddr, ArmFault::Translation1);
616 else
617 currState->fault =
618 new DataAbort(currState->vaddr, currState->l1Desc.domain(),
619 currState->isWrite, ArmFault::Translation1);
620 return;
621 }
622
623 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) {
624 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
625 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
626 */
627
628 currState->fault =
629 new DataAbort(currState->vaddr, 0, currState->isWrite,
630 ArmFault::AccessFlag1);
631
632 }
633
634 if (currState->l2Desc.large()) {
635 te.N = 16;
636 te.pfn = currState->l2Desc.pfn();
637 } else {
638 te.N = 12;
639 te.pfn = currState->l2Desc.pfn();
640 }
641
642 te.valid = true;
643 te.size = (1 << te.N) - 1;
644 te.asid = currState->contextId;
645 te.sNp = false;
646 te.vpn = currState->vaddr >> te.N;
647 te.global = currState->l2Desc.global();
648 te.xn = currState->l2Desc.xn();
649 te.ap = currState->l2Desc.ap();
650 te.domain = currState->l1Desc.domain();
651 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(),
652 currState->l2Desc.shareable());
653
654 if (!currState->timing) {
655 currState->tc = NULL;
656 currState->req = NULL;
657 }
658 tlb->insert(currState->vaddr, te);
659}
660
661void
662TableWalker::doL1DescriptorWrapper()
663{
664 currState = stateQueueL1.front();
665 currState->delayed = false;
666
667 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data);
668 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data);
669
670 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr);
671 doL1Descriptor();
672
673 stateQueueL1.pop_front();
674 // Check if fault was generated
675 if (currState->fault != NoFault) {
676 currState->transState->finish(currState->fault, currState->req,
677 currState->tc, currState->mode);
678
679 pending = false;
680 nextWalk(currState->tc);
681
682 currState->req = NULL;
683 currState->tc = NULL;
684 currState->delayed = false;
685 delete currState;
686 }
687 else if (!currState->delayed) {
688 // delay is not set so there is no L2 to do
689 DPRINTF(TLBVerbose, "calling translateTiming again\n");
690 currState->fault = tlb->translateTiming(currState->req, currState->tc,
691 currState->transState, currState->mode);
692
693 pending = false;
694 nextWalk(currState->tc);
695
696 currState->req = NULL;
697 currState->tc = NULL;
698 currState->delayed = false;
699 delete currState;
700 } else {
701 // need to do L2 descriptor
702 stateQueueL2.push_back(currState);
703 }
704 currState = NULL;
705}
706
707void
708TableWalker::doL2DescriptorWrapper()
709{
710 currState = stateQueueL2.front();
711 assert(currState->delayed);
712
713 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n",
714 currState->vaddr);
715 doL2Descriptor();
716
717 // Check if fault was generated
718 if (currState->fault != NoFault) {
719 currState->transState->finish(currState->fault, currState->req,
720 currState->tc, currState->mode);
721 }
722 else {
723 DPRINTF(TLBVerbose, "calling translateTiming again\n");
724 currState->fault = tlb->translateTiming(currState->req, currState->tc,
725 currState->transState, currState->mode);
726 }
727
728
729 stateQueueL2.pop_front();
730 pending = false;
731 nextWalk(currState->tc);
732
733 currState->req = NULL;
734 currState->tc = NULL;
735 currState->delayed = false;
736
737 delete currState;
738 currState = NULL;
739}
740
741void
742TableWalker::nextWalk(ThreadContext *tc)
743{
744 if (pendingQueue.size())
745 schedule(doProcessEvent, tc->getCpuPtr()->nextCycle(curTick()+1));
746}
747
748
749
750ArmISA::TableWalker *
751ArmTableWalkerParams::create()
752{
753 return new ArmISA::TableWalker(this);
754}
755