table_walker.cc (7438:8e4b37136330) | table_walker.cc (7439:b4c6b2532bbf) |
---|---|
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 --- 29 unchanged lines hidden (view full) --- 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 | 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 --- 29 unchanged lines hidden (view full) --- 38 */ 39 40#include "arch/arm/faults.hh" 41#include "arch/arm/table_walker.hh" 42#include "arch/arm/tlb.hh" 43#include "dev/io_device.hh" 44#include "cpu/thread_context.hh" 45 |
46#define NUM_WALKERS 2 // 2 should be enough to handle crossing page boundaries |
|
46 47using namespace ArmISA; 48 49TableWalker::TableWalker(const Params *p) | 47 48using namespace ArmISA; 49 50TableWalker::TableWalker(const Params *p) |
50 : MemObject(p), port(NULL), tlb(NULL), tc(NULL), req(NULL), 51 doL1DescEvent(this), doL2DescEvent(this) 52{} | 51 : MemObject(p), stateQueue(NUM_WALKERS), port(NULL), tlb(NULL), 52 currState(NULL), doL1DescEvent(this), doL2DescEvent(this) 53{ 54 sctlr = NULL; 55} |
53 54TableWalker::~TableWalker() 55{ 56 ; 57} 58 59 60unsigned int --- 17 unchanged lines hidden (view full) --- 78 } 79 return NULL; 80} 81 82Fault 83TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode, 84 TLB::Translation *_trans, bool _timing) 85{ | 56 57TableWalker::~TableWalker() 58{ 59 ; 60} 61 62 63unsigned int --- 17 unchanged lines hidden (view full) --- 81 } 82 return NULL; 83} 84 85Fault 86TableWalker::walk(RequestPtr _req, ThreadContext *_tc, uint8_t _cid, TLB::Mode _mode, 87 TLB::Translation *_trans, bool _timing) 88{ |
86 // Right now 1 CPU == 1 TLB == 1 TLB walker 87 // In the future we might want to change this as multiple 88 // threads/contexts could share a walker and/or a TLB 89 if (tc || req) 90 panic("Overlapping TLB walks attempted\n"); | 89 if (!currState) { 90 // For atomic mode, a new WalkerState instance should be only created 91 // once per TLB. For timing mode, a new instance is generated for every 92 // TLB miss. 93 DPRINTF(TLBVerbose, "creating new instance of WalkerState\n"); |
91 | 94 |
92 tc = _tc; 93 transState = _trans; 94 req = _req; 95 fault = NoFault; 96 contextId = _cid; 97 timing = _timing; 98 mode = _mode; | 95 currState = new WalkerState(); 96 currState->tableWalker = this; 97 } 98 else if (_timing) { 99 panic("currState should always be empty in timing mode!\n"); 100 } |
99 | 101 |
102 currState->tc = _tc; 103 currState->transState = _trans; 104 currState->req = _req; 105 currState->fault = NoFault; 106 currState->contextId = _cid; 107 currState->timing = _timing; 108 currState->mode = _mode; 109 |
|
100 /** @todo These should be cached or grabbed from cached copies in 101 the TLB, all these miscreg reads are expensive */ | 110 /** @todo These should be cached or grabbed from cached copies in 111 the TLB, all these miscreg reads are expensive */ |
102 vaddr = req->getVaddr() & ~PcModeMask; 103 sctlr = tc->readMiscReg(MISCREG_SCTLR); 104 cpsr = tc->readMiscReg(MISCREG_CPSR); 105 N = tc->readMiscReg(MISCREG_TTBCR); 106 Addr ttbr = 0; | 112 currState->vaddr = currState->req->getVaddr() & ~PcModeMask; 113 currState->sctlr = currState->tc->readMiscReg(MISCREG_SCTLR); 114 sctlr = currState->sctlr; 115 currState->cpsr = currState->tc->readMiscReg(MISCREG_CPSR); 116 currState->N = currState->tc->readMiscReg(MISCREG_TTBCR); |
107 | 117 |
108 isFetch = (mode == TLB::Execute); 109 isWrite = (mode == TLB::Write); 110 isPriv = (cpsr.mode != MODE_USER); | 118 currState->isFetch = (currState->mode == TLB::Execute); 119 currState->isWrite = (currState->mode == TLB::Write); 120 currState->isPriv = (currState->cpsr.mode != MODE_USER); |
111 | 121 |
122 Addr ttbr = 0; 123 |
|
112 // If translation isn't enabled, we shouldn't be here | 124 // If translation isn't enabled, we shouldn't be here |
113 assert(sctlr.m); | 125 assert(currState->sctlr.m); |
114 115 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n", | 126 127 DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n", |
116 vaddr, N, mbits(vaddr, 31, 32-N)); | 128 currState->vaddr, currState->N, mbits(currState->vaddr, 31, 129 32-currState->N)); |
117 | 130 |
118 if (N == 0 || !mbits(vaddr, 31, 32-N)) { | 131 if (currState->N == 0 || !mbits(currState->vaddr, 31, 32-currState->N)) { |
119 DPRINTF(TLB, " - Selecting TTBR0\n"); | 132 DPRINTF(TLB, " - Selecting TTBR0\n"); |
120 ttbr = tc->readMiscReg(MISCREG_TTBR0); | 133 ttbr = currState->tc->readMiscReg(MISCREG_TTBR0); |
121 } else { 122 DPRINTF(TLB, " - Selecting TTBR1\n"); | 134 } else { 135 DPRINTF(TLB, " - Selecting TTBR1\n"); |
123 ttbr = tc->readMiscReg(MISCREG_TTBR1); 124 N = 0; | 136 ttbr = currState->tc->readMiscReg(MISCREG_TTBR1); 137 currState->N = 0; |
125 } 126 | 138 } 139 |
127 Addr l1desc_addr = mbits(ttbr, 31, 14-N) | (bits(vaddr,31-N,20) << 2); | 140 Addr l1desc_addr = mbits(ttbr, 31, 14-currState->N) | 141 (bits(currState->vaddr,31-currState->N,20) << 2); |
128 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr); 129 130 131 // Trickbox address check | 142 DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr); 143 144 145 // Trickbox address check |
132 fault = tlb->walkTrickBoxCheck(l1desc_addr, vaddr, sizeof(uint32_t), 133 isFetch, isWrite, 0, true); 134 if (fault) { 135 tc = NULL; 136 req = NULL; 137 return fault; | 146 Fault f; 147 f = tlb->walkTrickBoxCheck(l1desc_addr, currState->vaddr, sizeof(uint32_t), 148 currState->isFetch, currState->isWrite, 0, true); 149 if (f) { 150 currState->tc = NULL; 151 currState->req = NULL; 152 return f; |
138 } 139 | 153 } 154 |
140 if (timing) { | 155 if (currState->timing) { |
141 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), | 156 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), |
142 &doL1DescEvent, (uint8_t*)&l1Desc.data, (Tick)0); | 157 &doL1DescEvent, (uint8_t*)&currState->l1Desc.data, (Tick)0); 158 DPRINTF(TLBVerbose, "Adding to walker fifo: %d free before adding\n", 159 stateQueue.free_slots()); 160 stateQueue.add(*currState); 161 currState = NULL; |
143 } else { 144 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), | 162 } else { 163 port->dmaAction(MemCmd::ReadReq, l1desc_addr, sizeof(uint32_t), |
145 NULL, (uint8_t*)&l1Desc.data, (Tick)0); | 164 NULL, (uint8_t*)&currState->l1Desc.data, (Tick)0); |
146 doL1Descriptor(); | 165 doL1Descriptor(); |
166 f = currState->fault; |
|
147 } 148 | 167 } 168 |
149 return fault; | 169 return f; |
150} 151 152void | 170} 171 172void |
153TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, uint8_t texcb, bool s) | 173TableWalker::memAttrs(ThreadContext *tc, TlbEntry &te, SCTLR sctlr, 174 uint8_t texcb, bool s) |
154{ | 175{ |
155 // Note: tc local variable is hiding tc class variable | 176 // Note: tc and sctlr local variables are hiding tc and sctrl class 177 // variables |
156 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 157 te.shareable = false; // default value 158 bool outer_shareable = false; | 178 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 179 te.shareable = false; // default value 180 bool outer_shareable = false; |
159 if (sctlr.tre == 0) { | 181 if (sctlr.tre == 0 || ((sctlr.tre == 1) && (sctlr.m == 0))) { |
160 switch(texcb) { 161 case 0: // Stongly-ordered 162 te.nonCacheable = true; 163 te.mtype = TlbEntry::StronglyOrdered; 164 te.shareable = true; 165 te.innerAttrs = 1; 166 te.outerAttrs = 0; 167 break; --- 19 unchanged lines hidden (view full) --- 187 case 4: // Outer and Inner Non-cacheable 188 te.nonCacheable = true; 189 te.mtype = TlbEntry::Normal; 190 te.shareable = s; 191 te.innerAttrs = 0; 192 te.outerAttrs = bits(texcb, 1, 0); 193 break; 194 case 5: // Reserved | 182 switch(texcb) { 183 case 0: // Stongly-ordered 184 te.nonCacheable = true; 185 te.mtype = TlbEntry::StronglyOrdered; 186 te.shareable = true; 187 te.innerAttrs = 1; 188 te.outerAttrs = 0; 189 break; --- 19 unchanged lines hidden (view full) --- 209 case 4: // Outer and Inner Non-cacheable 210 te.nonCacheable = true; 211 te.mtype = TlbEntry::Normal; 212 te.shareable = s; 213 te.innerAttrs = 0; 214 te.outerAttrs = bits(texcb, 1, 0); 215 break; 216 case 5: // Reserved |
217 panic("Reserved texcb value!\n"); |
|
195 break; 196 case 6: // Implementation Defined | 218 break; 219 case 6: // Implementation Defined |
220 panic("Implementation-defined texcb value!\n"); |
|
197 break; 198 case 7: // Outer and Inner Write-Back, Write-Allocate 199 te.mtype = TlbEntry::Normal; 200 te.shareable = s; 201 te.innerAttrs = 5; 202 te.outerAttrs = 1; 203 break; 204 case 8: // Non-shareable Device 205 te.nonCacheable = true; 206 te.mtype = TlbEntry::Device; 207 te.shareable = false; 208 te.innerAttrs = 3; 209 te.outerAttrs = 0; 210 break; 211 case 9 ... 15: // Reserved | 221 break; 222 case 7: // Outer and Inner Write-Back, Write-Allocate 223 te.mtype = TlbEntry::Normal; 224 te.shareable = s; 225 te.innerAttrs = 5; 226 te.outerAttrs = 1; 227 break; 228 case 8: // Non-shareable Device 229 te.nonCacheable = true; 230 te.mtype = TlbEntry::Device; 231 te.shareable = false; 232 te.innerAttrs = 3; 233 te.outerAttrs = 0; 234 break; 235 case 9 ... 15: // Reserved |
236 panic("Reserved texcb value!\n"); |
|
212 break; 213 case 16 ... 31: // Cacheable Memory 214 te.mtype = TlbEntry::Normal; 215 te.shareable = s; 216 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 217 te.nonCacheable = true; 218 te.innerAttrs = bits(texcb, 1, 0); 219 te.outerAttrs = bits(texcb, 3, 2); --- 78 unchanged lines hidden (view full) --- 298 case 2: 299 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 300 prrr.ns1, prrr.ns0, s); 301 te.mtype = TlbEntry::Normal; 302 if (prrr.ns1 && s) 303 te.shareable = true; 304 if (prrr.ns0 && !s) 305 te.shareable = true; | 237 break; 238 case 16 ... 31: // Cacheable Memory 239 te.mtype = TlbEntry::Normal; 240 te.shareable = s; 241 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 242 te.nonCacheable = true; 243 te.innerAttrs = bits(texcb, 1, 0); 244 te.outerAttrs = bits(texcb, 3, 2); --- 78 unchanged lines hidden (view full) --- 323 case 2: 324 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 325 prrr.ns1, prrr.ns0, s); 326 te.mtype = TlbEntry::Normal; 327 if (prrr.ns1 && s) 328 te.shareable = true; 329 if (prrr.ns0 && !s) 330 te.shareable = true; |
306 //te.shareable = outer_shareable; | |
307 break; 308 case 3: 309 panic("Reserved type"); 310 } 311 312 if (te.mtype == TlbEntry::Normal){ 313 switch(curr_ir) { 314 case 0: --- 23 unchanged lines hidden (view full) --- 338 te.outerAttrs = 2; 339 break; 340 case 3: 341 te.outerAttrs = 3; 342 break; 343 } 344 } 345 } | 331 break; 332 case 3: 333 panic("Reserved type"); 334 } 335 336 if (te.mtype == TlbEntry::Normal){ 337 switch(curr_ir) { 338 case 0: --- 23 unchanged lines hidden (view full) --- 362 te.outerAttrs = 2; 363 break; 364 case 3: 365 te.outerAttrs = 3; 366 break; 367 } 368 } 369 } |
370 DPRINTF(TLBVerbose, "memAttrs: shareable: %d, innerAttrs: %d, \ 371 outerAttrs: %d\n", 372 te.shareable, te.innerAttrs, te.outerAttrs); |
|
346 347 /** Formatting for Physical Address Register (PAR) 348 * Only including lower bits (TLB info here) 349 * PAR: 350 * PA [31:12] 351 * Reserved [11] 352 * TLB info [10:1] 353 * NOS [10] (Not Outer Sharable) --- 16 unchanged lines hidden (view full) --- 370 ); 371 372 373} 374 375void 376TableWalker::doL1Descriptor() 377{ | 373 374 /** Formatting for Physical Address Register (PAR) 375 * Only including lower bits (TLB info here) 376 * PAR: 377 * PA [31:12] 378 * Reserved [11] 379 * TLB info [10:1] 380 * NOS [10] (Not Outer Sharable) --- 16 unchanged lines hidden (view full) --- 397 ); 398 399 400} 401 402void 403TableWalker::doL1Descriptor() 404{ |
378 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", vaddr, l1Desc.data); | 405 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", 406 currState->vaddr, currState->l1Desc.data); |
379 TlbEntry te; 380 | 407 TlbEntry te; 408 |
381 switch (l1Desc.type()) { | 409 switch (currState->l1Desc.type()) { |
382 case L1Descriptor::Ignore: 383 case L1Descriptor::Reserved: | 410 case L1Descriptor::Ignore: 411 case L1Descriptor::Reserved: |
384 if (!delayed) { 385 tc = NULL; 386 req = NULL; | 412 if (!currState->delayed) { 413 currState->tc = NULL; 414 currState->req = NULL; |
387 } 388 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); | 415 } 416 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); |
389 if (isFetch) 390 fault = new PrefetchAbort(vaddr, ArmFault::Translation0); | 417 if (currState->isFetch) 418 currState->fault = 419 new PrefetchAbort(currState->vaddr, ArmFault::Translation0); |
391 else | 420 else |
392 fault = new DataAbort(vaddr, NULL, isWrite, | 421 currState->fault = 422 new DataAbort(currState->vaddr, NULL, currState->isWrite, |
393 ArmFault::Translation0); 394 return; 395 case L1Descriptor::Section: | 423 ArmFault::Translation0); 424 return; 425 case L1Descriptor::Section: |
396 if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) { | 426 if (currState->sctlr.afe && bits(currState->l1Desc.ap(), 0) == 0) { |
397 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 398 * enabled if set, do l1.Desc.setAp0() instead of generating 399 * AccessFlag0 400 */ 401 | 427 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 428 * enabled if set, do l1.Desc.setAp0() instead of generating 429 * AccessFlag0 430 */ 431 |
402 fault = new DataAbort(vaddr, NULL, isWrite, | 432 currState->fault = 433 new DataAbort(currState->vaddr, NULL, currState->isWrite, |
403 ArmFault::AccessFlag0); 404 } 405 | 434 ArmFault::AccessFlag0); 435 } 436 |
406 if (l1Desc.supersection()) { | 437 if (currState->l1Desc.supersection()) { |
407 panic("Haven't implemented supersections\n"); 408 } 409 te.N = 20; | 438 panic("Haven't implemented supersections\n"); 439 } 440 te.N = 20; |
410 te.pfn = l1Desc.pfn(); | 441 te.pfn = currState->l1Desc.pfn(); |
411 te.size = (1<<te.N) - 1; | 442 te.size = (1<<te.N) - 1; |
412 te.global = !l1Desc.global(); | 443 te.global = !currState->l1Desc.global(); |
413 te.valid = true; | 444 te.valid = true; |
414 te.vpn = vaddr >> te.N; | 445 te.vpn = currState->vaddr >> te.N; |
415 te.sNp = true; | 446 te.sNp = true; |
416 te.xn = l1Desc.xn(); 417 te.ap = l1Desc.ap(); 418 te.domain = l1Desc.domain(); 419 te.asid = contextId; 420 memAttrs(tc, te, l1Desc.texcb(), l1Desc.shareable()); | 447 te.xn = currState->l1Desc.xn(); 448 te.ap = currState->l1Desc.ap(); 449 te.domain = currState->l1Desc.domain(); 450 te.asid = currState->contextId; 451 memAttrs(currState->tc, te, currState->sctlr, 452 currState->l1Desc.texcb(), currState->l1Desc.shareable()); |
421 422 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); 423 DPRINTF(TLB, " - N%d pfn:%#x size: %#x global:%d valid: %d\n", 424 te.N, te.pfn, te.size, te.global, te.valid); 425 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d\n", 426 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid); 427 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", | 453 454 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); 455 DPRINTF(TLB, " - N%d pfn:%#x size: %#x global:%d valid: %d\n", 456 te.N, te.pfn, te.size, te.global, te.valid); 457 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d\n", 458 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid); 459 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", |
428 l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF ); | 460 currState->l1Desc.domain(), currState->l1Desc.data, 461 (currState->l1Desc.data >> 5) & 0xF ); |
429 | 462 |
430 if (!timing) { 431 tc = NULL; 432 req = NULL; | 463 if (!currState->timing) { 464 currState->tc = NULL; 465 currState->req = NULL; |
433 } | 466 } |
434 tlb->insert(vaddr, te); | 467 tlb->insert(currState->vaddr, te); |
435 436 return; 437 case L1Descriptor::PageTable: 438 Addr l2desc_addr; | 468 469 return; 470 case L1Descriptor::PageTable: 471 Addr l2desc_addr; |
439 l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2); | 472 l2desc_addr = currState->l1Desc.l2Addr() | 473 (bits(currState->vaddr, 19,12) << 2); |
440 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", 441 l2desc_addr); 442 443 // Trickbox address check | 474 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", 475 l2desc_addr); 476 477 // Trickbox address check |
444 fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t), 445 isFetch, isWrite, l1Desc.domain(), false); 446 if (fault) { 447 if (!timing) { 448 tc = NULL; 449 req = NULL; | 478 currState->fault = tlb->walkTrickBoxCheck(l2desc_addr, currState->vaddr, 479 sizeof(uint32_t), currState->isFetch, currState->isWrite, 480 currState->l1Desc.domain(), false); 481 482 if (currState->fault) { 483 if (!currState->timing) { 484 currState->tc = NULL; 485 currState->req = NULL; |
450 } 451 return; 452 } 453 454 | 486 } 487 return; 488 } 489 490 |
455 if (timing) { 456 delayed = true; | 491 if (currState->timing) { 492 currState->delayed = true; |
457 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), | 493 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), |
458 &doL2DescEvent, (uint8_t*)&l2Desc.data, 0); | 494 &doL2DescEvent, (uint8_t*)&currState->l2Desc.data, 0); |
459 } else { 460 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), | 495 } else { 496 port->dmaAction(MemCmd::ReadReq, l2desc_addr, sizeof(uint32_t), |
461 NULL, (uint8_t*)&l2Desc.data, 0); | 497 NULL, (uint8_t*)&currState->l2Desc.data, 0); |
462 doL2Descriptor(); 463 } 464 return; 465 default: 466 panic("A new type in a 2 bit field?\n"); 467 } 468} 469 470void 471TableWalker::doL2Descriptor() 472{ | 498 doL2Descriptor(); 499 } 500 return; 501 default: 502 panic("A new type in a 2 bit field?\n"); 503 } 504} 505 506void 507TableWalker::doL2Descriptor() 508{ |
473 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data); | 509 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", 510 currState->vaddr, currState->l2Desc.data); |
474 TlbEntry te; 475 | 511 TlbEntry te; 512 |
476 if (l2Desc.invalid()) { | 513 if (currState->l2Desc.invalid()) { |
477 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); | 514 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); |
478 if (!delayed) { 479 tc = NULL; 480 req = NULL; | 515 if (!currState->delayed) { 516 currState->tc = NULL; 517 currState->req = NULL; |
481 } | 518 } |
482 if (isFetch) 483 fault = new PrefetchAbort(vaddr, ArmFault::Translation1); | 519 if (currState->isFetch) 520 currState->fault = 521 new PrefetchAbort(currState->vaddr, ArmFault::Translation1); |
484 else | 522 else |
485 fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, 486 ArmFault::Translation1); | 523 currState->fault = 524 new DataAbort(currState->vaddr, currState->l1Desc.domain(), 525 currState->isWrite, ArmFault::Translation1); |
487 return; 488 } 489 | 526 return; 527 } 528 |
490 if (sctlr.afe && bits(l2Desc.ap(), 0) == 0) { | 529 if (currState->sctlr.afe && bits(currState->l2Desc.ap(), 0) == 0) { |
491 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 492 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 493 */ 494 | 530 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 531 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 532 */ 533 |
495 fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::AccessFlag1); | 534 currState->fault = 535 new DataAbort(currState->vaddr, NULL, currState->isWrite, 536 ArmFault::AccessFlag1); 537 |
496 } 497 | 538 } 539 |
498 if (l2Desc.large()) { | 540 if (currState->l2Desc.large()) { |
499 te.N = 16; | 541 te.N = 16; |
500 te.pfn = l2Desc.pfn(); | 542 te.pfn = currState->l2Desc.pfn(); |
501 } else { 502 te.N = 12; | 543 } else { 544 te.N = 12; |
503 te.pfn = l2Desc.pfn(); | 545 te.pfn = currState->l2Desc.pfn(); |
504 } 505 506 te.valid = true; 507 te.size = (1 << te.N) - 1; | 546 } 547 548 te.valid = true; 549 te.size = (1 << te.N) - 1; |
508 te.asid = contextId; | 550 te.asid = currState->contextId; |
509 te.sNp = false; | 551 te.sNp = false; |
510 te.vpn = vaddr >> te.N; 511 te.global = l2Desc.global(); 512 te.xn = l2Desc.xn(); 513 te.ap = l2Desc.ap(); 514 te.domain = l1Desc.domain(); 515 memAttrs(tc, te, l2Desc.texcb(), l2Desc.shareable()); | 552 te.vpn = currState->vaddr >> te.N; 553 te.global = currState->l2Desc.global(); 554 te.xn = currState->l2Desc.xn(); 555 te.ap = currState->l2Desc.ap(); 556 te.domain = currState->l1Desc.domain(); 557 memAttrs(currState->tc, te, currState->sctlr, currState->l2Desc.texcb(), 558 currState->l2Desc.shareable()); |
516 | 559 |
517 if (!delayed) { 518 tc = NULL; 519 req = NULL; | 560 if (!currState->delayed) { 561 currState->tc = NULL; 562 currState->req = NULL; |
520 } | 563 } |
521 tlb->insert(vaddr, te); | 564 tlb->insert(currState->vaddr, te); |
522} 523 524void 525TableWalker::doL1DescriptorWrapper() 526{ | 565} 566 567void 568TableWalker::doL1DescriptorWrapper() 569{ |
527 delayed = false; | 570 currState = stateQueue.peek(); 571 currState->delayed = false; |
528 | 572 |
529 DPRINTF(TLBVerbose, "calling doL1Descriptor\n"); | 573 DPRINTF(TLBVerbose, "calling doL1Descriptor for vaddr:%#x\n", currState->vaddr); |
530 doL1Descriptor(); 531 532 // Check if fault was generated | 574 doL1Descriptor(); 575 576 // Check if fault was generated |
533 if (fault != NoFault) { 534 transState->finish(fault, req, tc, mode); | 577 if (currState->fault != NoFault) { 578 currState->transState->finish(currState->fault, currState->req, 579 currState->tc, currState->mode); |
535 | 580 |
536 req = NULL; 537 tc = NULL; 538 delayed = false; | 581 currState->req = NULL; 582 currState->tc = NULL; 583 currState->delayed = false; 584 585 stateQueue.remove(); |
539 } | 586 } |
540 else if (!delayed) { | 587 else if (!currState->delayed) { |
541 DPRINTF(TLBVerbose, "calling translateTiming again\n"); | 588 DPRINTF(TLBVerbose, "calling translateTiming again\n"); |
542 fault = tlb->translateTiming(req, tc, transState, mode); | 589 currState->fault = tlb->translateTiming(currState->req, currState->tc, 590 currState->transState, currState->mode); |
543 | 591 |
544 req = NULL; 545 tc = NULL; 546 delayed = false; | 592 currState->req = NULL; 593 currState->tc = NULL; 594 currState->delayed = false; 595 596 stateQueue.remove(); |
547 } | 597 } |
598 currState = NULL; |
|
548} 549 550void 551TableWalker::doL2DescriptorWrapper() 552{ | 599} 600 601void 602TableWalker::doL2DescriptorWrapper() 603{ |
553 assert(delayed); | 604 currState = stateQueue.peek(); 605 assert(currState->delayed); |
554 | 606 |
555 DPRINTF(TLBVerbose, "calling doL2Descriptor\n"); | 607 DPRINTF(TLBVerbose, "calling doL2Descriptor for vaddr:%#x\n", 608 currState->vaddr); |
556 doL2Descriptor(); 557 558 // Check if fault was generated | 609 doL2Descriptor(); 610 611 // Check if fault was generated |
559 if (fault != NoFault) { 560 transState->finish(fault, req, tc, mode); | 612 if (currState->fault != NoFault) { 613 currState->transState->finish(currState->fault, currState->req, 614 currState->tc, currState->mode); |
561 } 562 else { 563 DPRINTF(TLBVerbose, "calling translateTiming again\n"); | 615 } 616 else { 617 DPRINTF(TLBVerbose, "calling translateTiming again\n"); |
564 fault = tlb->translateTiming(req, tc, transState, mode); | 618 currState->fault = tlb->translateTiming(currState->req, currState->tc, 619 currState->transState, currState->mode); |
565 } 566 | 620 } 621 |
567 req = NULL; 568 tc = NULL; 569 delayed = false; | 622 currState->req = NULL; 623 currState->tc = NULL; 624 currState->delayed = false; 625 626 stateQueue.remove(); 627 currState = NULL; |
570} 571 572ArmISA::TableWalker * 573ArmTableWalkerParams::create() 574{ 575 return new ArmISA::TableWalker(this); 576} 577 | 628} 629 630ArmISA::TableWalker * 631ArmTableWalkerParams::create() 632{ 633 return new ArmISA::TableWalker(this); 634} 635 |