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