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 "dev/io_device.hh" 44#include "cpu/thread_context.hh" 45
|
46#define NUM_WALKERS 2 // 2 should be enough to handle crossing page boundaries |
47 48using namespace ArmISA; 49 50TableWalker::TableWalker(const Params *p)
|
50 : MemObject(p), port(NULL), tlb(NULL), tc(NULL), req(NULL),
51 doL1DescEvent(this), doL2DescEvent(this)
52{}
|
51 : MemObject(p), stateQueue(NUM_WALKERS), port(NULL), tlb(NULL), 52 currState(NULL), doL1DescEvent(this), doL2DescEvent(this) 53{ 54 sctlr = NULL; 55} |
56 57TableWalker::~TableWalker() 58{ 59 ; 60} 61 62 63unsigned int 64drain(Event *de) 65{ 66 panic("Not implemented\n"); 67} 68 69Port* 70TableWalker::getPort(const std::string &if_name, int idx) 71{ 72 if (if_name == "port") { 73 if (port != NULL) 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); 80 return port; 81 } 82 return NULL; 83} 84 85Fault 86TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode, 87 TLB::Translation *_trans, bool _timing) 88{
|
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
89 if (tc || req)
90 panic("Overlapping TLB walks attempted\n");
|
89 if (!currState) { 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 92 // TLB miss. 93 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n"); |
94
|
92 tc = _tc;
93 transState = _trans;
94 req = _req;
95 fault = NoFault;
96 contextId = _cid;
97 timing = _timing;
98 mode = _mode;
|
95 currState = new WalkerState(); 96 currState->tableWalker = this; 97 } 98 else if (_timing) { 99 panic("currState should always be empty in timing mode!\n"); 100 } |
101
|
102 currState->tc = _tc; 103 currState->transState = _trans; 104 currState->req = _req; 105 currState->fault = NoFault; 106 currState->contextId = _cid; 107 currState->timing = _timing; 108 currState->mode = _mode; 109 |
110 /** @todo These should be cached or grabbed from cached copies in 111 the TLB, all these miscreg reads are expensive */
|
102 vaddr = req->getVaddr() & ~PcModeMask;
103 sctlr = tc->readMiscReg(MISCREG_SCTLR);
104 cpsr = tc->readMiscReg(MISCREG_CPSR);
105 N = tc->readMiscReg(MISCREG_TTBCR);
106 Addr ttbr = 0;
|
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); |
117
|
108 isFetch = (mode == TLB::Execute);
109 isWrite = (mode == TLB::Write);
110 isPriv = (cpsr.mode != MODE_USER);
|
118 currState->isFetch = (currState->mode == TLB::Execute); 119 currState->isWrite = (currState->mode == TLB::Write); 120 currState->isPriv = (currState->cpsr.mode != MODE_USER); |
121
|
122 Addr ttbr = 0; 123 |
124 // If translation isn't enabled, we shouldn't be here
|
113 assert(sctlr.m);
|
125 assert(currState->sctlr.m); |
126 127 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
|
116 vaddr, N, mbits(vaddr, 31, 32-N));
|
128 currState->vaddr, currState->N, mbits(currState->vaddr, 31, 129 32-currState->N)); |
130
|
118 if (N == 0 || !mbits(vaddr, 31, 32-N)) {
|
131 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) { |
132 DPRINTF(TLB, " - Selecting TTBR0\n");
|
120 ttbr = tc->readMiscReg(MISCREG_TTBR0);
|
133 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0); |
134 } else { 135 DPRINTF(TLB, " - Selecting TTBR1\n");
|
123 ttbr = tc->readMiscReg(MISCREG_TTBR1);
124 N = 0;
|
136 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1); 137 currState->N = 0; |
138 } 139
|
127 Addr l1desc_addr = mbits(ttbr, 31, 14-N) | (bits(vaddr,31-N,20) << 2);
|
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); 143 144 145 // Trickbox address check
|
132 fault = tlb->walkTrickBoxCheck(l1desc_addr, vaddr, sizeof(uint32_t),
133 isFetch, isWrite, 0, true);
134 if (fault) {
135 tc = NULL;
136 req = NULL;
137 return fault;
|
146 Fault f; 147 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t), 148 currState->isFetch, currState->isWrite, 0, true); 149 if (f) { 150 currState->tc = NULL; 151 currState->req = NULL; 152 return f; |
153 } 154
|
140 if (timing) {
|
155 if (currState->timing) { |
156 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
|
142 &doL1DescEvent, (uint8_t*)&l1Desc.data, (Tick)0);
|
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); 161 currState = NULL; |
162 } else { 163 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t),
|
145 NULL, (uint8_t*)&l1Desc.data, (Tick)0);
|
164 NULL, (uint8_t*)&currState->l1Desc.data, (Tick)0); |
165 doL1Descriptor();
|
166 f = currState->fault; |
167 } 168
|
149 return fault;
|
169 return f; |
170} 171 172void
|
153TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, uint8_t texcb, bool s)
|
173TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 174 uint8_t texcb, bool s) |
175{
|
155 // Note: tc local variable is hiding tc class variable
|
176 // Note: tc and sctlr local variables are hiding tc and sctrl class 177 // variables |
178 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 179 te.shareable = false; // default value 180 bool outer_shareable = false;
|
159 if (sctlr.tre == 0) {
|
181 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { |
182 switch(texcb) { 183 case 0: // Stongly-ordered 184 te.nonCacheable = true; 185 te.mtype = TlbEntry::StronglyOrdered; 186 te.shareable = true; 187 te.innerAttrs = 1; 188 te.outerAttrs = 0; 189 break; 190 case 1: // Shareable Device 191 te.nonCacheable = true; 192 te.mtype = TlbEntry::Device; 193 te.shareable = true; 194 te.innerAttrs = 3; 195 te.outerAttrs = 0; 196 break; 197 case 2: // Outer and Inner Write-Through, no Write-Allocate 198 te.mtype = TlbEntry::Normal; 199 te.shareable = s; 200 te.innerAttrs = 6; 201 te.outerAttrs = bits(texcb, 1, 0); 202 break; 203 case 3: // Outer and Inner Write-Back, no Write-Allocate 204 te.mtype = TlbEntry::Normal; 205 te.shareable = s; 206 te.innerAttrs = 7; 207 te.outerAttrs = bits(texcb, 1, 0); 208 break; 209 case 4: // Outer and Inner Non-cacheable 210 te.nonCacheable = true; 211 te.mtype = TlbEntry::Normal; 212 te.shareable = s; 213 te.innerAttrs = 0; 214 te.outerAttrs = bits(texcb, 1, 0); 215 break; 216 case 5: // Reserved
|
217 panic("Reserved texcb value!\n"); |
218 break; 219 case 6: // Implementation Defined
|
220 panic("Implementation-defined texcb value!\n"); |
221 break; 222 case 7: // Outer and Inner Write-Back, Write-Allocate 223 te.mtype = TlbEntry::Normal; 224 te.shareable = s; 225 te.innerAttrs = 5; 226 te.outerAttrs = 1; 227 break; 228 case 8: // Non-shareable Device 229 te.nonCacheable = true; 230 te.mtype = TlbEntry::Device; 231 te.shareable = false; 232 te.innerAttrs = 3; 233 te.outerAttrs = 0; 234 break; 235 case 9 ... 15: // Reserved
|
236 panic("Reserved texcb value!\n"); |
237 break; 238 case 16 ... 31: // Cacheable Memory 239 te.mtype = TlbEntry::Normal; 240 te.shareable = s; 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); 245 break; 246 default: 247 panic("More than 32 states for 5 bits?\n"); 248 } 249 } else { 250 assert(tc); 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)) { 256 case 0: 257 curr_tr = prrr.tr0; 258 curr_ir = nmrr.ir0; 259 curr_or = nmrr.or0; 260 outer_shareable = (prrr.nos0 == 0); 261 break; 262 case 1: 263 curr_tr = prrr.tr1; 264 curr_ir = nmrr.ir1; 265 curr_or = nmrr.or1; 266 outer_shareable = (prrr.nos1 == 0); 267 break; 268 case 2: 269 curr_tr = prrr.tr2; 270 curr_ir = nmrr.ir2; 271 curr_or = nmrr.or2; 272 outer_shareable = (prrr.nos2 == 0); 273 break; 274 case 3: 275 curr_tr = prrr.tr3; 276 curr_ir = nmrr.ir3; 277 curr_or = nmrr.or3; 278 outer_shareable = (prrr.nos3 == 0); 279 break; 280 case 4: 281 curr_tr = prrr.tr4; 282 curr_ir = nmrr.ir4; 283 curr_or = nmrr.or4; 284 outer_shareable = (prrr.nos4 == 0); 285 break; 286 case 5: 287 curr_tr = prrr.tr5; 288 curr_ir = nmrr.ir5; 289 curr_or = nmrr.or5; 290 outer_shareable = (prrr.nos5 == 0); 291 break; 292 case 6: 293 panic("Imp defined type\n"); 294 case 7: 295 curr_tr = prrr.tr7; 296 curr_ir = nmrr.ir7; 297 curr_or = nmrr.or7; 298 outer_shareable = (prrr.nos7 == 0); 299 break; 300 } 301 302 switch(curr_tr) { 303 case 0: 304 DPRINTF(TLBVerbose, "StronglyOrdered\n"); 305 te.mtype = TlbEntry::StronglyOrdered; 306 te.nonCacheable = true; 307 te.innerAttrs = 1; 308 te.outerAttrs = 0; 309 te.shareable = true; 310 break; 311 case 1: 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; 316 te.innerAttrs = 3; 317 te.outerAttrs = 0; 318 if (prrr.ds1 && s) 319 te.shareable = true; 320 if (prrr.ds0 && !s) 321 te.shareable = true; 322 break; 323 case 2: 324 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 325 prrr.ns1, prrr.ns0, s); 326 te.mtype = TlbEntry::Normal; 327 if (prrr.ns1 && s) 328 te.shareable = true; 329 if (prrr.ns0 && !s) 330 te.shareable = true;
|
306 //te.shareable = outer_shareable;
|
331 break; 332 case 3: 333 panic("Reserved type"); 334 } 335 336 if (te.mtype == TlbEntry::Normal){ 337 switch(curr_ir) { 338 case 0: 339 te.nonCacheable = true; 340 te.innerAttrs = 0; 341 break; 342 case 1: 343 te.innerAttrs = 5; 344 break; 345 case 2: 346 te.innerAttrs = 6; 347 break; 348 case 3: 349 te.innerAttrs = 7; 350 break; 351 } 352 353 switch(curr_or) { 354 case 0: 355 te.nonCacheable = true; 356 te.outerAttrs = 0; 357 break; 358 case 1: 359 te.outerAttrs = 1; 360 break; 361 case 2: 362 te.outerAttrs = 2; 363 break; 364 case 3: 365 te.outerAttrs = 3; 366 break; 367 } 368 } 369 }
|
370 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \ 371 outerAttrs: %d\n", 372 te.shareable, te.innerAttrs, te.outerAttrs); |
373 374 /** Formatting for Physical Address Register (PAR) 375 * Only including lower bits (TLB info here) 376 * PAR: 377 * PA [31:12] 378 * Reserved [11] 379 * TLB info [10:1] 380 * NOS [10] (Not Outer Sharable) 381 * NS [9] (Non-Secure) 382 * -- [8] (Implementation Defined) 383 * SH [7] (Sharable) 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) 388 */ 389 te.attributes = ( 390 ((outer_shareable ? 0:1) << 10) | 391 // TODO: NS Bit 392 ((te.shareable ? 1:0) << 7) | 393 (te.innerAttrs << 4) | 394 (te.outerAttrs << 2) 395 // TODO: Supersection bit 396 // TODO: Fault bit 397 ); 398 399 400} 401 402void 403TableWalker::doL1Descriptor() 404{
|
378 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", vaddr, l1Desc.data);
|
405 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", 406 currState->vaddr, currState->l1Desc.data); |
407 TlbEntry te; 408
|
381 switch (l1Desc.type()) {
|
409 switch (currState->l1Desc.type()) { |
410 case L1Descriptor::Ignore: 411 case L1Descriptor::Reserved:
|
384 if (!delayed) {
385 tc = NULL;
386 req = NULL;
|
412 if (!currState->delayed) { 413 currState->tc = NULL; 414 currState->req = NULL; |
415 } 416 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
|
389 if (isFetch)
390 fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
|
417 if (currState->isFetch) 418 currState->fault = 419 new PrefetchAbort(currState->vaddr, ArmFault::Translation0); |
420 else
|
392 fault = new DataAbort(vaddr, NULL, isWrite,
|
421 currState->fault = 422 new DataAbort(currState->vaddr, NULL, currState->isWrite, |
423 ArmFault::Translation0); 424 return; 425 case L1Descriptor::Section:
|
396 if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) {
|
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 429 * AccessFlag0 430 */ 431
|
402 fault = new DataAbort(vaddr, NULL, isWrite,
|
432 currState->fault = 433 new DataAbort(currState->vaddr, NULL, currState->isWrite, |
434 ArmFault::AccessFlag0); 435 } 436
|
406 if (l1Desc.supersection()) {
|
437 if (currState->l1Desc.supersection()) { |
438 panic("Haven't implemented supersections\n"); 439 } 440 te.N = 20;
|
410 te.pfn = l1Desc.pfn();
|
441 te.pfn = currState->l1Desc.pfn(); |
442 te.size = (1<<te.N) - 1;
|
412 te.global = !l1Desc.global();
|
443 te.global = !currState->l1Desc.global(); |
444 te.valid = true;
|
414 te.vpn = vaddr >> te.N;
|
445 te.vpn = currState->vaddr >> te.N; |
446 te.sNp = true;
|
416 te.xn = l1Desc.xn();
417 te.ap = l1Desc.ap();
418 te.domain = l1Desc.domain();
419 te.asid = contextId;
420 memAttrs(tc, te, l1Desc.texcb(), l1Desc.shareable());
|
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()); |
453 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",
|
428 l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF );
|
460 currState->l1Desc.domain(), currState->l1Desc.data, 461 (currState->l1Desc.data >> 5) & 0xF ); |
462
|
430 if (!timing) {
431 tc = NULL;
432 req = NULL;
|
463 if (!currState->timing) { 464 currState->tc = NULL; 465 currState->req = NULL; |
466 }
|
434 tlb->insert(vaddr, te);
|
467 tlb->insert(currState->vaddr, te); |
468 469 return; 470 case L1Descriptor::PageTable: 471 Addr l2desc_addr;
|
439 l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2);
|
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", 475 l2desc_addr); 476 477 // Trickbox address check
|
444 fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
445 isFetch, isWrite, l1Desc.domain(), false);
446 if (fault) {
447 if (!timing) {
448 tc = NULL;
449 req = NULL;
|
478 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr, 479 sizeof(uint32_t), currState->isFetch, currState->isWrite, 480 currState->l1Desc.domain(), false); 481 482 if (currState->fault) { 483 if (!currState->timing) { 484 currState->tc = NULL; 485 currState->req = NULL; |
486 } 487 return; 488 } 489 490
|
455 if (timing) {
456 delayed = true;
|
491 if (currState->timing) { 492 currState->delayed = true; |
493 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
458 &doL2DescEvent, (uint8_t*)&l2Desc.data, 0);
|
494 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, 0); |
495 } else { 496 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t),
|
461 NULL, (uint8_t*)&l2Desc.data, 0);
|
497 NULL, (uint8_t*)&currState->l2Desc.data, 0); |
498 doL2Descriptor(); 499 } 500 return; 501 default: 502 panic("A new type in a 2 bit field?\n"); 503 } 504} 505 506void 507TableWalker::doL2Descriptor() 508{
|
473 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data);
|
509 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", 510 currState->vaddr, currState->l2Desc.data); |
511 TlbEntry te; 512
|
476 if (l2Desc.invalid()) {
|
513 if (currState->l2Desc.invalid()) { |
514 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
|
478 if (!delayed) {
479 tc = NULL;
480 req = NULL;
|
515 if (!currState->delayed) { 516 currState->tc = NULL; 517 currState->req = NULL; |
518 }
|
482 if (isFetch)
483 fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
|
519 if (currState->isFetch) 520 currState->fault = 521 new PrefetchAbort(currState->vaddr, ArmFault::Translation1); |
522 else
|
485 fault = new DataAbort(vaddr, l1Desc.domain(), isWrite,
486 ArmFault::Translation1);
|
523 currState->fault = 524 new DataAbort(currState->vaddr, currState->l1Desc.domain(), 525 currState->isWrite, ArmFault::Translation1); |
526 return; 527 } 528
|
490 if (sctlr.afe && bits(l2Desc.ap(), 0) == 0) {
|
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 532 */ 533
|
495 fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::AccessFlag1);
|
534 currState->fault = 535 new DataAbort(currState->vaddr, NULL, currState->isWrite, 536 ArmFault::AccessFlag1); 537 |
538 } 539
|
498 if (l2Desc.large()) {
|
540 if (currState->l2Desc.large()) { |
541 te.N = 16;
|
500 te.pfn = l2Desc.pfn();
|
542 te.pfn = currState->l2Desc.pfn(); |
543 } else { 544 te.N = 12;
|
503 te.pfn = l2Desc.pfn();
|
545 te.pfn = currState->l2Desc.pfn(); |
546 } 547 548 te.valid = true; 549 te.size = (1 << te.N) - 1;
|
508 te.asid = contextId;
|
550 te.asid = currState->contextId; |
551 te.sNp = false;
|
510 te.vpn = vaddr >> te.N;
511 te.global = l2Desc.global();
512 te.xn = l2Desc.xn();
513 te.ap = l2Desc.ap();
514 te.domain = l1Desc.domain();
515 memAttrs(tc, te, l2Desc.texcb(), l2Desc.shareable());
|
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()); |
559
|
517 if (!delayed) {
518 tc = NULL;
519 req = NULL;
|
560 if (!currState->delayed) { 561 currState->tc = NULL; 562 currState->req = NULL; |
563 }
|
521 tlb->insert(vaddr, te);
|
564 tlb->insert(currState->vaddr, te); |
565} 566 567void 568TableWalker::doL1DescriptorWrapper() 569{
|
527 delayed = false;
|
570 currState = stateQueue.peek(); 571 currState->delayed = false; |
572
|
529 DPRINTF(TLBVerbose, "calling doL1Descriptor\n");
|
573 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr); |
574 doL1Descriptor(); 575 576 // Check if fault was generated
|
533 if (fault != NoFault) {
534 transState->finish(fault, req, tc, mode);
|
577 if (currState->fault != NoFault) { 578 currState->transState->finish(currState->fault, currState->req, 579 currState->tc, currState->mode); |
580
|
536 req = NULL;
537 tc = NULL;
538 delayed = false;
|
581 currState->req = NULL; 582 currState->tc = NULL; 583 currState->delayed = false; 584 585 stateQueue.remove(); |
586 }
|
540 else if (!delayed) {
|
587 else if (!currState->delayed) { |
588 DPRINTF(TLBVerbose, "calling translateTiming again\n");
|
542 fault = tlb->translateTiming(req, tc, transState, mode);
|
589 currState->fault = tlb->translateTiming(currState->req, currState->tc, 590 currState->transState, currState->mode); |
591
|
544 req = NULL;
545 tc = NULL;
546 delayed = false;
|
592 currState->req = NULL; 593 currState->tc = NULL; 594 currState->delayed = false; 595 596 stateQueue.remove(); |
597 }
|
598 currState = NULL; |
599} 600 601void 602TableWalker::doL2DescriptorWrapper() 603{
|
553 assert(delayed);
|
604 currState = stateQueue.peek(); 605 assert(currState->delayed); |
606
|
555 DPRINTF(TLBVerbose, "calling doL2Descriptor\n");
|
607 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", 608 currState->vaddr); |
609 doL2Descriptor(); 610 611 // Check if fault was generated
|
559 if (fault != NoFault) {
560 transState->finish(fault, req, tc, mode);
|
612 if (currState->fault != NoFault) { 613 currState->transState->finish(currState->fault, currState->req, 614 currState->tc, currState->mode); |
615 } 616 else { 617 DPRINTF(TLBVerbose, "calling translateTiming again\n");
|
564 fault = tlb->translateTiming(req, tc, transState, mode);
|
618 currState->fault = tlb->translateTiming(currState->req, currState->tc, 619 currState->transState, currState->mode); |
620 } 621
|
567 req = NULL;
568 tc = NULL;
569 delayed = false;
|
622 currState->req = NULL; 623 currState->tc = NULL; 624 currState->delayed = false; 625 626 stateQueue.remove(); 627 currState = NULL; |
628} 629 630ArmISA::TableWalker * 631ArmTableWalkerParams::create() 632{ 633 return new ArmISA::TableWalker(this); 634} 635
|