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