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