table_walker.cc (10024:fc10e1f9f124) | table_walker.cc (10037:5cac77888310) |
---|---|
1/* | 1/* |
2 * Copyright (c) 2010 ARM Limited | 2 * Copyright (c) 2010, 2012-2013 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 --- 19 unchanged lines hidden (view full) --- 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 | 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 --- 19 unchanged lines hidden (view full) --- 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 * Giacomo Gabrielli |
|
38 */ 39 40#include "arch/arm/faults.hh" | 39 */ 40 41#include "arch/arm/faults.hh" |
42#include "arch/arm/stage2_mmu.hh" 43#include "arch/arm/system.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) | 44#include "arch/arm/table_walker.hh" 45#include "arch/arm/tlb.hh" 46#include "cpu/base.hh" 47#include "cpu/thread_context.hh" 48#include "debug/Checkpoint.hh" 49#include "debug/Drain.hh" 50#include "debug/TLB.hh" 51#include "debug/TLBVerbose.hh" 52#include "sim/system.hh" 53 54using namespace ArmISA; 55 56TableWalker::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 : MemObject(p), port(this, p->sys), drainManager(NULL), 58 stage2Mmu(NULL), isStage2(p->is_stage2), tlb(NULL), 59 currState(NULL), pending(false), masterId(p->sys->getMasterId(name())), |
57 numSquashable(p->num_squash_per_cycle), | 60 numSquashable(p->num_squash_per_cycle), |
58 doL1DescEvent(this), doL2DescEvent(this), doProcessEvent(this) | 61 doL1DescEvent(this), doL2DescEvent(this), 62 doL0LongDescEvent(this), doL1LongDescEvent(this), doL2LongDescEvent(this), 63 doL3LongDescEvent(this), 64 doProcessEvent(this) |
59{ 60 sctlr = 0; | 65{ 66 sctlr = 0; |
67 68 // Cache system-level properties 69 if (FullSystem) { 70 armSys = dynamic_cast<ArmSystem *>(p->sys); 71 assert(armSys); 72 haveSecurity = armSys->haveSecurity(); 73 _haveLPAE = armSys->haveLPAE(); 74 _haveVirtualization = armSys->haveVirtualization(); 75 physAddrRange = armSys->physAddrRange(); 76 _haveLargeAsid64 = armSys->haveLargeAsid64(); 77 } else { 78 armSys = NULL; 79 haveSecurity = _haveLPAE = _haveVirtualization = false; 80 _haveLargeAsid64 = false; 81 physAddrRange = 32; 82 } 83 |
|
61} 62 63TableWalker::~TableWalker() 64{ 65 ; 66} 67 | 84} 85 86TableWalker::~TableWalker() 87{ 88 ; 89} 90 |
91TableWalker::WalkerState::WalkerState() : stage2Tran(NULL), l2Desc(l1Desc) 92{ 93} 94 |
|
68void 69TableWalker::completeDrain() 70{ | 95void 96TableWalker::completeDrain() 97{ |
71 if (drainManager && stateQueueL1.empty() && stateQueueL2.empty() && | 98 if (drainManager && stateQueues[L1].empty() && stateQueues[L2].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 | 99 pendingQueue.empty()) { 100 setDrainState(Drainable::Drained); 101 DPRINTF(Drain, "TableWalker done draining, processing drain event\n"); 102 drainManager->signalDrainDone(); 103 drainManager = NULL; 104 } 105} 106 107unsigned int 108TableWalker::drain(DrainManager *dm) 109{ 110 unsigned int count = port.drain(dm); 111 |
85 if (stateQueueL1.empty() && stateQueueL2.empty() && 86 pendingQueue.empty()) { 87 setDrainState(Drainable::Drained); 88 DPRINTF(Drain, "TableWalker free, no need to drain\n"); | 112 bool state_queues_not_empty = false; |
89 | 113 |
90 // table walker is drained, but its ports may still need to be drained 91 return count; 92 } else { | 114 for (int i = 0; i < MAX_LOOKUP_LEVELS; ++i) { 115 if (!stateQueues[i].empty()) { 116 state_queues_not_empty = true; 117 break; 118 } 119 } 120 121 if (state_queues_not_empty || pendingQueue.size()) { |
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; | 122 drainManager = dm; 123 setDrainState(Drainable::Draining); 124 DPRINTF(Drain, "TableWalker not drained\n"); 125 126 // return port drain count plus the table walker itself needs to drain 127 return count + 1; |
128 } else { 129 setDrainState(Drainable::Drained); 130 DPRINTF(Drain, "TableWalker free, no need to drain\n"); |
|
99 | 131 |
132 // table walker is drained, but its ports may still need to be drained 133 return count; |
|
100 } 101} 102 103void 104TableWalker::drainResume() 105{ 106 Drainable::drainResume(); 107 if (params()->sys->isTimingMode() && currState) { --- 7 unchanged lines hidden (view full) --- 115{ 116 if (if_name == "port") { 117 return port; 118 } 119 return MemObject::getMasterPort(if_name, idx); 120} 121 122Fault | 134 } 135} 136 137void 138TableWalker::drainResume() 139{ 140 Drainable::drainResume(); 141 if (params()->sys->isTimingMode() && currState) { --- 7 unchanged lines hidden (view full) --- 149{ 150 if (if_name == "port") { 151 return port; 152 } 153 return MemObject::getMasterPort(if_name, idx); 154} 155 156Fault |
123TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode, 124 TLB::Translation *_trans, bool _timing, bool _functional) | 157TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint16_t _asid, 158 uint8_t _vmid, bool _isHyp, TLB::Mode _mode, 159 TLB::Translation *_trans, bool _timing, bool _functional, 160 bool secure, TLB::ArmTranslationType tranType) |
125{ 126 assert(!(_functional && _timing)); | 161{ 162 assert(!(_functional && _timing)); |
163 |
|
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. | 164 if (!currState) { 165 // For atomic mode, a new WalkerState instance should be only created 166 // once per TLB. For timing mode, a new instance is generated for every 167 // TLB miss. 168 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n"); 169 170 currState = new WalkerState(); 171 currState->tableWalker = this; 172 } else if (_timing) { 173 // This is a translation that was completed and then faulted again 174 // because some underlying parameters that affect the translation 175 // changed out from under us (e.g. asid). It will either be a 176 // misprediction, in which case nothing will happen or we'll use 177 // this fault to re-execute the faulting instruction which should clean 178 // up everything. |
142 if (currState->vaddr == _req->getVaddr()) { | 179 if (currState->vaddr_tainted == _req->getVaddr()) { |
143 return new ReExec; 144 } | 180 return new ReExec; 181 } |
145 panic("currState should always be empty in timing mode!\n"); | |
146 } 147 148 currState->tc = _tc; | 182 } 183 184 currState->tc = _tc; |
185 currState->aarch64 = opModeIs64(currOpMode(_tc)); 186 currState->el = currEL(_tc); |
|
149 currState->transState = _trans; 150 currState->req = _req; 151 currState->fault = NoFault; | 187 currState->transState = _trans; 188 currState->req = _req; 189 currState->fault = NoFault; |
152 currState->contextId = _cid; | 190 currState->asid = _asid; 191 currState->vmid = _vmid; 192 currState->isHyp = _isHyp; |
153 currState->timing = _timing; 154 currState->functional = _functional; 155 currState->mode = _mode; | 193 currState->timing = _timing; 194 currState->functional = _functional; 195 currState->mode = _mode; |
196 currState->tranType = tranType; 197 currState->isSecure = secure; 198 currState->physAddrRange = physAddrRange; |
|
156 157 /** @todo These should be cached or grabbed from cached copies in 158 the TLB, all these miscreg reads are expensive */ | 199 200 /** @todo These should be cached or grabbed from cached copies in 201 the TLB, all these miscreg reads are expensive */ |
159 currState->vaddr = currState->req->getVaddr(); 160 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR); | 202 currState->vaddr_tainted = currState->req->getVaddr(); 203 if (currState->aarch64) 204 currState->vaddr = purifyTaggedAddr(currState->vaddr_tainted, 205 currState->tc, currState->el); 206 else 207 currState->vaddr = currState->vaddr_tainted; 208 209 if (currState->aarch64) { 210 switch (currState->el) { 211 case EL0: 212 case EL1: 213 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL1); 214 currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL1); 215 break; 216 // @todo: uncomment this to enable Virtualization 217 // case EL2: 218 // assert(haveVirtualization); 219 // currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL2); 220 // currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL2); 221 // break; 222 case EL3: 223 assert(haveSecurity); 224 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR_EL3); 225 currState->ttbcr = currState->tc->readMiscReg(MISCREG_TCR_EL3); 226 break; 227 default: 228 panic("Invalid exception level"); 229 break; 230 } 231 } else { 232 currState->sctlr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 233 MISCREG_SCTLR, currState->tc, !currState->isSecure)); 234 currState->ttbcr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 235 MISCREG_TTBCR, currState->tc, !currState->isSecure)); 236 currState->htcr = currState->tc->readMiscReg(MISCREG_HTCR); 237 currState->hcr = currState->tc->readMiscReg(MISCREG_HCR); 238 currState->vtcr = currState->tc->readMiscReg(MISCREG_VTCR); 239 } |
161 sctlr = currState->sctlr; | 240 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 | 241 242 currState->isFetch = (currState->mode == TLB::Execute); 243 currState->isWrite = (currState->mode == TLB::Write); 244 |
245 // We only do a second stage of translation if we're not secure, or in 246 // hyp mode, the second stage MMU is enabled, and this table walker 247 // instance is the first stage. 248 currState->doingStage2 = false; 249 // @todo: for now disable this in AArch64 (HCR is not set) 250 currState->stage2Req = !currState->aarch64 && currState->hcr.vm && 251 !isStage2 && !currState->isSecure && !currState->isHyp; |
|
167 | 252 |
168 if (!currState->timing) 169 return processWalk(); | 253 bool long_desc_format = currState->aarch64 || 254 (_haveLPAE && currState->ttbcr.eae) || 255 _isHyp || isStage2; |
170 | 256 |
257 if (long_desc_format) { 258 // Helper variables used for hierarchical permissions 259 currState->secureLookup = currState->isSecure; 260 currState->rwTable = true; 261 currState->userTable = true; 262 currState->xnTable = false; 263 currState->pxnTable = false; 264 } 265 266 if (!currState->timing) { 267 if (currState->aarch64) 268 return processWalkAArch64(); 269 else if (long_desc_format) 270 return processWalkLPAE(); 271 else 272 return processWalk(); 273 } 274 |
|
171 if (pending || pendingQueue.size()) { 172 pendingQueue.push_back(currState); 173 currState = NULL; 174 } else { 175 pending = true; | 275 if (pending || pendingQueue.size()) { 276 pendingQueue.push_back(currState); 277 currState = NULL; 278 } else { 279 pending = true; |
176 return processWalk(); | 280 if (currState->aarch64) 281 return processWalkAArch64(); 282 else if (long_desc_format) 283 return processWalkLPAE(); 284 else 285 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 | 286 } 287 288 return NoFault; 289} 290 291void 292TableWalker::processWalkWrapper() 293{ 294 assert(!currState); 295 assert(pendingQueue.size()); 296 currState = pendingQueue.front(); 297 |
298 ExceptionLevel target_el = EL0; 299 if (currState->aarch64) 300 target_el = currEL(currState->tc); 301 else 302 target_el = EL1; 303 |
|
189 // Check if a previous walk filled this request already | 304 // Check if a previous walk filled this request already |
190 TlbEntry* te = tlb->lookup(currState->vaddr, currState->contextId, true); | 305 // @TODO Should this always be the TLB or should we look in the stage2 TLB? 306 TlbEntry* te = tlb->lookup(currState->vaddr, currState->asid, 307 currState->vmid, currState->isHyp, currState->isSecure, true, false, 308 target_el); |
191 192 // Check if we still need to have a walk for this request. If the requesting 193 // instruction has been squashed, or a previous walk has filled the TLB with 194 // a match, we just want to get rid of the walk. The latter could happen 195 // when there are multiple outstanding misses to a single page and a 196 // previous request has been successfully translated. 197 if (!currState->transState->squashed() && !te) { 198 // We've got a valid request, lets process it 199 pending = true; 200 pendingQueue.pop_front(); | 309 310 // Check if we still need to have a walk for this request. If the requesting 311 // instruction has been squashed, or a previous walk has filled the TLB with 312 // a match, we just want to get rid of the walk. The latter could happen 313 // when there are multiple outstanding misses to a single page and a 314 // previous request has been successfully translated. 315 if (!currState->transState->squashed() && !te) { 316 // We've got a valid request, lets process it 317 pending = true; 318 pendingQueue.pop_front(); |
201 processWalk(); | 319 if (currState->aarch64) 320 processWalkAArch64(); 321 else if ((_haveLPAE && currState->ttbcr.eae) || currState->isHyp || isStage2) 322 processWalkLPAE(); 323 else 324 processWalk(); |
202 return; 203 } 204 205 206 // If the instruction that we were translating for has been 207 // squashed we shouldn't bother. 208 unsigned num_squashed = 0; 209 ThreadContext *tc = currState->tc; 210 while ((num_squashed < numSquashable) && currState && 211 (currState->transState->squashed() || te)) { 212 pendingQueue.pop_front(); 213 num_squashed++; 214 | 325 return; 326 } 327 328 329 // If the instruction that we were translating for has been 330 // squashed we shouldn't bother. 331 unsigned num_squashed = 0; 332 ThreadContext *tc = currState->tc; 333 while ((num_squashed < numSquashable) && currState && 334 (currState->transState->squashed() || te)) { 335 pendingQueue.pop_front(); 336 num_squashed++; 337 |
215 DPRINTF(TLB, "Squashing table walk for address %#x\n", currState->vaddr); | 338 DPRINTF(TLB, "Squashing table walk for address %#x\n", 339 currState->vaddr_tainted); |
216 217 if (currState->transState->squashed()) { 218 // finish the translation which will delete the translation object 219 currState->transState->finish(new UnimpFault("Squashed Inst"), 220 currState->req, currState->tc, currState->mode); 221 } else { 222 // translate the request now that we know it will work | 340 341 if (currState->transState->squashed()) { 342 // finish the translation which will delete the translation object 343 currState->transState->finish(new UnimpFault("Squashed Inst"), 344 currState->req, currState->tc, currState->mode); 345 } else { 346 // translate the request now that we know it will work |
223 currState->fault = tlb->translateTiming(currState->req, currState->tc, 224 currState->transState, currState->mode); | 347 tlb->translateTiming(currState->req, currState->tc, 348 currState->transState, currState->mode); 349 |
225 } 226 227 // delete the current request 228 delete currState; 229 230 // peak at the next one 231 if (pendingQueue.size()) { 232 currState = pendingQueue.front(); | 350 } 351 352 // delete the current request 353 delete currState; 354 355 // peak at the next one 356 if (pendingQueue.size()) { 357 currState = pendingQueue.front(); |
233 te = tlb->lookup(currState->vaddr, currState->contextId, true); | 358 te = tlb->lookup(currState->vaddr, currState->asid, 359 currState->vmid, currState->isHyp, currState->isSecure, true, 360 false, target_el); |
234 } else { 235 // Terminate the loop, nothing more to do 236 currState = NULL; 237 } 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 | 361 } else { 362 // Terminate the loop, nothing more to do 363 currState = NULL; 364 } 365 } 366 367 // if we've still got pending translations schedule more work 368 nextWalk(tc); 369 currState = NULL; 370 completeDrain(); 371} 372 373Fault 374TableWalker::processWalk() 375{ 376 Addr ttbr = 0; 377 378 // If translation isn't enabled, we shouldn't be here |
252 assert(currState->sctlr.m); | 379 assert(currState->sctlr.m || isStage2); |
253 | 380 |
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)); | 381 DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x, bits:%#x\n", 382 currState->vaddr_tainted, currState->ttbcr, mbits(currState->vaddr, 31, 383 32 - currState->ttbcr.n)); |
257 | 384 |
258 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) { | 385 if (currState->ttbcr.n == 0 || !mbits(currState->vaddr, 31, 386 32 - currState->ttbcr.n)) { |
259 DPRINTF(TLB, " - Selecting TTBR0\n"); | 387 DPRINTF(TLB, " - Selecting TTBR0\n"); |
260 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0); | 388 // Check if table walk is allowed when Security Extensions are enabled 389 if (haveSecurity && currState->ttbcr.pd0) { 390 if (currState->isFetch) 391 return new PrefetchAbort(currState->vaddr_tainted, 392 ArmFault::TranslationLL + L1, 393 isStage2, 394 ArmFault::VmsaTran); 395 else 396 return new DataAbort(currState->vaddr_tainted, 397 TlbEntry::DomainType::NoAccess, currState->isWrite, 398 ArmFault::TranslationLL + L1, isStage2, 399 ArmFault::VmsaTran); 400 } 401 ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 402 MISCREG_TTBR0, currState->tc, !currState->isSecure)); |
261 } else { 262 DPRINTF(TLB, " - Selecting TTBR1\n"); | 403 } else { 404 DPRINTF(TLB, " - Selecting TTBR1\n"); |
263 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1); 264 currState->N = 0; | 405 // Check if table walk is allowed when Security Extensions are enabled 406 if (haveSecurity && currState->ttbcr.pd1) { 407 if (currState->isFetch) 408 return new PrefetchAbort(currState->vaddr_tainted, 409 ArmFault::TranslationLL + L1, 410 isStage2, 411 ArmFault::VmsaTran); 412 else 413 return new DataAbort(currState->vaddr_tainted, 414 TlbEntry::DomainType::NoAccess, currState->isWrite, 415 ArmFault::TranslationLL + L1, isStage2, 416 ArmFault::VmsaTran); 417 } 418 ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 419 MISCREG_TTBR1, currState->tc, !currState->isSecure)); 420 currState->ttbcr.n = 0; |
265 } 266 | 421 } 422 |
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); | 423 Addr l1desc_addr = mbits(ttbr, 31, 14 - currState->ttbcr.n) | 424 (bits(currState->vaddr, 31 - currState->ttbcr.n, 20) << 2); 425 DPRINTF(TLB, " - Descriptor at address %#x (%s)\n", l1desc_addr, 426 currState->isSecure ? "s" : "ns"); |
270 | 427 |
271 | |
272 // Trickbox address check 273 Fault f; | 428 // Trickbox address check 429 Fault f; |
274 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t), 275 currState->isFetch, currState->isWrite, 0, true); | 430 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->isSecure, 431 currState->vaddr, sizeof(uint32_t), currState->isFetch, 432 currState->isWrite, TlbEntry::DomainType::NoAccess, L1); |
276 if (f) { | 433 if (f) { |
277 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr); | 434 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); |
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 | 435 if (currState->timing) { 436 pending = false; 437 nextWalk(currState->tc); 438 currState = NULL; 439 } else { 440 currState->tc = NULL; 441 currState->req = NULL; 442 } 443 return f; 444 } 445 446 Request::Flags flag = 0; 447 if (currState->sctlr.c == 0) { 448 flag = Request::UNCACHEABLE; 449 } 450 |
451 bool delayed; 452 delayed = fetchDescriptor(l1desc_addr, (uint8_t*)&currState->l1Desc.data, 453 sizeof(uint32_t), flag, L1, &doL1DescEvent, 454 &TableWalker::doL1Descriptor); 455 if (!delayed) { 456 f = currState->fault; 457 } 458 459 return f; 460} 461 462Fault 463TableWalker::processWalkLPAE() 464{ 465 Addr ttbr, ttbr0_max, ttbr1_min, desc_addr; 466 int tsz, n; 467 LookupLevel start_lookup_level = L1; 468 469 DPRINTF(TLB, "Beginning table walk for address %#x, TTBCR: %#x\n", 470 currState->vaddr_tainted, currState->ttbcr); 471 472 Request::Flags flag = 0; 473 if (currState->isSecure) 474 flag.set(Request::SECURE); 475 476 // work out which base address register to use, if in hyp mode we always 477 // use HTTBR 478 if (isStage2) { 479 DPRINTF(TLB, " - Selecting VTTBR (long-desc.)\n"); 480 ttbr = currState->tc->readMiscReg(MISCREG_VTTBR); 481 tsz = sext<4>(currState->vtcr.t0sz); 482 start_lookup_level = currState->vtcr.sl0 ? L1 : L2; 483 } else if (currState->isHyp) { 484 DPRINTF(TLB, " - Selecting HTTBR (long-desc.)\n"); 485 ttbr = currState->tc->readMiscReg(MISCREG_HTTBR); 486 tsz = currState->htcr.t0sz; 487 } else { 488 assert(_haveLPAE && currState->ttbcr.eae); 489 490 // Determine boundaries of TTBR0/1 regions 491 if (currState->ttbcr.t0sz) 492 ttbr0_max = (1ULL << (32 - currState->ttbcr.t0sz)) - 1; 493 else if (currState->ttbcr.t1sz) 494 ttbr0_max = (1ULL << 32) - 495 (1ULL << (32 - currState->ttbcr.t1sz)) - 1; 496 else 497 ttbr0_max = (1ULL << 32) - 1; 498 if (currState->ttbcr.t1sz) 499 ttbr1_min = (1ULL << 32) - (1ULL << (32 - currState->ttbcr.t1sz)); 500 else 501 ttbr1_min = (1ULL << (32 - currState->ttbcr.t0sz)); 502 503 // The following code snippet selects the appropriate translation table base 504 // address (TTBR0 or TTBR1) and the appropriate starting lookup level 505 // depending on the address range supported by the translation table (ARM 506 // ARM issue C B3.6.4) 507 if (currState->vaddr <= ttbr0_max) { 508 DPRINTF(TLB, " - Selecting TTBR0 (long-desc.)\n"); 509 // Check if table walk is allowed 510 if (currState->ttbcr.epd0) { 511 if (currState->isFetch) 512 return new PrefetchAbort(currState->vaddr_tainted, 513 ArmFault::TranslationLL + L1, 514 isStage2, 515 ArmFault::LpaeTran); 516 else 517 return new DataAbort(currState->vaddr_tainted, 518 TlbEntry::DomainType::NoAccess, 519 currState->isWrite, 520 ArmFault::TranslationLL + L1, 521 isStage2, 522 ArmFault::LpaeTran); 523 } 524 ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 525 MISCREG_TTBR0, currState->tc, !currState->isSecure)); 526 tsz = currState->ttbcr.t0sz; 527 if (ttbr0_max < (1ULL << 30)) // Upper limit < 1 GB 528 start_lookup_level = L2; 529 } else if (currState->vaddr >= ttbr1_min) { 530 DPRINTF(TLB, " - Selecting TTBR1 (long-desc.)\n"); 531 // Check if table walk is allowed 532 if (currState->ttbcr.epd1) { 533 if (currState->isFetch) 534 return new PrefetchAbort(currState->vaddr_tainted, 535 ArmFault::TranslationLL + L1, 536 isStage2, 537 ArmFault::LpaeTran); 538 else 539 return new DataAbort(currState->vaddr_tainted, 540 TlbEntry::DomainType::NoAccess, 541 currState->isWrite, 542 ArmFault::TranslationLL + L1, 543 isStage2, 544 ArmFault::LpaeTran); 545 } 546 ttbr = currState->tc->readMiscReg(flattenMiscRegNsBanked( 547 MISCREG_TTBR1, currState->tc, !currState->isSecure)); 548 tsz = currState->ttbcr.t1sz; 549 if (ttbr1_min >= (1ULL << 31) + (1ULL << 30)) // Lower limit >= 3 GB 550 start_lookup_level = L2; 551 } else { 552 // Out of boundaries -> translation fault 553 if (currState->isFetch) 554 return new PrefetchAbort(currState->vaddr_tainted, 555 ArmFault::TranslationLL + L1, 556 isStage2, 557 ArmFault::LpaeTran); 558 else 559 return new DataAbort(currState->vaddr_tainted, 560 TlbEntry::DomainType::NoAccess, 561 currState->isWrite, ArmFault::TranslationLL + L1, 562 isStage2, ArmFault::LpaeTran); 563 } 564 565 } 566 567 // Perform lookup (ARM ARM issue C B3.6.6) 568 if (start_lookup_level == L1) { 569 n = 5 - tsz; 570 desc_addr = mbits(ttbr, 39, n) | 571 (bits(currState->vaddr, n + 26, 30) << 3); 572 DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n", 573 desc_addr, currState->isSecure ? "s" : "ns"); 574 } else { 575 // Skip first-level lookup 576 n = (tsz >= 2 ? 14 - tsz : 12); 577 desc_addr = mbits(ttbr, 39, n) | 578 (bits(currState->vaddr, n + 17, 21) << 3); 579 DPRINTF(TLB, " - Descriptor at address %#x (%s) (long-desc.)\n", 580 desc_addr, currState->isSecure ? "s" : "ns"); 581 } 582 583 // Trickbox address check 584 Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure, 585 currState->vaddr, sizeof(uint64_t), currState->isFetch, 586 currState->isWrite, TlbEntry::DomainType::NoAccess, 587 start_lookup_level); 588 if (f) { 589 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); 590 if (currState->timing) { 591 pending = false; 592 nextWalk(currState->tc); 593 currState = NULL; 594 } else { 595 currState->tc = NULL; 596 currState->req = NULL; 597 } 598 return f; 599 } 600 601 if (currState->sctlr.c == 0) { 602 flag = Request::UNCACHEABLE; 603 } 604 605 if (currState->isSecure) 606 flag.set(Request::SECURE); 607 608 currState->longDesc.lookupLevel = start_lookup_level; 609 currState->longDesc.aarch64 = false; 610 currState->longDesc.largeGrain = false; 611 currState->longDesc.grainSize = 12; 612 613 Event *event = start_lookup_level == L1 ? (Event *) &doL1LongDescEvent 614 : (Event *) &doL2LongDescEvent; 615 616 bool delayed = fetchDescriptor(desc_addr, (uint8_t*)&currState->longDesc.data, 617 sizeof(uint64_t), flag, start_lookup_level, 618 event, &TableWalker::doLongDescriptor); 619 if (!delayed) { 620 f = currState->fault; 621 } 622 623 return f; 624} 625 626unsigned 627TableWalker::adjustTableSizeAArch64(unsigned tsz) 628{ 629 if (tsz < 25) 630 return 25; 631 if (tsz > 48) 632 return 48; 633 return tsz; 634} 635 636bool 637TableWalker::checkAddrSizeFaultAArch64(Addr addr, int currPhysAddrRange) 638{ 639 return (currPhysAddrRange != MaxPhysAddrRange && 640 bits(addr, MaxPhysAddrRange - 1, currPhysAddrRange)); 641} 642 643Fault 644TableWalker::processWalkAArch64() 645{ 646 assert(currState->aarch64); 647 648 DPRINTF(TLB, "Beginning table walk for address %#llx, TTBCR: %#llx\n", 649 currState->vaddr_tainted, currState->ttbcr); 650 651 // Determine TTBR, table size, granule size and phys. address range 652 Addr ttbr = 0; 653 int tsz = 0, ps = 0; 654 bool large_grain = false; 655 bool fault = false; 656 switch (currState->el) { 657 case EL0: 658 case EL1: 659 switch (bits(currState->vaddr, 63,48)) { 660 case 0: 661 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n"); 662 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL1); 663 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t0sz); 664 large_grain = currState->ttbcr.tg0; 665 if (bits(currState->vaddr, 63, tsz) != 0x0 || 666 currState->ttbcr.epd0) 667 fault = true; 668 break; 669 case 0xffff: 670 DPRINTF(TLB, " - Selecting TTBR1 (AArch64)\n"); 671 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1_EL1); 672 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t1sz); 673 large_grain = currState->ttbcr.tg1; 674 if (bits(currState->vaddr, 63, tsz) != mask(64-tsz) || 675 currState->ttbcr.epd1) 676 fault = true; 677 break; 678 default: 679 // top two bytes must be all 0s or all 1s, else invalid addr 680 fault = true; 681 } 682 ps = currState->ttbcr.ips; 683 break; 684 case EL2: 685 case EL3: 686 switch(bits(currState->vaddr, 63,48)) { 687 case 0: 688 DPRINTF(TLB, " - Selecting TTBR0 (AArch64)\n"); 689 if (currState->el == EL2) 690 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL2); 691 else 692 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0_EL3); 693 tsz = adjustTableSizeAArch64(64 - currState->ttbcr.t0sz); 694 large_grain = currState->ttbcr.tg0; 695 break; 696 default: 697 // invalid addr if top two bytes are not all 0s 698 fault = true; 699 } 700 ps = currState->ttbcr.ps; 701 break; 702 } 703 704 if (fault) { 705 Fault f; 706 if (currState->isFetch) 707 f = new PrefetchAbort(currState->vaddr_tainted, 708 ArmFault::TranslationLL + L0, isStage2, 709 ArmFault::LpaeTran); 710 else 711 f = new DataAbort(currState->vaddr_tainted, 712 TlbEntry::DomainType::NoAccess, 713 currState->isWrite, 714 ArmFault::TranslationLL + L0, 715 isStage2, ArmFault::LpaeTran); 716 717 if (currState->timing) { 718 pending = false; 719 nextWalk(currState->tc); 720 currState = NULL; 721 } else { 722 currState->tc = NULL; 723 currState->req = NULL; 724 } 725 return f; 726 727 } 728 729 // Determine starting lookup level 730 LookupLevel start_lookup_level; 731 int grain_size, stride; 732 if (large_grain) { // 64 KB granule 733 grain_size = 16; 734 stride = grain_size - 3; 735 if (tsz > grain_size + 2 * stride) 736 start_lookup_level = L1; 737 else if (tsz > grain_size + stride) 738 start_lookup_level = L2; 739 else 740 start_lookup_level = L3; 741 } else { // 4 KB granule 742 grain_size = 12; 743 stride = grain_size - 3; 744 if (tsz > grain_size + 3 * stride) 745 start_lookup_level = L0; 746 else if (tsz > grain_size + 2 * stride) 747 start_lookup_level = L1; 748 else 749 start_lookup_level = L2; 750 } 751 752 // Determine table base address 753 int base_addr_lo = 3 + tsz - stride * (3 - start_lookup_level) - 754 grain_size; 755 Addr base_addr = mbits(ttbr, 47, base_addr_lo); 756 757 // Determine physical address size and raise an Address Size Fault if 758 // necessary 759 int pa_range = decodePhysAddrRange64(ps); 760 // Clamp to lower limit 761 if (pa_range > physAddrRange) 762 currState->physAddrRange = physAddrRange; 763 else 764 currState->physAddrRange = pa_range; 765 if (checkAddrSizeFaultAArch64(base_addr, currState->physAddrRange)) { 766 DPRINTF(TLB, "Address size fault before any lookup\n"); 767 Fault f; 768 if (currState->isFetch) 769 f = new PrefetchAbort(currState->vaddr_tainted, 770 ArmFault::AddressSizeLL + start_lookup_level, 771 isStage2, 772 ArmFault::LpaeTran); 773 else 774 f = new DataAbort(currState->vaddr_tainted, 775 TlbEntry::DomainType::NoAccess, 776 currState->isWrite, 777 ArmFault::AddressSizeLL + start_lookup_level, 778 isStage2, 779 ArmFault::LpaeTran); 780 781 782 if (currState->timing) { 783 pending = false; 784 nextWalk(currState->tc); 785 currState = NULL; 786 } else { 787 currState->tc = NULL; 788 currState->req = NULL; 789 } 790 return f; 791 792 } 793 794 // Determine descriptor address 795 Addr desc_addr = base_addr | 796 (bits(currState->vaddr, tsz - 1, 797 stride * (3 - start_lookup_level) + grain_size) << 3); 798 799 // Trickbox address check 800 Fault f = tlb->walkTrickBoxCheck(desc_addr, currState->isSecure, 801 currState->vaddr, sizeof(uint64_t), currState->isFetch, 802 currState->isWrite, TlbEntry::DomainType::NoAccess, 803 start_lookup_level); 804 if (f) { 805 DPRINTF(TLB, "Trickbox check caused fault on %#x\n", currState->vaddr_tainted); 806 if (currState->timing) { 807 pending = false; 808 nextWalk(currState->tc); 809 currState = NULL; 810 } else { 811 currState->tc = NULL; 812 currState->req = NULL; 813 } 814 return f; 815 } 816 817 Request::Flags flag = 0; 818 if (currState->sctlr.c == 0) { 819 flag = Request::UNCACHEABLE; 820 } 821 822 currState->longDesc.lookupLevel = start_lookup_level; 823 currState->longDesc.aarch64 = true; 824 currState->longDesc.largeGrain = large_grain; 825 currState->longDesc.grainSize = grain_size; 826 |
|
294 if (currState->timing) { | 827 if (currState->timing) { |
295 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), 296 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, | 828 Event *event; 829 switch (start_lookup_level) { 830 case L0: 831 event = (Event *) &doL0LongDescEvent; 832 break; 833 case L1: 834 event = (Event *) &doL1LongDescEvent; 835 break; 836 case L2: 837 event = (Event *) &doL2LongDescEvent; 838 break; 839 case L3: 840 event = (Event *) &doL3LongDescEvent; 841 break; 842 default: 843 panic("Invalid table lookup level"); 844 break; 845 } 846 port.dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), event, 847 (uint8_t*) &currState->longDesc.data, |
297 currState->tc->getCpuPtr()->clockPeriod(), flag); | 848 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); | 849 DPRINTF(TLBVerbose, 850 "Adding to walker fifo: queue size before adding: %d\n", 851 stateQueues[start_lookup_level].size()); 852 stateQueues[start_lookup_level].push_back(currState); |
302 currState = NULL; 303 } else if (!currState->functional) { | 853 currState = NULL; 854 } else if (!currState->functional) { |
304 port.dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), 305 NULL, (uint8_t*)&currState->l1Desc.data, | 855 port.dmaAction(MemCmd::ReadReq, desc_addr, sizeof(uint64_t), 856 NULL, (uint8_t*) &currState->longDesc.data, |
306 currState->tc->getCpuPtr()->clockPeriod(), flag); | 857 currState->tc->getCpuPtr()->clockPeriod(), flag); |
307 doL1Descriptor(); | 858 doLongDescriptor(); |
308 f = currState->fault; 309 } else { | 859 f = currState->fault; 860 } else { |
310 RequestPtr req = new Request(l1desc_addr, sizeof(uint32_t), flag, masterId); 311 req->taskId(ContextSwitchTaskId::DMA); | 861 RequestPtr req = new Request(desc_addr, sizeof(uint64_t), flag, 862 masterId); |
312 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); | 863 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); |
313 pkt->dataStatic((uint8_t*)&currState->l1Desc.data); | 864 pkt->dataStatic((uint8_t*) &currState->longDesc.data); |
314 port.sendFunctional(pkt); | 865 port.sendFunctional(pkt); |
315 doL1Descriptor(); | 866 doLongDescriptor(); |
316 delete req; 317 delete pkt; 318 f = currState->fault; 319 } 320 321 return f; 322} 323 324void 325TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 326 uint8_t texcb, bool s) 327{ 328 // Note: tc and sctlr local variables are hiding tc and sctrl class 329 // variables 330 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 331 te.shareable = false; // default value 332 te.nonCacheable = false; | 867 delete req; 868 delete pkt; 869 f = currState->fault; 870 } 871 872 return f; 873} 874 875void 876TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 877 uint8_t texcb, bool s) 878{ 879 // Note: tc and sctlr local variables are hiding tc and sctrl class 880 // variables 881 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 882 te.shareable = false; // default value 883 te.nonCacheable = false; |
333 bool outer_shareable = false; | 884 te.outerShareable = false; |
334 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { 335 switch(texcb) { 336 case 0: // Stongly-ordered 337 te.nonCacheable = true; | 885 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { 886 switch(texcb) { 887 case 0: // Stongly-ordered 888 te.nonCacheable = true; |
338 te.mtype = TlbEntry::StronglyOrdered; | 889 te.mtype = TlbEntry::MemoryType::StronglyOrdered; |
339 te.shareable = true; 340 te.innerAttrs = 1; 341 te.outerAttrs = 0; 342 break; 343 case 1: // Shareable Device 344 te.nonCacheable = true; | 890 te.shareable = true; 891 te.innerAttrs = 1; 892 te.outerAttrs = 0; 893 break; 894 case 1: // Shareable Device 895 te.nonCacheable = true; |
345 te.mtype = TlbEntry::Device; | 896 te.mtype = TlbEntry::MemoryType::Device; |
346 te.shareable = true; 347 te.innerAttrs = 3; 348 te.outerAttrs = 0; 349 break; 350 case 2: // Outer and Inner Write-Through, no Write-Allocate | 897 te.shareable = true; 898 te.innerAttrs = 3; 899 te.outerAttrs = 0; 900 break; 901 case 2: // Outer and Inner Write-Through, no Write-Allocate |
351 te.mtype = TlbEntry::Normal; | 902 te.mtype = TlbEntry::MemoryType::Normal; |
352 te.shareable = s; 353 te.innerAttrs = 6; 354 te.outerAttrs = bits(texcb, 1, 0); 355 break; 356 case 3: // Outer and Inner Write-Back, no Write-Allocate | 903 te.shareable = s; 904 te.innerAttrs = 6; 905 te.outerAttrs = bits(texcb, 1, 0); 906 break; 907 case 3: // Outer and Inner Write-Back, no Write-Allocate |
357 te.mtype = TlbEntry::Normal; | 908 te.mtype = TlbEntry::MemoryType::Normal; |
358 te.shareable = s; 359 te.innerAttrs = 7; 360 te.outerAttrs = bits(texcb, 1, 0); 361 break; 362 case 4: // Outer and Inner Non-cacheable 363 te.nonCacheable = true; | 909 te.shareable = s; 910 te.innerAttrs = 7; 911 te.outerAttrs = bits(texcb, 1, 0); 912 break; 913 case 4: // Outer and Inner Non-cacheable 914 te.nonCacheable = true; |
364 te.mtype = TlbEntry::Normal; | 915 te.mtype = TlbEntry::MemoryType::Normal; |
365 te.shareable = s; 366 te.innerAttrs = 0; 367 te.outerAttrs = bits(texcb, 1, 0); 368 break; 369 case 5: // Reserved 370 panic("Reserved texcb value!\n"); 371 break; 372 case 6: // Implementation Defined 373 panic("Implementation-defined texcb value!\n"); 374 break; 375 case 7: // Outer and Inner Write-Back, Write-Allocate | 916 te.shareable = s; 917 te.innerAttrs = 0; 918 te.outerAttrs = bits(texcb, 1, 0); 919 break; 920 case 5: // Reserved 921 panic("Reserved texcb value!\n"); 922 break; 923 case 6: // Implementation Defined 924 panic("Implementation-defined texcb value!\n"); 925 break; 926 case 7: // Outer and Inner Write-Back, Write-Allocate |
376 te.mtype = TlbEntry::Normal; | 927 te.mtype = TlbEntry::MemoryType::Normal; |
377 te.shareable = s; 378 te.innerAttrs = 5; 379 te.outerAttrs = 1; 380 break; 381 case 8: // Non-shareable Device 382 te.nonCacheable = true; | 928 te.shareable = s; 929 te.innerAttrs = 5; 930 te.outerAttrs = 1; 931 break; 932 case 8: // Non-shareable Device 933 te.nonCacheable = true; |
383 te.mtype = TlbEntry::Device; | 934 te.mtype = TlbEntry::MemoryType::Device; |
384 te.shareable = false; 385 te.innerAttrs = 3; 386 te.outerAttrs = 0; 387 break; 388 case 9 ... 15: // Reserved 389 panic("Reserved texcb value!\n"); 390 break; 391 case 16 ... 31: // Cacheable Memory | 935 te.shareable = false; 936 te.innerAttrs = 3; 937 te.outerAttrs = 0; 938 break; 939 case 9 ... 15: // Reserved 940 panic("Reserved texcb value!\n"); 941 break; 942 case 16 ... 31: // Cacheable Memory |
392 te.mtype = TlbEntry::Normal; | 943 te.mtype = TlbEntry::MemoryType::Normal; |
393 te.shareable = s; 394 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 395 te.nonCacheable = true; 396 te.innerAttrs = bits(texcb, 1, 0); 397 te.outerAttrs = bits(texcb, 3, 2); 398 break; 399 default: 400 panic("More than 32 states for 5 bits?\n"); 401 } 402 } else { 403 assert(tc); | 944 te.shareable = s; 945 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 946 te.nonCacheable = true; 947 te.innerAttrs = bits(texcb, 1, 0); 948 te.outerAttrs = bits(texcb, 3, 2); 949 break; 950 default: 951 panic("More than 32 states for 5 bits?\n"); 952 } 953 } else { 954 assert(tc); |
404 PRRR prrr = tc->readMiscReg(MISCREG_PRRR); 405 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); | 955 PRRR prrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_PRRR, 956 currState->tc, !currState->isSecure)); 957 NMRR nmrr = tc->readMiscReg(flattenMiscRegNsBanked(MISCREG_NMRR, 958 currState->tc, !currState->isSecure)); |
406 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); 407 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0; 408 switch(bits(texcb, 2,0)) { 409 case 0: 410 curr_tr = prrr.tr0; 411 curr_ir = nmrr.ir0; 412 curr_or = nmrr.or0; | 959 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); 960 uint8_t curr_tr = 0, curr_ir = 0, curr_or = 0; 961 switch(bits(texcb, 2,0)) { 962 case 0: 963 curr_tr = prrr.tr0; 964 curr_ir = nmrr.ir0; 965 curr_or = nmrr.or0; |
413 outer_shareable = (prrr.nos0 == 0); | 966 te.outerShareable = (prrr.nos0 == 0); |
414 break; 415 case 1: 416 curr_tr = prrr.tr1; 417 curr_ir = nmrr.ir1; 418 curr_or = nmrr.or1; | 967 break; 968 case 1: 969 curr_tr = prrr.tr1; 970 curr_ir = nmrr.ir1; 971 curr_or = nmrr.or1; |
419 outer_shareable = (prrr.nos1 == 0); | 972 te.outerShareable = (prrr.nos1 == 0); |
420 break; 421 case 2: 422 curr_tr = prrr.tr2; 423 curr_ir = nmrr.ir2; 424 curr_or = nmrr.or2; | 973 break; 974 case 2: 975 curr_tr = prrr.tr2; 976 curr_ir = nmrr.ir2; 977 curr_or = nmrr.or2; |
425 outer_shareable = (prrr.nos2 == 0); | 978 te.outerShareable = (prrr.nos2 == 0); |
426 break; 427 case 3: 428 curr_tr = prrr.tr3; 429 curr_ir = nmrr.ir3; 430 curr_or = nmrr.or3; | 979 break; 980 case 3: 981 curr_tr = prrr.tr3; 982 curr_ir = nmrr.ir3; 983 curr_or = nmrr.or3; |
431 outer_shareable = (prrr.nos3 == 0); | 984 te.outerShareable = (prrr.nos3 == 0); |
432 break; 433 case 4: 434 curr_tr = prrr.tr4; 435 curr_ir = nmrr.ir4; 436 curr_or = nmrr.or4; | 985 break; 986 case 4: 987 curr_tr = prrr.tr4; 988 curr_ir = nmrr.ir4; 989 curr_or = nmrr.or4; |
437 outer_shareable = (prrr.nos4 == 0); | 990 te.outerShareable = (prrr.nos4 == 0); |
438 break; 439 case 5: 440 curr_tr = prrr.tr5; 441 curr_ir = nmrr.ir5; 442 curr_or = nmrr.or5; | 991 break; 992 case 5: 993 curr_tr = prrr.tr5; 994 curr_ir = nmrr.ir5; 995 curr_or = nmrr.or5; |
443 outer_shareable = (prrr.nos5 == 0); | 996 te.outerShareable = (prrr.nos5 == 0); |
444 break; 445 case 6: 446 panic("Imp defined type\n"); 447 case 7: 448 curr_tr = prrr.tr7; 449 curr_ir = nmrr.ir7; 450 curr_or = nmrr.or7; | 997 break; 998 case 6: 999 panic("Imp defined type\n"); 1000 case 7: 1001 curr_tr = prrr.tr7; 1002 curr_ir = nmrr.ir7; 1003 curr_or = nmrr.or7; |
451 outer_shareable = (prrr.nos7 == 0); | 1004 te.outerShareable = (prrr.nos7 == 0); |
452 break; 453 } 454 455 switch(curr_tr) { 456 case 0: 457 DPRINTF(TLBVerbose, "StronglyOrdered\n"); | 1005 break; 1006 } 1007 1008 switch(curr_tr) { 1009 case 0: 1010 DPRINTF(TLBVerbose, "StronglyOrdered\n"); |
458 te.mtype = TlbEntry::StronglyOrdered; | 1011 te.mtype = TlbEntry::MemoryType::StronglyOrdered; |
459 te.nonCacheable = true; 460 te.innerAttrs = 1; 461 te.outerAttrs = 0; 462 te.shareable = true; 463 break; 464 case 1: 465 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", 466 prrr.ds1, prrr.ds0, s); | 1012 te.nonCacheable = true; 1013 te.innerAttrs = 1; 1014 te.outerAttrs = 0; 1015 te.shareable = true; 1016 break; 1017 case 1: 1018 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", 1019 prrr.ds1, prrr.ds0, s); |
467 te.mtype = TlbEntry::Device; | 1020 te.mtype = TlbEntry::MemoryType::Device; |
468 te.nonCacheable = true; 469 te.innerAttrs = 3; 470 te.outerAttrs = 0; 471 if (prrr.ds1 && s) 472 te.shareable = true; 473 if (prrr.ds0 && !s) 474 te.shareable = true; 475 break; 476 case 2: 477 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 478 prrr.ns1, prrr.ns0, s); | 1021 te.nonCacheable = true; 1022 te.innerAttrs = 3; 1023 te.outerAttrs = 0; 1024 if (prrr.ds1 && s) 1025 te.shareable = true; 1026 if (prrr.ds0 && !s) 1027 te.shareable = true; 1028 break; 1029 case 2: 1030 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 1031 prrr.ns1, prrr.ns0, s); |
479 te.mtype = TlbEntry::Normal; | 1032 te.mtype = TlbEntry::MemoryType::Normal; |
480 if (prrr.ns1 && s) 481 te.shareable = true; 482 if (prrr.ns0 && !s) 483 te.shareable = true; 484 break; 485 case 3: 486 panic("Reserved type"); 487 } 488 | 1033 if (prrr.ns1 && s) 1034 te.shareable = true; 1035 if (prrr.ns0 && !s) 1036 te.shareable = true; 1037 break; 1038 case 3: 1039 panic("Reserved type"); 1040 } 1041 |
489 if (te.mtype == TlbEntry::Normal){ | 1042 if (te.mtype == TlbEntry::MemoryType::Normal){ |
490 switch(curr_ir) { 491 case 0: 492 te.nonCacheable = true; 493 te.innerAttrs = 0; 494 break; 495 case 1: 496 te.innerAttrs = 5; 497 break; --- 20 unchanged lines hidden (view full) --- 518 te.outerAttrs = 3; 519 break; 520 } 521 } 522 } 523 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \ 524 outerAttrs: %d\n", 525 te.shareable, te.innerAttrs, te.outerAttrs); | 1043 switch(curr_ir) { 1044 case 0: 1045 te.nonCacheable = true; 1046 te.innerAttrs = 0; 1047 break; 1048 case 1: 1049 te.innerAttrs = 5; 1050 break; --- 20 unchanged lines hidden (view full) --- 1071 te.outerAttrs = 3; 1072 break; 1073 } 1074 } 1075 } 1076 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \ 1077 outerAttrs: %d\n", 1078 te.shareable, te.innerAttrs, te.outerAttrs); |
1079 te.setAttributes(false); 1080} |
|
526 | 1081 |
527 /** Formatting for Physical Address Register (PAR) 528 * Only including lower bits (TLB info here) 529 * PAR: 530 * PA [31:12] 531 * Reserved [11] 532 * TLB info [10:1] 533 * NOS [10] (Not Outer Sharable) 534 * NS [9] (Non-Secure) 535 * -- [8] (Implementation Defined) 536 * SH [7] (Sharable) 537 * Inner[6:4](Inner memory attributes) 538 * Outer[3:2](Outer memory attributes) 539 * SS [1] (SuperSection) 540 * F [0] (Fault, Fault Status in [6:1] if faulted) 541 */ 542 te.attributes = ( 543 ((outer_shareable ? 0:1) << 10) | 544 // TODO: NS Bit 545 ((te.shareable ? 1:0) << 7) | 546 (te.innerAttrs << 4) | 547 (te.outerAttrs << 2) 548 // TODO: Supersection bit 549 // TODO: Fault bit 550 ); | 1082void 1083TableWalker::memAttrsLPAE(ThreadContext *tc, TlbEntry &te, 1084 LongDescriptor &lDescriptor) 1085{ 1086 assert(_haveLPAE); |
551 | 1087 |
1088 uint8_t attr; 1089 uint8_t sh = lDescriptor.sh(); 1090 // Different format and source of attributes if this is a stage 2 1091 // translation 1092 if (isStage2) { 1093 attr = lDescriptor.memAttr(); 1094 uint8_t attr_3_2 = (attr >> 2) & 0x3; 1095 uint8_t attr_1_0 = attr & 0x3; |
|
552 | 1096 |
1097 DPRINTF(TLBVerbose, "memAttrsLPAE MemAttr:%#x sh:%#x\n", attr, sh); 1098 1099 if (attr_3_2 == 0) { 1100 te.mtype = attr_1_0 == 0 ? TlbEntry::MemoryType::StronglyOrdered 1101 : TlbEntry::MemoryType::Device; 1102 te.outerAttrs = 0; 1103 te.innerAttrs = attr_1_0 == 0 ? 1 : 3; 1104 te.nonCacheable = true; 1105 } else { 1106 te.mtype = TlbEntry::MemoryType::Normal; 1107 te.outerAttrs = attr_3_2 == 1 ? 0 : 1108 attr_3_2 == 2 ? 2 : 1; 1109 te.innerAttrs = attr_1_0 == 1 ? 0 : 1110 attr_1_0 == 2 ? 6 : 5; 1111 te.nonCacheable = (attr_3_2 == 1) || (attr_1_0 == 1); 1112 } 1113 } else { 1114 uint8_t attrIndx = lDescriptor.attrIndx(); 1115 1116 // LPAE always uses remapping of memory attributes, irrespective of the 1117 // value of SCTLR.TRE 1118 int reg = attrIndx & 0x4 ? MISCREG_MAIR1 : MISCREG_MAIR0; 1119 reg = flattenMiscRegNsBanked(reg, currState->tc, !currState->isSecure); 1120 uint32_t mair = currState->tc->readMiscReg(reg); 1121 attr = (mair >> (8 * (attrIndx % 4))) & 0xff; 1122 uint8_t attr_7_4 = bits(attr, 7, 4); 1123 uint8_t attr_3_0 = bits(attr, 3, 0); 1124 DPRINTF(TLBVerbose, "memAttrsLPAE AttrIndx:%#x sh:%#x, attr %#x\n", attrIndx, sh, attr); 1125 1126 // Note: the memory subsystem only cares about the 'cacheable' memory 1127 // attribute. The other attributes are only used to fill the PAR register 1128 // accordingly to provide the illusion of full support 1129 te.nonCacheable = false; 1130 1131 switch (attr_7_4) { 1132 case 0x0: 1133 // Strongly-ordered or Device memory 1134 if (attr_3_0 == 0x0) 1135 te.mtype = TlbEntry::MemoryType::StronglyOrdered; 1136 else if (attr_3_0 == 0x4) 1137 te.mtype = TlbEntry::MemoryType::Device; 1138 else 1139 panic("Unpredictable behavior\n"); 1140 te.nonCacheable = true; 1141 te.outerAttrs = 0; 1142 break; 1143 case 0x4: 1144 // Normal memory, Outer Non-cacheable 1145 te.mtype = TlbEntry::MemoryType::Normal; 1146 te.outerAttrs = 0; 1147 if (attr_3_0 == 0x4) 1148 // Inner Non-cacheable 1149 te.nonCacheable = true; 1150 else if (attr_3_0 < 0x8) 1151 panic("Unpredictable behavior\n"); 1152 break; 1153 case 0x8: 1154 case 0x9: 1155 case 0xa: 1156 case 0xb: 1157 case 0xc: 1158 case 0xd: 1159 case 0xe: 1160 case 0xf: 1161 if (attr_7_4 & 0x4) { 1162 te.outerAttrs = (attr_7_4 & 1) ? 1 : 3; 1163 } else { 1164 te.outerAttrs = 0x2; 1165 } 1166 // Normal memory, Outer Cacheable 1167 te.mtype = TlbEntry::MemoryType::Normal; 1168 if (attr_3_0 != 0x4 && attr_3_0 < 0x8) 1169 panic("Unpredictable behavior\n"); 1170 break; 1171 default: 1172 panic("Unpredictable behavior\n"); 1173 break; 1174 } 1175 1176 switch (attr_3_0) { 1177 case 0x0: 1178 te.innerAttrs = 0x1; 1179 break; 1180 case 0x4: 1181 te.innerAttrs = attr_7_4 == 0 ? 0x3 : 0; 1182 break; 1183 case 0x8: 1184 case 0x9: 1185 case 0xA: 1186 case 0xB: 1187 te.innerAttrs = 6; 1188 break; 1189 case 0xC: 1190 case 0xD: 1191 case 0xE: 1192 case 0xF: 1193 te.innerAttrs = attr_3_0 & 1 ? 0x5 : 0x7; 1194 break; 1195 default: 1196 panic("Unpredictable behavior\n"); 1197 break; 1198 } 1199 } 1200 1201 te.outerShareable = sh == 2; 1202 te.shareable = (sh & 0x2) ? true : false; 1203 te.setAttributes(true); 1204 te.attributes |= (uint64_t) attr << 56; |
|
553} 554 555void | 1205} 1206 1207void |
1208TableWalker::memAttrsAArch64(ThreadContext *tc, TlbEntry &te, uint8_t attrIndx, 1209 uint8_t sh) 1210{ 1211 DPRINTF(TLBVerbose, "memAttrsAArch64 AttrIndx:%#x sh:%#x\n", attrIndx, sh); 1212 1213 // Select MAIR 1214 uint64_t mair; 1215 switch (currState->el) { 1216 case EL0: 1217 case EL1: 1218 mair = tc->readMiscReg(MISCREG_MAIR_EL1); 1219 break; 1220 case EL2: 1221 mair = tc->readMiscReg(MISCREG_MAIR_EL2); 1222 break; 1223 case EL3: 1224 mair = tc->readMiscReg(MISCREG_MAIR_EL3); 1225 break; 1226 default: 1227 panic("Invalid exception level"); 1228 break; 1229 } 1230 1231 // Select attributes 1232 uint8_t attr = bits(mair, 8 * attrIndx + 7, 8 * attrIndx); 1233 uint8_t attr_lo = bits(attr, 3, 0); 1234 uint8_t attr_hi = bits(attr, 7, 4); 1235 1236 // Memory type 1237 te.mtype = attr_hi == 0 ? TlbEntry::MemoryType::Device : TlbEntry::MemoryType::Normal; 1238 1239 // Cacheability 1240 te.nonCacheable = false; 1241 if (te.mtype == TlbEntry::MemoryType::Device || // Device memory 1242 attr_hi == 0x8 || // Normal memory, Outer Non-cacheable 1243 attr_lo == 0x8) { // Normal memory, Inner Non-cacheable 1244 te.nonCacheable = true; 1245 } 1246 1247 te.shareable = sh == 2; 1248 te.outerShareable = (sh & 0x2) ? true : false; 1249 // Attributes formatted according to the 64-bit PAR 1250 te.attributes = ((uint64_t) attr << 56) | 1251 (1 << 11) | // LPAE bit 1252 (te.ns << 9) | // NS bit 1253 (sh << 7); 1254} 1255 1256void |
|
556TableWalker::doL1Descriptor() 557{ | 1257TableWalker::doL1Descriptor() 1258{ |
1259 if (currState->fault != NoFault) { 1260 return; 1261 } 1262 |
|
558 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", | 1263 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", |
559 currState->vaddr, currState->l1Desc.data); | 1264 currState->vaddr_tainted, currState->l1Desc.data); |
560 TlbEntry te; 561 562 switch (currState->l1Desc.type()) { 563 case L1Descriptor::Ignore: 564 case L1Descriptor::Reserved: 565 if (!currState->timing) { 566 currState->tc = NULL; 567 currState->req = NULL; 568 } 569 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 570 if (currState->isFetch) 571 currState->fault = | 1265 TlbEntry te; 1266 1267 switch (currState->l1Desc.type()) { 1268 case L1Descriptor::Ignore: 1269 case L1Descriptor::Reserved: 1270 if (!currState->timing) { 1271 currState->tc = NULL; 1272 currState->req = NULL; 1273 } 1274 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 1275 if (currState->isFetch) 1276 currState->fault = |
572 new PrefetchAbort(currState->vaddr, ArmFault::Translation0); | 1277 new PrefetchAbort(currState->vaddr_tainted, 1278 ArmFault::TranslationLL + L1, 1279 isStage2, 1280 ArmFault::VmsaTran); |
573 else 574 currState->fault = | 1281 else 1282 currState->fault = |
575 new DataAbort(currState->vaddr, 0, currState->isWrite, 576 ArmFault::Translation0); | 1283 new DataAbort(currState->vaddr_tainted, 1284 TlbEntry::DomainType::NoAccess, 1285 currState->isWrite, 1286 ArmFault::TranslationLL + L1, isStage2, 1287 ArmFault::VmsaTran); |
577 return; 578 case L1Descriptor::Section: 579 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { 580 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 581 * enabled if set, do l1.Desc.setAp0() instead of generating 582 * AccessFlag0 583 */ 584 | 1288 return; 1289 case L1Descriptor::Section: 1290 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { 1291 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 1292 * enabled if set, do l1.Desc.setAp0() instead of generating 1293 * AccessFlag0 1294 */ 1295 |
585 currState->fault = new DataAbort(currState->vaddr, 586 currState->l1Desc.domain(), currState->isWrite, 587 ArmFault::AccessFlag0); | 1296 currState->fault = new DataAbort(currState->vaddr_tainted, 1297 currState->l1Desc.domain(), 1298 currState->isWrite, 1299 ArmFault::AccessFlagLL + L1, 1300 isStage2, 1301 ArmFault::VmsaTran); |
588 } 589 if (currState->l1Desc.supersection()) { 590 panic("Haven't implemented supersections\n"); 591 } | 1302 } 1303 if (currState->l1Desc.supersection()) { 1304 panic("Haven't implemented supersections\n"); 1305 } |
592 te.N = 20; 593 te.pfn = currState->l1Desc.pfn(); 594 te.size = (1<<te.N) - 1; 595 te.global = !currState->l1Desc.global(); 596 te.valid = true; 597 te.vpn = currState->vaddr >> te.N; 598 te.sNp = true; 599 te.xn = currState->l1Desc.xn(); 600 te.ap = currState->l1Desc.ap(); 601 te.domain = currState->l1Desc.domain(); 602 te.asid = currState->contextId; 603 memAttrs(currState->tc, te, currState->sctlr, 604 currState->l1Desc.texcb(), currState->l1Desc.shareable()); | 1306 insertTableEntry(currState->l1Desc, false); 1307 return; 1308 case L1Descriptor::PageTable: 1309 { 1310 Addr l2desc_addr; 1311 l2desc_addr = currState->l1Desc.l2Addr() | 1312 (bits(currState->vaddr, 19, 12) << 2); 1313 DPRINTF(TLB, "L1 descriptor points to page table at: %#x (%s)\n", 1314 l2desc_addr, currState->isSecure ? "s" : "ns"); |
605 | 1315 |
606 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); 607 DPRINTF(TLB, " - N:%d pfn:%#x size: %#x global:%d valid: %d\n", 608 te.N, te.pfn, te.size, te.global, te.valid); 609 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d nc:%d\n", 610 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid, 611 te.nonCacheable); 612 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", 613 currState->l1Desc.domain(), currState->l1Desc.data, 614 (currState->l1Desc.data >> 5) & 0xF ); | 1316 // Trickbox address check 1317 currState->fault = tlb->walkTrickBoxCheck( 1318 l2desc_addr, currState->isSecure, currState->vaddr, 1319 sizeof(uint32_t), currState->isFetch, currState->isWrite, 1320 currState->l1Desc.domain(), L2); |
615 | 1321 |
1322 if (currState->fault) { 1323 if (!currState->timing) { 1324 currState->tc = NULL; 1325 currState->req = NULL; 1326 } 1327 return; 1328 } 1329 1330 Request::Flags flag = 0; 1331 if (currState->isSecure) 1332 flag.set(Request::SECURE); 1333 1334 bool delayed; 1335 delayed = fetchDescriptor(l2desc_addr, 1336 (uint8_t*)&currState->l2Desc.data, 1337 sizeof(uint32_t), flag, -1, &doL2DescEvent, 1338 &TableWalker::doL2Descriptor); 1339 if (delayed) { 1340 currState->delayed = true; 1341 } 1342 1343 return; 1344 } 1345 default: 1346 panic("A new type in a 2 bit field?\n"); 1347 } 1348} 1349 1350void 1351TableWalker::doLongDescriptor() 1352{ 1353 if (currState->fault != NoFault) { 1354 return; 1355 } 1356 1357 DPRINTF(TLB, "L%d descriptor for %#llx is %#llx (%s)\n", 1358 currState->longDesc.lookupLevel, currState->vaddr_tainted, 1359 currState->longDesc.data, 1360 currState->aarch64 ? "AArch64" : "long-desc."); 1361 1362 if ((currState->longDesc.type() == LongDescriptor::Block) || 1363 (currState->longDesc.type() == LongDescriptor::Page)) { 1364 DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, pxn: %d, " 1365 "xn: %d, ap: %d, af: %d, type: %d\n", 1366 currState->longDesc.lookupLevel, 1367 currState->longDesc.data, 1368 currState->longDesc.pxn(), 1369 currState->longDesc.xn(), 1370 currState->longDesc.ap(), 1371 currState->longDesc.af(), 1372 currState->longDesc.type()); 1373 } else { 1374 DPRINTF(TLBVerbose, "Analyzing L%d descriptor: %#llx, type: %d\n", 1375 currState->longDesc.lookupLevel, 1376 currState->longDesc.data, 1377 currState->longDesc.type()); 1378 } 1379 1380 TlbEntry te; 1381 1382 switch (currState->longDesc.type()) { 1383 case LongDescriptor::Invalid: |
|
616 if (!currState->timing) { 617 currState->tc = NULL; 618 currState->req = NULL; 619 } | 1384 if (!currState->timing) { 1385 currState->tc = NULL; 1386 currState->req = NULL; 1387 } |
620 tlb->insert(currState->vaddr, te); | |
621 | 1388 |
1389 DPRINTF(TLB, "L%d descriptor Invalid, causing fault type %d\n", 1390 currState->longDesc.lookupLevel, 1391 ArmFault::TranslationLL + currState->longDesc.lookupLevel); 1392 if (currState->isFetch) 1393 currState->fault = new PrefetchAbort( 1394 currState->vaddr_tainted, 1395 ArmFault::TranslationLL + currState->longDesc.lookupLevel, 1396 isStage2, 1397 ArmFault::LpaeTran); 1398 else 1399 currState->fault = new DataAbort( 1400 currState->vaddr_tainted, 1401 TlbEntry::DomainType::NoAccess, 1402 currState->isWrite, 1403 ArmFault::TranslationLL + currState->longDesc.lookupLevel, 1404 isStage2, 1405 ArmFault::LpaeTran); |
|
622 return; | 1406 return; |
623 case L1Descriptor::PageTable: 624 Addr l2desc_addr; 625 l2desc_addr = currState->l1Desc.l2Addr() | 626 (bits(currState->vaddr, 19,12) << 2); 627 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", 628 l2desc_addr); | 1407 case LongDescriptor::Block: 1408 case LongDescriptor::Page: 1409 { 1410 bool fault = false; 1411 bool aff = false; 1412 // Check for address size fault 1413 if (checkAddrSizeFaultAArch64( 1414 mbits(currState->longDesc.data, MaxPhysAddrRange - 1, 1415 currState->longDesc.offsetBits()), 1416 currState->physAddrRange)) { 1417 fault = true; 1418 DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n", 1419 currState->longDesc.lookupLevel); 1420 // Check for access fault 1421 } else if (currState->longDesc.af() == 0) { 1422 fault = true; 1423 DPRINTF(TLB, "L%d descriptor causing Access Fault\n", 1424 currState->longDesc.lookupLevel); 1425 aff = true; 1426 } 1427 if (fault) { 1428 if (currState->isFetch) 1429 currState->fault = new PrefetchAbort( 1430 currState->vaddr_tainted, 1431 (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) + 1432 currState->longDesc.lookupLevel, 1433 isStage2, 1434 ArmFault::LpaeTran); 1435 else 1436 currState->fault = new DataAbort( 1437 currState->vaddr_tainted, 1438 TlbEntry::DomainType::NoAccess, currState->isWrite, 1439 (aff ? ArmFault::AccessFlagLL : ArmFault::AddressSizeLL) + 1440 currState->longDesc.lookupLevel, 1441 isStage2, 1442 ArmFault::LpaeTran); 1443 } else { 1444 insertTableEntry(currState->longDesc, true); 1445 } 1446 } 1447 return; 1448 case LongDescriptor::Table: 1449 { 1450 // Set hierarchical permission flags 1451 currState->secureLookup = currState->secureLookup && 1452 currState->longDesc.secureTable(); 1453 currState->rwTable = currState->rwTable && 1454 currState->longDesc.rwTable(); 1455 currState->userTable = currState->userTable && 1456 currState->longDesc.userTable(); 1457 currState->xnTable = currState->xnTable || 1458 currState->longDesc.xnTable(); 1459 currState->pxnTable = currState->pxnTable || 1460 currState->longDesc.pxnTable(); |
629 | 1461 |
630 // Trickbox address check 631 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr, 632 sizeof(uint32_t), currState->isFetch, currState->isWrite, 633 currState->l1Desc.domain(), false); | 1462 // Set up next level lookup 1463 Addr next_desc_addr = currState->longDesc.nextDescAddr( 1464 currState->vaddr); |
634 | 1465 |
635 if (currState->fault) { 636 if (!currState->timing) { 637 currState->tc = NULL; 638 currState->req = NULL; | 1466 DPRINTF(TLB, "L%d descriptor points to L%d descriptor at: %#x (%s)\n", 1467 currState->longDesc.lookupLevel, 1468 currState->longDesc.lookupLevel + 1, 1469 next_desc_addr, 1470 currState->secureLookup ? "s" : "ns"); 1471 1472 // Check for address size fault 1473 if (currState->aarch64 && checkAddrSizeFaultAArch64( 1474 next_desc_addr, currState->physAddrRange)) { 1475 DPRINTF(TLB, "L%d descriptor causing Address Size Fault\n", 1476 currState->longDesc.lookupLevel); 1477 if (currState->isFetch) 1478 currState->fault = new PrefetchAbort( 1479 currState->vaddr_tainted, 1480 ArmFault::AddressSizeLL 1481 + currState->longDesc.lookupLevel, 1482 isStage2, 1483 ArmFault::LpaeTran); 1484 else 1485 currState->fault = new DataAbort( 1486 currState->vaddr_tainted, 1487 TlbEntry::DomainType::NoAccess, currState->isWrite, 1488 ArmFault::AddressSizeLL 1489 + currState->longDesc.lookupLevel, 1490 isStage2, 1491 ArmFault::LpaeTran); 1492 return; |
639 } | 1493 } |
640 return; 641 } | |
642 | 1494 |
1495 // Trickbox address check 1496 currState->fault = tlb->walkTrickBoxCheck( 1497 next_desc_addr, currState->vaddr, 1498 currState->vaddr, sizeof(uint64_t), 1499 currState->isFetch, currState->isWrite, 1500 TlbEntry::DomainType::Client, 1501 toLookupLevel(currState->longDesc.lookupLevel +1)); |
|
643 | 1502 |
644 if (currState->timing) { 645 currState->delayed = true; 646 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), 647 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, 648 currState->tc->getCpuPtr()->clockPeriod()); 649 } else if (!currState->functional) { 650 port.dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), 651 NULL, (uint8_t*)&currState->l2Desc.data, 652 currState->tc->getCpuPtr()->clockPeriod()); 653 doL2Descriptor(); 654 } else { 655 RequestPtr req = new Request(l2desc_addr, sizeof(uint32_t), 0, 656 masterId); 657 req->taskId(ContextSwitchTaskId::DMA); 658 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 659 pkt->dataStatic((uint8_t*)&currState->l2Desc.data); 660 port.sendFunctional(pkt); 661 doL2Descriptor(); 662 delete req; 663 delete pkt; | 1503 if (currState->fault) { 1504 if (!currState->timing) { 1505 currState->tc = NULL; 1506 currState->req = NULL; 1507 } 1508 return; 1509 } 1510 1511 Request::Flags flag = 0; 1512 if (currState->secureLookup) 1513 flag.set(Request::SECURE); 1514 1515 currState->longDesc.lookupLevel = 1516 (LookupLevel) (currState->longDesc.lookupLevel + 1); 1517 Event *event = NULL; 1518 switch (currState->longDesc.lookupLevel) { 1519 case L1: 1520 assert(currState->aarch64); 1521 event = &doL1LongDescEvent; 1522 break; 1523 case L2: 1524 event = &doL2LongDescEvent; 1525 break; 1526 case L3: 1527 event = &doL3LongDescEvent; 1528 break; 1529 default: 1530 panic("Wrong lookup level in table walk\n"); 1531 break; 1532 } 1533 1534 bool delayed; 1535 delayed = fetchDescriptor(next_desc_addr, (uint8_t*)&currState->longDesc.data, 1536 sizeof(uint64_t), flag, -1, event, 1537 &TableWalker::doLongDescriptor); 1538 if (delayed) { 1539 currState->delayed = true; 1540 } |
664 } 665 return; 666 default: 667 panic("A new type in a 2 bit field?\n"); 668 } 669} 670 671void 672TableWalker::doL2Descriptor() 673{ | 1541 } 1542 return; 1543 default: 1544 panic("A new type in a 2 bit field?\n"); 1545 } 1546} 1547 1548void 1549TableWalker::doL2Descriptor() 1550{ |
1551 if (currState->fault != NoFault) { 1552 return; 1553 } 1554 |
|
674 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", | 1555 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", |
675 currState->vaddr, currState->l2Desc.data); | 1556 currState->vaddr_tainted, currState->l2Desc.data); |
676 TlbEntry te; 677 678 if (currState->l2Desc.invalid()) { 679 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 680 if (!currState->timing) { 681 currState->tc = NULL; 682 currState->req = NULL; 683 } 684 if (currState->isFetch) 685 currState->fault = | 1557 TlbEntry te; 1558 1559 if (currState->l2Desc.invalid()) { 1560 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 1561 if (!currState->timing) { 1562 currState->tc = NULL; 1563 currState->req = NULL; 1564 } 1565 if (currState->isFetch) 1566 currState->fault = |
686 new PrefetchAbort(currState->vaddr, ArmFault::Translation1); | 1567 new PrefetchAbort(currState->vaddr_tainted, 1568 ArmFault::TranslationLL + L2, 1569 isStage2, 1570 ArmFault::VmsaTran); |
687 else 688 currState->fault = | 1571 else 1572 currState->fault = |
689 new DataAbort(currState->vaddr, currState->l1Desc.domain(), 690 currState->isWrite, ArmFault::Translation1); | 1573 new DataAbort(currState->vaddr_tainted, currState->l1Desc.domain(), 1574 currState->isWrite, ArmFault::TranslationLL + L2, 1575 isStage2, 1576 ArmFault::VmsaTran); |
691 return; 692 } 693 694 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) { 695 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 696 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 697 */ | 1577 return; 1578 } 1579 1580 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) { 1581 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 1582 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 1583 */ |
1584 DPRINTF(TLB, "Generating access fault at L2, afe: %d, ap: %d\n", 1585 currState->sctlr.afe, currState->l2Desc.ap()); |
|
698 699 currState->fault = | 1586 1587 currState->fault = |
700 new DataAbort(currState->vaddr, 0, currState->isWrite, 701 ArmFault::AccessFlag1); 702 | 1588 new DataAbort(currState->vaddr_tainted, 1589 TlbEntry::DomainType::NoAccess, currState->isWrite, 1590 ArmFault::AccessFlagLL + L2, isStage2, 1591 ArmFault::VmsaTran); |
703 } 704 | 1592 } 1593 |
705 if (currState->l2Desc.large()) { 706 te.N = 16; 707 te.pfn = currState->l2Desc.pfn(); 708 } else { 709 te.N = 12; 710 te.pfn = currState->l2Desc.pfn(); 711 } 712 713 te.valid = true; 714 te.size = (1 << te.N) - 1; 715 te.asid = currState->contextId; 716 te.sNp = false; 717 te.vpn = currState->vaddr >> te.N; 718 te.global = currState->l2Desc.global(); 719 te.xn = currState->l2Desc.xn(); 720 te.ap = currState->l2Desc.ap(); 721 te.domain = currState->l1Desc.domain(); 722 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(), 723 currState->l2Desc.shareable()); 724 725 if (!currState->timing) { 726 currState->tc = NULL; 727 currState->req = NULL; 728 } 729 tlb->insert(currState->vaddr, te); | 1594 insertTableEntry(currState->l2Desc, false); |
730} 731 732void 733TableWalker::doL1DescriptorWrapper() 734{ | 1595} 1596 1597void 1598TableWalker::doL1DescriptorWrapper() 1599{ |
735 currState = stateQueueL1.front(); | 1600 currState = stateQueues[L1].front(); |
736 currState->delayed = false; | 1601 currState->delayed = false; |
1602 // if there's a stage2 translation object we don't need it any more 1603 if (currState->stage2Tran) { 1604 delete currState->stage2Tran; 1605 currState->stage2Tran = NULL; 1606 } |
|
737 | 1607 |
1608 |
|
738 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data); 739 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data); 740 | 1609 DPRINTF(TLBVerbose, "L1 Desc object host addr: %p\n",&currState->l1Desc.data); 1610 DPRINTF(TLBVerbose, "L1 Desc object data: %08x\n",currState->l1Desc.data); 1611 |
741 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr); | 1612 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr_tainted); |
742 doL1Descriptor(); 743 | 1613 doL1Descriptor(); 1614 |
744 stateQueueL1.pop_front(); | 1615 stateQueues[L1].pop_front(); |
745 completeDrain(); 746 // Check if fault was generated 747 if (currState->fault != NoFault) { 748 currState->transState->finish(currState->fault, currState->req, 749 currState->tc, currState->mode); 750 751 pending = false; 752 nextWalk(currState->tc); 753 754 currState->req = NULL; 755 currState->tc = NULL; 756 currState->delayed = false; 757 delete currState; 758 } 759 else if (!currState->delayed) { 760 // delay is not set so there is no L2 to do | 1616 completeDrain(); 1617 // Check if fault was generated 1618 if (currState->fault != NoFault) { 1619 currState->transState->finish(currState->fault, currState->req, 1620 currState->tc, currState->mode); 1621 1622 pending = false; 1623 nextWalk(currState->tc); 1624 1625 currState->req = NULL; 1626 currState->tc = NULL; 1627 currState->delayed = false; 1628 delete currState; 1629 } 1630 else if (!currState->delayed) { 1631 // delay is not set so there is no L2 to do |
761 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 762 currState->fault = tlb->translateTiming(currState->req, currState->tc, 763 currState->transState, currState->mode); | 1632 // Don't finish the translation if a stage 2 look up is underway 1633 if (!currState->doingStage2) { 1634 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 1635 currState->fault = tlb->translateTiming(currState->req, currState->tc, 1636 currState->transState, currState->mode); 1637 } |
764 765 pending = false; 766 nextWalk(currState->tc); 767 768 currState->req = NULL; 769 currState->tc = NULL; 770 currState->delayed = false; 771 delete currState; 772 } else { 773 // need to do L2 descriptor | 1638 1639 pending = false; 1640 nextWalk(currState->tc); 1641 1642 currState->req = NULL; 1643 currState->tc = NULL; 1644 currState->delayed = false; 1645 delete currState; 1646 } else { 1647 // need to do L2 descriptor |
774 stateQueueL2.push_back(currState); | 1648 stateQueues[L2].push_back(currState); |
775 } 776 currState = NULL; 777} 778 779void 780TableWalker::doL2DescriptorWrapper() 781{ | 1649 } 1650 currState = NULL; 1651} 1652 1653void 1654TableWalker::doL2DescriptorWrapper() 1655{ |
782 currState = stateQueueL2.front(); | 1656 currState = stateQueues[L2].front(); |
783 assert(currState->delayed); | 1657 assert(currState->delayed); |
1658 // if there's a stage2 translation object we don't need it any more 1659 if (currState->stage2Tran) { 1660 delete currState->stage2Tran; 1661 currState->stage2Tran = NULL; 1662 } |
|
784 785 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", | 1663 1664 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", |
786 currState->vaddr); | 1665 currState->vaddr_tainted); |
787 doL2Descriptor(); 788 789 // Check if fault was generated 790 if (currState->fault != NoFault) { 791 currState->transState->finish(currState->fault, currState->req, 792 currState->tc, currState->mode); 793 } 794 else { | 1666 doL2Descriptor(); 1667 1668 // Check if fault was generated 1669 if (currState->fault != NoFault) { 1670 currState->transState->finish(currState->fault, currState->req, 1671 currState->tc, currState->mode); 1672 } 1673 else { |
795 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 796 currState->fault = tlb->translateTiming(currState->req, currState->tc, 797 currState->transState, currState->mode); | 1674 // Don't finish the translation if a stage 2 look up is underway 1675 if (!currState->doingStage2) { 1676 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 1677 currState->fault = tlb->translateTiming(currState->req, 1678 currState->tc, currState->transState, currState->mode); 1679 } |
798 } 799 800 | 1680 } 1681 1682 |
801 stateQueueL2.pop_front(); | 1683 stateQueues[L2].pop_front(); |
802 completeDrain(); 803 pending = false; 804 nextWalk(currState->tc); 805 806 currState->req = NULL; 807 currState->tc = NULL; 808 currState->delayed = false; 809 810 delete currState; 811 currState = NULL; 812} 813 814void | 1684 completeDrain(); 1685 pending = false; 1686 nextWalk(currState->tc); 1687 1688 currState->req = NULL; 1689 currState->tc = NULL; 1690 currState->delayed = false; 1691 1692 delete currState; 1693 currState = NULL; 1694} 1695 1696void |
1697TableWalker::doL0LongDescriptorWrapper() 1698{ 1699 doLongDescriptorWrapper(L0); 1700} 1701 1702void 1703TableWalker::doL1LongDescriptorWrapper() 1704{ 1705 doLongDescriptorWrapper(L1); 1706} 1707 1708void 1709TableWalker::doL2LongDescriptorWrapper() 1710{ 1711 doLongDescriptorWrapper(L2); 1712} 1713 1714void 1715TableWalker::doL3LongDescriptorWrapper() 1716{ 1717 doLongDescriptorWrapper(L3); 1718} 1719 1720void 1721TableWalker::doLongDescriptorWrapper(LookupLevel curr_lookup_level) 1722{ 1723 currState = stateQueues[curr_lookup_level].front(); 1724 assert(curr_lookup_level == currState->longDesc.lookupLevel); 1725 currState->delayed = false; 1726 1727 // if there's a stage2 translation object we don't need it any more 1728 if (currState->stage2Tran) { 1729 delete currState->stage2Tran; 1730 currState->stage2Tran = NULL; 1731 } 1732 1733 DPRINTF(TLBVerbose, "calling doLongDescriptor for vaddr:%#x\n", 1734 currState->vaddr_tainted); 1735 doLongDescriptor(); 1736 1737 stateQueues[curr_lookup_level].pop_front(); 1738 1739 if (currState->fault != NoFault) { 1740 // A fault was generated 1741 currState->transState->finish(currState->fault, currState->req, 1742 currState->tc, currState->mode); 1743 1744 pending = false; 1745 nextWalk(currState->tc); 1746 1747 currState->req = NULL; 1748 currState->tc = NULL; 1749 currState->delayed = false; 1750 delete currState; 1751 } else if (!currState->delayed) { 1752 // No additional lookups required 1753 // Don't finish the translation if a stage 2 look up is underway 1754 if (!currState->doingStage2) { 1755 DPRINTF(TLBVerbose, "calling translateTiming again\n"); 1756 currState->fault = tlb->translateTiming(currState->req, currState->tc, 1757 currState->transState, 1758 currState->mode); 1759 } 1760 1761 pending = false; 1762 nextWalk(currState->tc); 1763 1764 currState->req = NULL; 1765 currState->tc = NULL; 1766 currState->delayed = false; 1767 delete currState; 1768 } else { 1769 if (curr_lookup_level >= MAX_LOOKUP_LEVELS - 1) 1770 panic("Max. number of lookups already reached in table walk\n"); 1771 // Need to perform additional lookups 1772 stateQueues[currState->longDesc.lookupLevel].push_back(currState); 1773 } 1774 currState = NULL; 1775} 1776 1777 1778void |
|
815TableWalker::nextWalk(ThreadContext *tc) 816{ 817 if (pendingQueue.size()) 818 schedule(doProcessEvent, clockEdge(Cycles(1))); 819} 820 | 1779TableWalker::nextWalk(ThreadContext *tc) 1780{ 1781 if (pendingQueue.size()) 1782 schedule(doProcessEvent, clockEdge(Cycles(1))); 1783} 1784 |
1785bool 1786TableWalker::fetchDescriptor(Addr descAddr, uint8_t *data, int numBytes, 1787 Request::Flags flags, int queueIndex, Event *event, 1788 void (TableWalker::*doDescriptor)()) 1789{ 1790 bool isTiming = currState->timing; |
|
821 | 1791 |
1792 // do the requests for the page table descriptors have to go through the 1793 // second stage MMU 1794 if (currState->stage2Req) { 1795 Fault fault; 1796 flags = flags | TLB::MustBeOne; |
|
822 | 1797 |
1798 if (isTiming) { 1799 Stage2MMU::Stage2Translation *tran = new 1800 Stage2MMU::Stage2Translation(*stage2Mmu, data, event, 1801 currState->vaddr); 1802 currState->stage2Tran = tran; 1803 stage2Mmu->readDataTimed(currState->tc, descAddr, tran, numBytes, 1804 flags, masterId); 1805 fault = tran->fault; 1806 } else { 1807 fault = stage2Mmu->readDataUntimed(currState->tc, 1808 currState->vaddr, descAddr, data, numBytes, flags, masterId, 1809 currState->functional); 1810 } 1811 1812 if (fault != NoFault) { 1813 currState->fault = fault; 1814 } 1815 if (isTiming) { 1816 if (queueIndex >= 0) { 1817 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 1818 stateQueues[queueIndex].size()); 1819 stateQueues[queueIndex].push_back(currState); 1820 currState = NULL; 1821 } 1822 } else { 1823 (this->*doDescriptor)(); 1824 } 1825 } else { 1826 if (isTiming) { 1827 port.dmaAction(MemCmd::ReadReq, descAddr, numBytes, event, data, 1828 currState->tc->getCpuPtr()->clockPeriod(), flags); 1829 if (queueIndex >= 0) { 1830 DPRINTF(TLBVerbose, "Adding to walker fifo: queue size before adding: %d\n", 1831 stateQueues[queueIndex].size()); 1832 stateQueues[queueIndex].push_back(currState); 1833 currState = NULL; 1834 } 1835 } else if (!currState->functional) { 1836 port.dmaAction(MemCmd::ReadReq, descAddr, numBytes, NULL, data, 1837 currState->tc->getCpuPtr()->clockPeriod(), flags); 1838 (this->*doDescriptor)(); 1839 } else { 1840 RequestPtr req = new Request(descAddr, numBytes, flags, masterId); 1841 req->taskId(ContextSwitchTaskId::DMA); 1842 PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 1843 pkt->dataStatic(data); 1844 port.sendFunctional(pkt); 1845 (this->*doDescriptor)(); 1846 delete req; 1847 delete pkt; 1848 } 1849 } 1850 return (isTiming); 1851} 1852 1853void 1854TableWalker::insertTableEntry(DescriptorBase &descriptor, bool longDescriptor) 1855{ 1856 TlbEntry te; 1857 1858 // Create and fill a new page table entry 1859 te.valid = true; 1860 te.longDescFormat = longDescriptor; 1861 te.isHyp = currState->isHyp; 1862 te.asid = currState->asid; 1863 te.vmid = currState->vmid; 1864 te.N = descriptor.offsetBits(); 1865 te.vpn = currState->vaddr >> te.N; 1866 te.size = (1<<te.N) - 1; 1867 te.pfn = descriptor.pfn(); 1868 te.domain = descriptor.domain(); 1869 te.lookupLevel = descriptor.lookupLevel; 1870 te.ns = !descriptor.secure(haveSecurity, currState) || isStage2; 1871 te.nstid = !currState->isSecure; 1872 te.xn = descriptor.xn(); 1873 if (currState->aarch64) 1874 te.el = currState->el; 1875 else 1876 te.el = 1; 1877 1878 // ASID has no meaning for stage 2 TLB entries, so mark all stage 2 entries 1879 // as global 1880 te.global = descriptor.global(currState) || isStage2; 1881 if (longDescriptor) { 1882 LongDescriptor lDescriptor = 1883 dynamic_cast<LongDescriptor &>(descriptor); 1884 1885 te.xn |= currState->xnTable; 1886 te.pxn = currState->pxnTable || lDescriptor.pxn(); 1887 if (isStage2) { 1888 // this is actually the HAP field, but its stored in the same bit 1889 // possitions as the AP field in a stage 1 translation. 1890 te.hap = lDescriptor.ap(); 1891 } else { 1892 te.ap = ((!currState->rwTable || descriptor.ap() >> 1) << 1) | 1893 (currState->userTable && (descriptor.ap() & 0x1)); 1894 } 1895 if (currState->aarch64) 1896 memAttrsAArch64(currState->tc, te, currState->longDesc.attrIndx(), 1897 currState->longDesc.sh()); 1898 else 1899 memAttrsLPAE(currState->tc, te, lDescriptor); 1900 } else { 1901 te.ap = descriptor.ap(); 1902 memAttrs(currState->tc, te, currState->sctlr, descriptor.texcb(), 1903 descriptor.shareable()); 1904 } 1905 1906 // Debug output 1907 DPRINTF(TLB, descriptor.dbgHeader().c_str()); 1908 DPRINTF(TLB, " - N:%d pfn:%#x size:%#x global:%d valid:%d\n", 1909 te.N, te.pfn, te.size, te.global, te.valid); 1910 DPRINTF(TLB, " - vpn:%#x xn:%d pxn:%d ap:%d domain:%d asid:%d " 1911 "vmid:%d hyp:%d nc:%d ns:%d\n", te.vpn, te.xn, te.pxn, 1912 te.ap, static_cast<uint8_t>(te.domain), te.asid, te.vmid, te.isHyp, 1913 te.nonCacheable, te.ns); 1914 DPRINTF(TLB, " - domain from L%d desc:%d data:%#x\n", 1915 descriptor.lookupLevel, static_cast<uint8_t>(descriptor.domain()), 1916 descriptor.getRawData()); 1917 1918 // Insert the entry into the TLB 1919 tlb->insert(currState->vaddr, te); 1920 if (!currState->timing) { 1921 currState->tc = NULL; 1922 currState->req = NULL; 1923 } 1924} 1925 |
|
823ArmISA::TableWalker * 824ArmTableWalkerParams::create() 825{ 826 return new ArmISA::TableWalker(this); 827} 828 | 1926ArmISA::TableWalker * 1927ArmTableWalkerParams::create() 1928{ 1929 return new ArmISA::TableWalker(this); 1930} 1931 |
1932LookupLevel 1933TableWalker::toLookupLevel(uint8_t lookup_level_as_int) 1934{ 1935 switch (lookup_level_as_int) { 1936 case L1: 1937 return L1; 1938 case L2: 1939 return L2; 1940 case L3: 1941 return L3; 1942 default: 1943 panic("Invalid lookup level conversion"); 1944 } 1945} |
|