Changes in kernel/arch/ppc32/src/mm/tlb.c [e731b0d:7e752b2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ppc32/src/mm/tlb.c
re731b0d r7e752b2 38 38 #include <interrupt.h> 39 39 #include <mm/as.h> 40 #include <mm/page.h> 40 41 #include <arch.h> 41 42 #include <print.h> … … 44 45 45 46 static unsigned int seed = 10; 46 static unsigned int seed_real __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;47 47 static unsigned int seed_real 48 __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42; 48 49 49 50 /** Try to find PTE for faulting address 50 51 * 51 * Try to find PTE for faulting address. 52 * The as->lock must be held on entry to this function 53 * if lock is true. 54 * 55 * @param as Address space. 56 * @param lock Lock/unlock the address space. 57 * @param badvaddr Faulting virtual address. 58 * @param access Access mode that caused the fault. 59 * @param istate Pointer to interrupted state. 60 * @param pfrc Pointer to variable where as_page_fault() return code 61 * will be stored. 62 * @return PTE on success, NULL otherwise. 63 * 64 */ 65 static pte_t * 66 find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, 52 * @param as Address space. 53 * @param lock Lock/unlock the address space. 54 * @param badvaddr Faulting virtual address. 55 * @param access Access mode that caused the fault. 56 * @param istate Pointer to interrupted state. 57 * @param pfrc Pointer to variable where as_page_fault() return code 58 * will be stored. 59 * 60 * @return PTE on success, NULL otherwise. 61 * 62 */ 63 static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access, 67 64 istate_t *istate, int *pfrc) 68 65 { 66 ASSERT(mutex_locked(&as->lock)); 67 69 68 /* 70 69 * Check if the mapping exists in page tables. 71 */ 70 */ 72 71 pte_t *pte = page_mapping_find(as, badvaddr); 73 72 if ((pte) && (pte->present)) { … … 78 77 return pte; 79 78 } else { 80 int rc;81 82 79 /* 83 80 * Mapping not found in page tables. 84 81 * Resort to higher-level page fault handler. 85 82 */ 86 page_table_unlock(as, lock); 87 switch (rc = as_page_fault(badvaddr, access, istate)) { 83 page_table_unlock(as, true); 84 85 int rc = as_page_fault(badvaddr, access, istate); 86 switch (rc) { 88 87 case AS_PF_OK: 89 88 /* … … 91 90 * The mapping ought to be in place. 92 91 */ 93 page_table_lock(as, lock);92 page_table_lock(as, true); 94 93 pte = page_mapping_find(as, badvaddr); 95 94 ASSERT((pte) && (pte->present)); … … 97 96 return pte; 98 97 case AS_PF_DEFER: 99 page_table_lock(as, lock);98 page_table_lock(as, true); 100 99 *pfrc = rc; 101 100 return NULL; 102 101 case AS_PF_FAULT: 103 page_table_lock(as, lock);102 page_table_lock(as, true); 104 103 *pfrc = rc; 105 104 return NULL; 106 105 default: 107 106 panic("Unexpected rc (%d).", rc); 108 } 109 } 110 } 111 107 } 108 } 109 } 112 110 113 111 static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate) 114 112 { 115 char *symbol; 116 char *sym2; 117 118 symbol = symtab_fmt_name_lookup(istate->pc); 119 sym2 = symtab_fmt_name_lookup(istate->lr); 120 121 fault_if_from_uspace(istate, 122 "PHT Refill Exception on %p.", badvaddr); 123 panic("%p: PHT Refill Exception at %p (%s<-%s).", badvaddr, 124 istate->pc, symbol, sym2); 125 } 126 113 fault_if_from_uspace(istate, "PHT Refill Exception on %p.", 114 (void *) badvaddr); 115 panic_memtrap(istate, PF_ACCESS_UNKNOWN, badvaddr, 116 "PHT Refill Exception."); 117 } 127 118 128 119 static void pht_insert(const uintptr_t vaddr, const pte_t *pte) … … 131 122 uint32_t api = (vaddr >> 22) & 0x3f; 132 123 133 uint32_t vsid; 134 asm volatile ( 135 "mfsrin %0, %1\n" 136 : "=r" (vsid) 137 : "r" (vaddr) 138 ); 139 140 uint32_t sdr1; 141 asm volatile ( 142 "mfsdr1 %0\n" 143 : "=r" (sdr1) 144 ); 124 uint32_t vsid = sr_get(vaddr); 125 uint32_t sdr1 = sdr1_get(); 126 127 // FIXME: compute size of PHT exactly 145 128 phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000); 146 129 … … 217 200 } 218 201 219 220 202 /** Process Instruction/Data Storage Exception 221 203 * … … 224 206 * 225 207 */ 226 void pht_refill(int n, istate_t *istate) 227 { 208 void pht_refill(unsigned int n, istate_t *istate) 209 { 210 as_t *as = (AS == NULL) ? AS_KERNEL : AS; 228 211 uintptr_t badvaddr; 229 pte_t *pte;230 int pfrc;231 as_t *as;232 bool lock;233 234 if (AS == NULL) {235 as = AS_KERNEL;236 lock = false;237 } else {238 as = AS;239 lock = true;240 }241 212 242 213 if (n == VECTOR_DATA_STORAGE) … … 244 215 else 245 216 badvaddr = istate->pc; 246 247 page_table_lock(as, lock); 248 249 pte = find_mapping_and_check(as, lock, badvaddr, 217 218 page_table_lock(as, true); 219 220 int pfrc; 221 pte_t *pte = find_mapping_and_check(as, badvaddr, 250 222 PF_ACCESS_READ /* FIXME */, istate, &pfrc); 223 251 224 if (!pte) { 252 225 switch (pfrc) { … … 259 232 * or copy_to_uspace(). 260 233 */ 261 page_table_unlock(as, lock);234 page_table_unlock(as, true); 262 235 return; 263 236 default: … … 266 239 } 267 240 268 pte->accessed = 1; /* Record access to PTE */ 241 /* Record access to PTE */ 242 pte->accessed = 1; 269 243 pht_insert(badvaddr, pte); 270 244 271 page_table_unlock(as, lock);245 page_table_unlock(as, true); 272 246 return; 273 247 274 248 fail: 275 page_table_unlock(as, lock);249 page_table_unlock(as, true); 276 250 pht_refill_fail(badvaddr, istate); 277 251 } 278 279 252 280 253 /** Process Instruction/Data Storage Exception in Real Mode … … 284 257 * 285 258 */ 286 bool pht_refill_real( int n, istate_t *istate)259 bool pht_refill_real(unsigned int n, istate_t *istate) 287 260 { 288 261 uintptr_t badvaddr; … … 293 266 badvaddr = istate->pc; 294 267 295 uint32_t physmem; 296 asm volatile ( 297 "mfsprg3 %0\n" 298 : "=r" (physmem) 299 ); 268 uint32_t physmem = physmem_top(); 300 269 301 270 if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem))) … … 305 274 uint32_t api = (badvaddr >> 22) & 0x3f; 306 275 307 uint32_t vsid; 308 asm volatile ( 309 "mfsrin %0, %1\n" 310 : "=r" (vsid) 311 : "r" (badvaddr) 312 ); 313 314 uint32_t sdr1; 315 asm volatile ( 316 "mfsdr1 %0\n" 317 : "=r" (sdr1) 318 ); 276 uint32_t vsid = sr_get(badvaddr); 277 uint32_t sdr1 = sdr1_get(); 278 279 // FIXME: compute size of PHT exactly 319 280 phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000); 320 281 … … 398 359 } 399 360 400 401 361 /** Process ITLB/DTLB Miss Exception in Real Mode 402 362 * 403 363 * 404 364 */ 405 void tlb_refill_real(int n, uint32_t tlbmiss, ptehi_t ptehi, ptelo_t ptelo, istate_t *istate) 365 void tlb_refill_real(unsigned int n, uint32_t tlbmiss, ptehi_t ptehi, 366 ptelo_t ptelo, istate_t *istate) 406 367 { 407 368 uint32_t badvaddr = tlbmiss & 0xfffffffc; 408 409 uint32_t physmem; 410 asm volatile ( 411 "mfsprg3 %0\n" 412 : "=r" (physmem) 413 ); 369 uint32_t physmem = physmem_top(); 414 370 415 371 if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem))) … … 422 378 uint32_t index = 0; 423 379 asm volatile ( 424 "mtspr 981, % 0\n"425 "mtspr 982, % 1\n"426 "tlbld % 2\n"427 "tlbli % 2\n"428 : "=r" (index)429 : "r" (ptehi),430 "r" (ptelo)380 "mtspr 981, %[ptehi]\n" 381 "mtspr 982, %[ptelo]\n" 382 "tlbld %[index]\n" 383 "tlbli %[index]\n" 384 : [index] "=r" (index) 385 : [ptehi] "r" (ptehi), 386 [ptelo] "r" (ptelo) 431 387 ); 432 388 } 433 389 434 435 390 void tlb_arch_init(void) 436 391 { … … 438 393 } 439 394 440 441 395 void tlb_invalidate_all(void) 442 396 { 443 397 uint32_t index; 398 444 399 asm volatile ( 445 "li % 0, 0\n"400 "li %[index], 0\n" 446 401 "sync\n" 447 402 448 403 ".rept 64\n" 449 " tlbie %0\n"450 " addi %0, %0, 0x1000\n"404 " tlbie %[index]\n" 405 " addi %[index], %[index], 0x1000\n" 451 406 ".endr\n" 452 407 … … 454 409 "tlbsync\n" 455 410 "sync\n" 456 : "=r" (index)411 : [index] "=r" (index) 457 412 ); 458 413 } 459 414 460 461 415 void tlb_invalidate_asid(asid_t asid) 462 416 { 463 uint32_t sdr1; 464 asm volatile ( 465 "mfsdr1 %0\n" 466 : "=r" (sdr1) 467 ); 417 uint32_t sdr1 = sdr1_get(); 418 419 // FIXME: compute size of PHT exactly 468 420 phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000); 469 421 470 uint32_t i;422 size_t i; 471 423 for (i = 0; i < 8192; i++) { 472 424 if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && … … 474 426 phte[i].v = 0; 475 427 } 428 476 429 tlb_invalidate_all(); 477 430 } 478 479 431 480 432 void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt) … … 484 436 } 485 437 486 487 438 #define PRINT_BAT(name, ureg, lreg) \ 488 439 asm volatile ( \ 489 "mfspr %0," #ureg "\n" \ 490 "mfspr %1," #lreg "\n" \ 491 : "=r" (upper), "=r" (lower) \ 440 "mfspr %[upper], " #ureg "\n" \ 441 "mfspr %[lower], " #lreg "\n" \ 442 : [upper] "=r" (upper), \ 443 [lower] "=r" (lower) \ 492 444 ); \ 445 \ 493 446 mask = (upper & 0x1ffc) >> 2; \ 494 447 if (upper & 3) { \ 495 448 uint32_t tmp = mask; \ 496 449 length = 128; \ 450 \ 497 451 while (tmp) { \ 498 452 if ((tmp & 1) == 0) { \ … … 505 459 } else \ 506 460 length = 0; \ 507 printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \ 508 sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \ 509 lower & 0xffff0000, length, mask, \ 461 \ 462 printf(name ": page=%#0" PRIx32 " frame=%#0" PRIx32 \ 463 " length=%#0" PRIx32 " KB (mask=%#0" PRIx32 ")%s%s\n", \ 464 upper & UINT32_C(0xffff0000), lower & UINT32_C(0xffff0000), \ 465 length, mask, \ 510 466 ((upper >> 1) & 1) ? " supervisor" : "", \ 511 467 (upper & 1) ? " user" : ""); 512 468 513 514 469 void tlb_print(void) 515 470 { … … 517 472 518 473 for (sr = 0; sr < 16; sr++) { 519 uint32_t vsid; 520 asm volatile ( 521 "mfsrin %0, %1\n" 522 : "=r" (vsid) 523 : "r" (sr << 28) 524 ); 525 printf("sr[%02u]: vsid=%.*p (asid=%u)%s%s\n", sr, 526 sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, 474 uint32_t vsid = sr_get(sr << 28); 475 476 printf("sr[%02" PRIu32 "]: vsid=%#0" PRIx32 " (asid=%" PRIu32 ")" 477 "%s%s\n", sr, vsid & UINT32_C(0x00ffffff), 478 (vsid & UINT32_C(0x00ffffff)) >> 4, 527 479 ((vsid >> 30) & 1) ? " supervisor" : "", 528 480 ((vsid >> 29) & 1) ? " user" : "");
Note:
See TracChangeset
for help on using the changeset viewer.