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