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