table_walker.cc (7406:ddc26bd4ea7d) | table_walker.cc (7436:b578349f9371) |
---|---|
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 --- 82 unchanged lines hidden (view full) --- 91 92 tc = _tc; 93 transState = _trans; 94 req = _req; 95 fault = NoFault; 96 contextId = _cid; 97 timing = _timing; 98 | 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 --- 82 unchanged lines hidden (view full) --- 91 92 tc = _tc; 93 transState = _trans; 94 req = _req; 95 fault = NoFault; 96 contextId = _cid; 97 timing = _timing; 98 |
99 // XXX These should be cached or grabbed from cached copies in 100 // the TLB, all these miscreg reads are expensive | 99 /** @todo These should be cached or grabbed from cached copies in 100 the TLB, all these miscreg reads are expensive */ |
101 vaddr = req->getVaddr() & ~PcModeMask; 102 sctlr = tc->readMiscReg(MISCREG_SCTLR); 103 cpsr = tc->readMiscReg(MISCREG_CPSR); 104 N = tc->readMiscReg(MISCREG_TTBCR); 105 Addr ttbr = 0; 106 107 isFetch = (mode == TLB::Execute); 108 isWrite = (mode == TLB::Write); --- 35 unchanged lines hidden (view full) --- 144 NULL, (uint8_t*)&l1Desc.data, (Tick)0); 145 doL1Descriptor(); 146 } 147 148 return fault; 149} 150 151void | 101 vaddr = req->getVaddr() & ~PcModeMask; 102 sctlr = tc->readMiscReg(MISCREG_SCTLR); 103 cpsr = tc->readMiscReg(MISCREG_CPSR); 104 N = tc->readMiscReg(MISCREG_TTBCR); 105 Addr ttbr = 0; 106 107 isFetch = (mode == TLB::Execute); 108 isWrite = (mode == TLB::Write); --- 35 unchanged lines hidden (view full) --- 144 NULL, (uint8_t*)&l1Desc.data, (Tick)0); 145 doL1Descriptor(); 146 } 147 148 return fault; 149} 150 151void |
152TableWalker::memAttrs(TlbEntry &te, uint8_t texcb) | 152TableWalker::memAttrs(TlbEntry &te, uint8_t texcb, bool s) |
153{ | 153{ |
154 | 154 DPRINTF(TLBVerbose, "memAttrs texcb:%d s:%d\n", texcb, s); 155 te.shareable = false; // default value 156 bool outer_shareable = false; |
155 if (sctlr.tre == 0) { 156 switch(texcb) { | 157 if (sctlr.tre == 0) { 158 switch(texcb) { |
157 case 0: 158 case 1: 159 case 4: 160 case 8: | 159 case 0: // Stongly-ordered |
161 te.nonCacheable = true; | 160 te.nonCacheable = true; |
161 te.mtype = TlbEntry::StronglyOrdered; 162 te.shareable = true; 163 te.innerAttrs = 1; 164 te.outerAttrs = 0; |
|
162 break; | 165 break; |
163 case 16: | 166 case 1: // Shareable Device 167 te.nonCacheable = true; 168 te.mtype = TlbEntry::Device; 169 te.shareable = true; 170 te.innerAttrs = 3; 171 te.outerAttrs = 0; 172 break; 173 case 2: // Outer and Inner Write-Through, no Write-Allocate 174 te.mtype = TlbEntry::Normal; 175 te.shareable = s; 176 te.innerAttrs = 6; 177 te.outerAttrs = bits(texcb, 1, 0); 178 break; 179 case 3: // Outer and Inner Write-Back, no Write-Allocate 180 te.mtype = TlbEntry::Normal; 181 te.shareable = s; 182 te.innerAttrs = 7; 183 te.outerAttrs = bits(texcb, 1, 0); 184 break; 185 case 4: // Outer and Inner Non-cacheable 186 te.nonCacheable = true; 187 te.mtype = TlbEntry::Normal; 188 te.shareable = s; 189 te.innerAttrs = 0; 190 te.outerAttrs = bits(texcb, 1, 0); 191 break; 192 case 5: // Reserved 193 break; 194 case 6: // Implementation Defined 195 break; 196 case 7: // Outer and Inner Write-Back, Write-Allocate 197 te.mtype = TlbEntry::Normal; 198 te.shareable = s; 199 te.innerAttrs = 5; 200 te.outerAttrs = 1; 201 break; 202 case 8: // Non-shareable Device 203 te.nonCacheable = true; 204 te.mtype = TlbEntry::Device; 205 te.shareable = false; 206 te.innerAttrs = 3; 207 te.outerAttrs = 0; 208 break; 209 case 9 ... 15: // Reserved 210 break; 211 case 16 ... 31: // Cacheable Memory 212 te.mtype = TlbEntry::Normal; 213 te.shareable = s; |
164 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 165 te.nonCacheable = true; | 214 if (bits(texcb, 1,0) == 0 || bits(texcb, 3,2) == 0) 215 te.nonCacheable = true; |
216 te.innerAttrs = bits(texcb, 1, 0); 217 te.outerAttrs = bits(texcb, 3, 2); |
|
166 break; | 218 break; |
219 default: 220 panic("More than 32 states for 5 bits?\n"); |
|
167 } 168 } else { 169 PRRR prrr = tc->readMiscReg(MISCREG_PRRR); 170 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); | 221 } 222 } else { 223 PRRR prrr = tc->readMiscReg(MISCREG_PRRR); 224 NMRR nmrr = tc->readMiscReg(MISCREG_NMRR); |
225 DPRINTF(TLBVerbose, "memAttrs PRRR:%08x NMRR:%08x\n", prrr, nmrr); 226 uint8_t curr_tr, curr_ir, curr_or; |
|
171 switch(bits(texcb, 2,0)) { 172 case 0: | 227 switch(bits(texcb, 2,0)) { 228 case 0: |
173 if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2) 174 te.nonCacheable = true; | 229 curr_tr = prrr.tr0; 230 curr_ir = nmrr.ir0; 231 curr_or = nmrr.or0; 232 outer_shareable = (prrr.nos0 == 0); |
175 break; 176 case 1: | 233 break; 234 case 1: |
177 if (nmrr.ir1 == 0 || nmrr.or1 == 0 || prrr.tr1 != 0x2) 178 te.nonCacheable = true; | 235 curr_tr = prrr.tr1; 236 curr_ir = nmrr.ir1; 237 curr_or = nmrr.or1; 238 outer_shareable = (prrr.nos1 == 0); |
179 break; 180 case 2: | 239 break; 240 case 2: |
181 if (nmrr.ir2 == 0 || nmrr.or2 == 0 || prrr.tr2 != 0x2) 182 te.nonCacheable = true; | 241 curr_tr = prrr.tr2; 242 curr_ir = nmrr.ir2; 243 curr_or = nmrr.or2; 244 outer_shareable = (prrr.nos2 == 0); |
183 break; 184 case 3: | 245 break; 246 case 3: |
185 if (nmrr.ir3 == 0 || nmrr.or3 == 0 || prrr.tr3 != 0x2) 186 te.nonCacheable = true; | 247 curr_tr = prrr.tr3; 248 curr_ir = nmrr.ir3; 249 curr_or = nmrr.or3; 250 outer_shareable = (prrr.nos3 == 0); |
187 break; 188 case 4: | 251 break; 252 case 4: |
189 if (nmrr.ir4 == 0 || nmrr.or4 == 0 || prrr.tr4 != 0x2) 190 te.nonCacheable = true; | 253 curr_tr = prrr.tr4; 254 curr_ir = nmrr.ir4; 255 curr_or = nmrr.or4; 256 outer_shareable = (prrr.nos4 == 0); |
191 break; 192 case 5: | 257 break; 258 case 5: |
193 if (nmrr.ir5 == 0 || nmrr.or5 == 0 || prrr.tr5 != 0x2) 194 te.nonCacheable = true; | 259 curr_tr = prrr.tr5; 260 curr_ir = nmrr.ir5; 261 curr_or = nmrr.or5; 262 outer_shareable = (prrr.nos5 == 0); |
195 break; 196 case 6: 197 panic("Imp defined type\n"); 198 case 7: | 263 break; 264 case 6: 265 panic("Imp defined type\n"); 266 case 7: |
199 if (nmrr.ir7 == 0 || nmrr.or7 == 0 || prrr.tr7 != 0x2) 200 te.nonCacheable = true; | 267 curr_tr = prrr.tr7; 268 curr_ir = nmrr.ir7; 269 curr_or = nmrr.or7; 270 outer_shareable = (prrr.nos7 == 0); |
201 break; 202 } | 271 break; 272 } |
273 274 switch(curr_tr) { 275 case 0: 276 DPRINTF(TLBVerbose, "StronglyOrdered\n"); 277 te.mtype = TlbEntry::StronglyOrdered; 278 te.nonCacheable = true; 279 te.innerAttrs = 1; 280 te.outerAttrs = 0; 281 te.shareable = true; 282 break; 283 case 1: 284 DPRINTF(TLBVerbose, "Device ds1:%d ds0:%d s:%d\n", 285 prrr.ds1, prrr.ds0, s); 286 te.mtype = TlbEntry::Device; 287 te.nonCacheable = true; 288 te.innerAttrs = 3; 289 te.outerAttrs = 0; 290 if (prrr.ds1 && s) 291 te.shareable = true; 292 if (prrr.ds0 && !s) 293 te.shareable = true; 294 break; 295 case 2: 296 DPRINTF(TLBVerbose, "Normal ns1:%d ns0:%d s:%d\n", 297 prrr.ns1, prrr.ns0, s); 298 te.mtype = TlbEntry::Normal; 299 if (prrr.ns1 && s) 300 te.shareable = true; 301 if (prrr.ns0 && !s) 302 te.shareable = true; 303 //te.shareable = outer_shareable; 304 break; 305 case 3: 306 panic("Reserved type"); 307 } 308 309 if (te.mtype == TlbEntry::Normal){ 310 switch(curr_ir) { 311 case 0: 312 te.nonCacheable = true; 313 te.innerAttrs = 0; 314 break; 315 case 1: 316 te.innerAttrs = 5; 317 break; 318 case 2: 319 te.innerAttrs = 6; 320 break; 321 case 3: 322 te.innerAttrs = 7; 323 break; 324 } 325 326 switch(curr_or) { 327 case 0: 328 te.nonCacheable = true; 329 te.outerAttrs = 0; 330 break; 331 case 1: 332 te.outerAttrs = 1; 333 break; 334 case 2: 335 te.outerAttrs = 2; 336 break; 337 case 3: 338 te.outerAttrs = 3; 339 break; 340 } 341 } |
|
203 } | 342 } |
343 344 /** Formatting for Physical Address Register (PAR) 345 * Only including lower bits (TLB info here) 346 * PAR: 347 * PA [31:12] 348 * Reserved [11] 349 * TLB info [10:1] 350 * NOS [10] (Not Outer Sharable) 351 * NS [9] (Non-Secure) 352 * -- [8] (Implementation Defined) 353 * SH [7] (Sharable) 354 * Inner[6:4](Inner memory attributes) 355 * Outer[3:2](Outer memory attributes) 356 * SS [1] (SuperSection) 357 * F [0] (Fault, Fault Status in [6:1] if faulted) 358 */ 359 te.attributes = ( 360 ((outer_shareable ? 0:1) << 10) | 361 // TODO: NS Bit 362 ((te.shareable ? 1:0) << 7) | 363 (te.innerAttrs << 4) | 364 (te.outerAttrs << 2) 365 // TODO: Supersection bit 366 // TODO: Fault bit 367 ); 368 369 |
|
204} 205 206void 207TableWalker::doL1Descriptor() 208{ 209 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", vaddr, l1Desc.data); 210 TlbEntry te; 211 212 switch (l1Desc.type()) { 213 case L1Descriptor::Ignore: 214 case L1Descriptor::Reserved: 215 tc = NULL; 216 req = NULL; 217 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 218 if (isFetch) 219 fault = new PrefetchAbort(vaddr, ArmFault::Translation0); 220 else | 370} 371 372void 373TableWalker::doL1Descriptor() 374{ 375 DPRINTF(TLB, "L1 descriptor for %#x is %#x\n", vaddr, l1Desc.data); 376 TlbEntry te; 377 378 switch (l1Desc.type()) { 379 case L1Descriptor::Ignore: 380 case L1Descriptor::Reserved: 381 tc = NULL; 382 req = NULL; 383 DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n"); 384 if (isFetch) 385 fault = new PrefetchAbort(vaddr, ArmFault::Translation0); 386 else |
221 fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::Translation0); | 387 fault = new DataAbort(vaddr, NULL, isWrite, 388 ArmFault::Translation0); |
222 return; 223 case L1Descriptor::Section: | 389 return; 390 case L1Descriptor::Section: |
224 if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) 225 panic("Haven't implemented AFE\n"); | 391 if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) { 392 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is 393 * enabled if set, do l1.Desc.setAp0() instead of generating 394 * AccessFlag0 395 */ |
226 | 396 |
397 fault = new DataAbort(vaddr, NULL, isWrite, 398 ArmFault::AccessFlag0); 399 } 400 |
|
227 if (l1Desc.supersection()) { 228 panic("Haven't implemented supersections\n"); 229 } 230 te.N = 20; 231 te.pfn = l1Desc.pfn(); 232 te.size = (1<<te.N) - 1; 233 te.global = !l1Desc.global(); 234 te.valid = true; 235 te.vpn = vaddr >> te.N; 236 te.sNp = true; 237 te.xn = l1Desc.xn(); 238 te.ap = l1Desc.ap(); 239 te.domain = l1Desc.domain(); 240 te.asid = contextId; | 401 if (l1Desc.supersection()) { 402 panic("Haven't implemented supersections\n"); 403 } 404 te.N = 20; 405 te.pfn = l1Desc.pfn(); 406 te.size = (1<<te.N) - 1; 407 te.global = !l1Desc.global(); 408 te.valid = true; 409 te.vpn = vaddr >> te.N; 410 te.sNp = true; 411 te.xn = l1Desc.xn(); 412 te.ap = l1Desc.ap(); 413 te.domain = l1Desc.domain(); 414 te.asid = contextId; |
241 memAttrs(te, l1Desc.texcb()); | 415 memAttrs(te, l1Desc.texcb(), l1Desc.shareable()); |
242 243 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); 244 DPRINTF(TLB, " - N%d pfn:%#x size: %#x global:%d valid: %d\n", 245 te.N, te.pfn, te.size, te.global, te.valid); 246 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d\n", 247 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid); 248 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", 249 l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF ); 250 251 tc = NULL; 252 req = NULL; 253 tlb->insert(vaddr, te); 254 255 return; 256 case L1Descriptor::PageTable: 257 Addr l2desc_addr; 258 l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2); | 416 417 DPRINTF(TLB, "Inserting Section Descriptor into TLB\n"); 418 DPRINTF(TLB, " - N%d pfn:%#x size: %#x global:%d valid: %d\n", 419 te.N, te.pfn, te.size, te.global, te.valid); 420 DPRINTF(TLB, " - vpn:%#x sNp: %d xn:%d ap:%d domain: %d asid:%d\n", 421 te.vpn, te.sNp, te.xn, te.ap, te.domain, te.asid); 422 DPRINTF(TLB, " - domain from l1 desc: %d data: %#x bits:%d\n", 423 l1Desc.domain(), l1Desc.data, (l1Desc.data >> 5) & 0xF ); 424 425 tc = NULL; 426 req = NULL; 427 tlb->insert(vaddr, te); 428 429 return; 430 case L1Descriptor::PageTable: 431 Addr l2desc_addr; 432 l2desc_addr = l1Desc.l2Addr() | (bits(vaddr, 19,12) << 2); |
259 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", l2desc_addr); | 433 DPRINTF(TLB, "L1 descriptor points to page table at: %#x\n", 434 l2desc_addr); |
260 261 // Trickbox address check 262 fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t), 263 isFetch, isWrite, l1Desc.domain(), false); 264 if (fault) { 265 tc = NULL; 266 req = NULL; 267 return; --- 15 unchanged lines hidden (view full) --- 283} 284 285void 286TableWalker::doL2Descriptor() 287{ 288 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data); 289 TlbEntry te; 290 | 435 436 // Trickbox address check 437 fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t), 438 isFetch, isWrite, l1Desc.domain(), false); 439 if (fault) { 440 tc = NULL; 441 req = NULL; 442 return; --- 15 unchanged lines hidden (view full) --- 458} 459 460void 461TableWalker::doL2Descriptor() 462{ 463 DPRINTF(TLB, "L2 descriptor for %#x is %#x\n", vaddr, l2Desc.data); 464 TlbEntry te; 465 |
291 if (sctlr.afe && bits(l1Desc.ap(), 0) == 0) 292 panic("Haven't implemented AFE\n"); 293 | |
294 if (l2Desc.invalid()) { 295 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 296 tc = NULL; 297 req = NULL; 298 if (isFetch) 299 fault = new PrefetchAbort(vaddr, ArmFault::Translation1); 300 else | 466 if (l2Desc.invalid()) { 467 DPRINTF(TLB, "L2 descriptor invalid, causing fault\n"); 468 tc = NULL; 469 req = NULL; 470 if (isFetch) 471 fault = new PrefetchAbort(vaddr, ArmFault::Translation1); 472 else |
301 fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, ArmFault::Translation1); | 473 fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, 474 ArmFault::Translation1); |
302 return; 303 } 304 | 475 return; 476 } 477 |
478 if (sctlr.afe && bits(l2Desc.ap(), 0) == 0) { 479 /** @todo: check sctlr.ha (bit[17]) if Hardware Access Flag is enabled 480 * if set, do l2.Desc.setAp0() instead of generating AccessFlag0 481 */ 482 483 fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::AccessFlag1); 484 } 485 |
|
305 if (l2Desc.large()) { 306 te.N = 16; 307 te.pfn = l2Desc.pfn(); 308 } else { 309 te.N = 12; 310 te.pfn = l2Desc.pfn(); 311 } 312 313 te.valid = true; 314 te.size = (1 << te.N) - 1; 315 te.asid = contextId; 316 te.sNp = false; 317 te.vpn = vaddr >> te.N; 318 te.global = l2Desc.global(); 319 te.xn = l2Desc.xn(); 320 te.ap = l2Desc.ap(); 321 te.domain = l1Desc.domain(); | 486 if (l2Desc.large()) { 487 te.N = 16; 488 te.pfn = l2Desc.pfn(); 489 } else { 490 te.N = 12; 491 te.pfn = l2Desc.pfn(); 492 } 493 494 te.valid = true; 495 te.size = (1 << te.N) - 1; 496 te.asid = contextId; 497 te.sNp = false; 498 te.vpn = vaddr >> te.N; 499 te.global = l2Desc.global(); 500 te.xn = l2Desc.xn(); 501 te.ap = l2Desc.ap(); 502 te.domain = l1Desc.domain(); |
322 memAttrs(te, l2Desc.texcb()); | 503 memAttrs(te, l2Desc.texcb(), l2Desc.shareable()); |
323 324 tc = NULL; 325 req = NULL; 326 tlb->insert(vaddr, te); 327} 328 329ArmISA::TableWalker * 330ArmTableWalkerParams::create() 331{ 332 return new ArmISA::TableWalker(this); 333} 334 | 504 505 tc = NULL; 506 req = NULL; 507 tlb->insert(vaddr, te); 508} 509 510ArmISA::TableWalker * 511ArmTableWalkerParams::create() 512{ 513 return new ArmISA::TableWalker(this); 514} 515 |