table_walker.cc (7406:ddc26bd4ea7d) table_walker.cc (7436:b578349f9371)
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

--- 82 unchanged lines hidden (view full) ---

91
92 tc = _tc;
93 transState = _trans;
94 req = _req;
95 fault = NoFault;
96 contextId = _cid;
97 timing = _timing;
98
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

--- 82 unchanged lines hidden (view full) ---

91
92 tc = _tc;
93 transState = _trans;
94 req = _req;
95 fault = NoFault;
96 contextId = _cid;
97 timing = _timing;
98
99 // XXX These should be cached or grabbed from cached copies in
100 // the TLB, all these miscreg reads are expensive
99 /** @todo 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);
105 Addr ttbr = 0;
106
107 isFetch = (mode == TLB::Execute);
108 isWrite = (mode == TLB::Write);

--- 35 unchanged lines hidden (view full) ---

144 NULL, (uint8_t*)&l1Desc.data, (Tick)0);
145 doL1Descriptor();
146 }
147
148 return fault;
149}
150
151void
101 vaddr = req->getVaddr() & ~PcModeMask;
102 sctlr = tc->readMiscReg(MISCREG_SCTLR);
103 cpsr = tc->readMiscReg(MISCREG_CPSR);
104 N = tc->readMiscReg(MISCREG_TTBCR);
105 Addr ttbr = 0;
106
107 isFetch = (mode == TLB::Execute);
108 isWrite = (mode == TLB::Write);

--- 35 unchanged lines hidden (view full) ---

144 NULL, (uint8_t*)&l1Desc.data, (Tick)0);
145 doL1Descriptor();
146 }
147
148 return fault;
149}
150
151void
152TableWalker::memAttrs(TlbEntry &te, uint8_t texcb)
152TableWalker::memAttrs(TlbEntry &te, uint8_t texcb, bool s)
153{
153{
154
154 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s);
155 te.shareable = false; // default value
156 bool outer_shareable = false;
155 if (sctlr.tre == 0) {
156 switch(texcb) {
157 if (sctlr.tre == 0) {
158 switch(texcb) {
157 case 0:
158 case 1:
159 case 4:
160 case 8:
159 case 0: // Stongly-ordered
161 te.nonCacheable = true;
160 te.nonCacheable = true;
161 te.mtype = TlbEntry::StronglyOrdered;
162 te.shareable = true;
163 te.innerAttrs = 1;
164 te.outerAttrs = 0;
162 break;
165 break;
163 case 16:
166 case 1: // Shareable Device
167 te.nonCacheable = true;
168 te.mtype = TlbEntry::Device;
169 te.shareable = true;
170 te.innerAttrs = 3;
171 te.outerAttrs = 0;
172 break;
173 case 2: // Outer and Inner Write-Through, no Write-Allocate
174 te.mtype = TlbEntry::Normal;
175 te.shareable = s;
176 te.innerAttrs = 6;
177 te.outerAttrs = bits(texcb, 1, 0);
178 break;
179 case 3: // Outer and Inner Write-Back, no Write-Allocate
180 te.mtype = TlbEntry::Normal;
181 te.shareable = s;
182 te.innerAttrs = 7;
183 te.outerAttrs = bits(texcb, 1, 0);
184 break;
185 case 4: // Outer and Inner Non-cacheable
186 te.nonCacheable = true;
187 te.mtype = TlbEntry::Normal;
188 te.shareable = s;
189 te.innerAttrs = 0;
190 te.outerAttrs = bits(texcb, 1, 0);
191 break;
192 case 5: // Reserved
193 break;
194 case 6: // Implementation Defined
195 break;
196 case 7: // Outer and Inner Write-Back, Write-Allocate
197 te.mtype = TlbEntry::Normal;
198 te.shareable = s;
199 te.innerAttrs = 5;
200 te.outerAttrs = 1;
201 break;
202 case 8: // Non-shareable Device
203 te.nonCacheable = true;
204 te.mtype = TlbEntry::Device;
205 te.shareable = false;
206 te.innerAttrs = 3;
207 te.outerAttrs = 0;
208 break;
209 case 9 ... 15: // Reserved
210 break;
211 case 16 ... 31: // Cacheable Memory
212 te.mtype = TlbEntry::Normal;
213 te.shareable = s;
164 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
165 te.nonCacheable = true;
214 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0)
215 te.nonCacheable = true;
216 te.innerAttrs = bits(texcb, 1, 0);
217 te.outerAttrs = bits(texcb, 3, 2);
166 break;
218 break;
219 default:
220 panic("More than 32 states for 5 bits?\n");
167 }
168 } else {
169 PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
170 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
221 }
222 } else {
223 PRRR prrr = tc->readMiscReg(MISCREG_PRRR);
224 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR);
225 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr);
226 uint8_t curr_tr, curr_ir, curr_or;
171 switch(bits(texcb, 2,0)) {
172 case 0:
227 switch(bits(texcb, 2,0)) {
228 case 0:
173 if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2)
174 te.nonCacheable = true;
229 curr_tr = prrr.tr0;
230 curr_ir = nmrr.ir0;
231 curr_or = nmrr.or0;
232 outer_shareable = (prrr.nos0 == 0);
175 break;
176 case 1:
233 break;
234 case 1:
177 if (nmrr.ir1 == 0 || nmrr.or1 == 0 || prrr.tr1 != 0x2)
178 te.nonCacheable = true;
235 curr_tr = prrr.tr1;
236 curr_ir = nmrr.ir1;
237 curr_or = nmrr.or1;
238 outer_shareable = (prrr.nos1 == 0);
179 break;
180 case 2:
239 break;
240 case 2:
181 if (nmrr.ir2 == 0 || nmrr.or2 == 0 || prrr.tr2 != 0x2)
182 te.nonCacheable = true;
241 curr_tr = prrr.tr2;
242 curr_ir = nmrr.ir2;
243 curr_or = nmrr.or2;
244 outer_shareable = (prrr.nos2 == 0);
183 break;
184 case 3:
245 break;
246 case 3:
185 if (nmrr.ir3 == 0 || nmrr.or3 == 0 || prrr.tr3 != 0x2)
186 te.nonCacheable = true;
247 curr_tr = prrr.tr3;
248 curr_ir = nmrr.ir3;
249 curr_or = nmrr.or3;
250 outer_shareable = (prrr.nos3 == 0);
187 break;
188 case 4:
251 break;
252 case 4:
189 if (nmrr.ir4 == 0 || nmrr.or4 == 0 || prrr.tr4 != 0x2)
190 te.nonCacheable = true;
253 curr_tr = prrr.tr4;
254 curr_ir = nmrr.ir4;
255 curr_or = nmrr.or4;
256 outer_shareable = (prrr.nos4 == 0);
191 break;
192 case 5:
257 break;
258 case 5:
193 if (nmrr.ir5 == 0 || nmrr.or5 == 0 || prrr.tr5 != 0x2)
194 te.nonCacheable = true;
259 curr_tr = prrr.tr5;
260 curr_ir = nmrr.ir5;
261 curr_or = nmrr.or5;
262 outer_shareable = (prrr.nos5 == 0);
195 break;
196 case 6:
197 panic("Imp defined type\n");
198 case 7:
263 break;
264 case 6:
265 panic("Imp defined type\n");
266 case 7:
199 if (nmrr.ir7 == 0 || nmrr.or7 == 0 || prrr.tr7 != 0x2)
200 te.nonCacheable = true;
267 curr_tr = prrr.tr7;
268 curr_ir = nmrr.ir7;
269 curr_or = nmrr.or7;
270 outer_shareable = (prrr.nos7 == 0);
201 break;
202 }
271 break;
272 }
273
274 switch(curr_tr) {
275 case 0:
276 DPRINTF(TLBVerbose, "StronglyOrdered\n");
277 te.mtype = TlbEntry::StronglyOrdered;
278 te.nonCacheable = true;
279 te.innerAttrs = 1;
280 te.outerAttrs = 0;
281 te.shareable = true;
282 break;
283 case 1:
284 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n",
285 prrr.ds1, prrr.ds0, s);
286 te.mtype = TlbEntry::Device;
287 te.nonCacheable = true;
288 te.innerAttrs = 3;
289 te.outerAttrs = 0;
290 if (prrr.ds1 && s)
291 te.shareable = true;
292 if (prrr.ds0 && !s)
293 te.shareable = true;
294 break;
295 case 2:
296 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n",
297 prrr.ns1, prrr.ns0, s);
298 te.mtype = TlbEntry::Normal;
299 if (prrr.ns1 && s)
300 te.shareable = true;
301 if (prrr.ns0 && !s)
302 te.shareable = true;
303 //te.shareable = outer_shareable;
304 break;
305 case 3:
306 panic("Reserved type");
307 }
308
309 if (te.mtype == TlbEntry::Normal){
310 switch(curr_ir) {
311 case 0:
312 te.nonCacheable = true;
313 te.innerAttrs = 0;
314 break;
315 case 1:
316 te.innerAttrs = 5;
317 break;
318 case 2:
319 te.innerAttrs = 6;
320 break;
321 case 3:
322 te.innerAttrs = 7;
323 break;
324 }
325
326 switch(curr_or) {
327 case 0:
328 te.nonCacheable = true;
329 te.outerAttrs = 0;
330 break;
331 case 1:
332 te.outerAttrs = 1;
333 break;
334 case 2:
335 te.outerAttrs = 2;
336 break;
337 case 3:
338 te.outerAttrs = 3;
339 break;
340 }
341 }
203 }
342 }
343
344 /** Formatting for Physical Address Register (PAR)
345 * Only including lower bits (TLB info here)
346 * PAR:
347 * PA [31:12]
348 * Reserved [11]
349 * TLB info [10:1]
350 * NOS [10] (Not Outer Sharable)
351 * NS [9] (Non-Secure)
352 * -- [8] (Implementation Defined)
353 * SH [7] (Sharable)
354 * Inner[6:4](Inner memory attributes)
355 * Outer[3:2](Outer memory attributes)
356 * SS [1] (SuperSection)
357 * F [0] (Fault, Fault Status in [6:1] if faulted)
358 */
359 te.attributes = (
360 ((outer_shareable ? 0:1) << 10) |
361 // TODO: NS Bit
362 ((te.shareable ? 1:0) << 7) |
363 (te.innerAttrs << 4) |
364 (te.outerAttrs << 2)
365 // TODO: Supersection bit
366 // TODO: Fault bit
367 );
368
369
204}
205
206void
207TableWalker::doL1Descriptor()
208{
209 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", vaddr, l1Desc.data);
210 TlbEntry te;
211
212 switch (l1Desc.type()) {
213 case L1Descriptor::Ignore:
214 case L1Descriptor::Reserved:
215 tc = NULL;
216 req = NULL;
217 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
218 if (isFetch)
219 fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
220 else
370}
371
372void
373TableWalker::doL1Descriptor()
374{
375 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", vaddr, l1Desc.data);
376 TlbEntry te;
377
378 switch (l1Desc.type()) {
379 case L1Descriptor::Ignore:
380 case L1Descriptor::Reserved:
381 tc = NULL;
382 req = NULL;
383 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
384 if (isFetch)
385 fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
386 else
221 fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::Translation0);
387 fault = new DataAbort(vaddr, NULL, isWrite,
388 ArmFault::Translation0);
222 return;
223 case L1Descriptor::Section:
389 return;
390 case L1Descriptor::Section:
224 if (sctlr.afe && bits(l1Desc.ap(), 0) == 0)
225 panic("Haven't implemented AFE\n");
391 if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) {
392 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is
393 * enabled if set, do l1.Desc.setAp0() instead of generating
394 * AccessFlag0
395 */
226
396
397 fault = new DataAbort(vaddr, NULL, isWrite,
398 ArmFault::AccessFlag0);
399 }
400
227 if (l1Desc.supersection()) {
228 panic("Haven't implemented supersections\n");
229 }
230 te.N = 20;
231 te.pfn = l1Desc.pfn();
232 te.size = (1<<te.N) - 1;
233 te.global = !l1Desc.global();
234 te.valid = true;
235 te.vpn = vaddr >> te.N;
236 te.sNp = true;
237 te.xn = l1Desc.xn();
238 te.ap = l1Desc.ap();
239 te.domain = l1Desc.domain();
240 te.asid = contextId;
401 if (l1Desc.supersection()) {
402 panic("Haven't implemented supersections\n");
403 }
404 te.N = 20;
405 te.pfn = l1Desc.pfn();
406 te.size = (1<<te.N) - 1;
407 te.global = !l1Desc.global();
408 te.valid = true;
409 te.vpn = vaddr >> te.N;
410 te.sNp = true;
411 te.xn = l1Desc.xn();
412 te.ap = l1Desc.ap();
413 te.domain = l1Desc.domain();
414 te.asid = contextId;
241 memAttrs(te, l1Desc.texcb());
415 memAttrs(te, l1Desc.texcb(), l1Desc.shareable());
242
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 );
250
251 tc = NULL;
252 req = NULL;
253 tlb->insert(vaddr, te);
254
255 return;
256 case L1Descriptor::PageTable:
257 Addr l2desc_addr;
258 l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2);
416
417 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n");
418 DPRINTF(TLB, " - N%d pfn:%#x size: %#x global:%d valid: %d\n",
419 te.N, te.pfn, te.size, te.global, te.valid);
420 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d\n",
421 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid);
422 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n",
423 l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF );
424
425 tc = NULL;
426 req = NULL;
427 tlb->insert(vaddr, te);
428
429 return;
430 case L1Descriptor::PageTable:
431 Addr l2desc_addr;
432 l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2);
259 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", l2desc_addr);
433 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n",
434 l2desc_addr);
260
261 // Trickbox address check
262 fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
263 isFetch, isWrite, l1Desc.domain(), false);
264 if (fault) {
265 tc = NULL;
266 req = NULL;
267 return;

--- 15 unchanged lines hidden (view full) ---

283}
284
285void
286TableWalker::doL2Descriptor()
287{
288 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data);
289 TlbEntry te;
290
435
436 // Trickbox address check
437 fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
438 isFetch, isWrite, l1Desc.domain(), false);
439 if (fault) {
440 tc = NULL;
441 req = NULL;
442 return;

--- 15 unchanged lines hidden (view full) ---

458}
459
460void
461TableWalker::doL2Descriptor()
462{
463 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data);
464 TlbEntry te;
465
291 if (sctlr.afe && bits(l1Desc.ap(), 0) == 0)
292 panic("Haven't implemented AFE\n");
293
294 if (l2Desc.invalid()) {
295 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
296 tc = NULL;
297 req = NULL;
298 if (isFetch)
299 fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
300 else
466 if (l2Desc.invalid()) {
467 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
468 tc = NULL;
469 req = NULL;
470 if (isFetch)
471 fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
472 else
301 fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, ArmFault::Translation1);
473 fault = new DataAbort(vaddr, l1Desc.domain(), isWrite,
474 ArmFault::Translation1);
302 return;
303 }
304
475 return;
476 }
477
478 if (sctlr.afe && bits(l2Desc.ap(), 0) == 0) {
479 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled
480 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0
481 */
482
483 fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::AccessFlag1);
484 }
485
305 if (l2Desc.large()) {
306 te.N = 16;
307 te.pfn = l2Desc.pfn();
308 } else {
309 te.N = 12;
310 te.pfn = l2Desc.pfn();
311 }
312
313 te.valid = true;
314 te.size = (1 << te.N) - 1;
315 te.asid = contextId;
316 te.sNp = false;
317 te.vpn = vaddr >> te.N;
318 te.global = l2Desc.global();
319 te.xn = l2Desc.xn();
320 te.ap = l2Desc.ap();
321 te.domain = l1Desc.domain();
486 if (l2Desc.large()) {
487 te.N = 16;
488 te.pfn = l2Desc.pfn();
489 } else {
490 te.N = 12;
491 te.pfn = l2Desc.pfn();
492 }
493
494 te.valid = true;
495 te.size = (1 << te.N) - 1;
496 te.asid = contextId;
497 te.sNp = false;
498 te.vpn = vaddr >> te.N;
499 te.global = l2Desc.global();
500 te.xn = l2Desc.xn();
501 te.ap = l2Desc.ap();
502 te.domain = l1Desc.domain();
322 memAttrs(te, l2Desc.texcb());
503 memAttrs(te, l2Desc.texcb(), l2Desc.shareable());
323
324 tc = NULL;
325 req = NULL;
326 tlb->insert(vaddr, te);
327}
328
329ArmISA::TableWalker *
330ArmTableWalkerParams::create()
331{
332 return new ArmISA::TableWalker(this);
333}
334
504
505 tc = NULL;
506 req = NULL;
507 tlb->insert(vaddr, te);
508}
509
510ArmISA::TableWalker *
511ArmTableWalkerParams::create()
512{
513 return new ArmISA::TableWalker(this);
514}
515