Rev 598 | Rev 618 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 598 | Rev 599 | ||
---|---|---|---|
Line 53... | Line 53... | ||
53 | * Initialize TLB. |
53 | * Initialize TLB. |
54 | * Invalidate all entries and mark wired entries. |
54 | * Invalidate all entries and mark wired entries. |
55 | */ |
55 | */ |
56 | void tlb_arch_init(void) |
56 | void tlb_arch_init(void) |
57 | { |
57 | { |
- | 58 | int i; |
|
- | 59 | ||
58 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
60 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
- | 61 | cp0_entry_hi_write(0); |
|
- | 62 | cp0_entry_lo0_write(0); |
|
- | 63 | cp0_entry_lo1_write(0); |
|
59 | 64 | ||
- | 65 | /* Clear and initialize TLB. */ |
|
- | 66 | ||
- | 67 | for (i = 0; i < TLB_ENTRY_COUNT; i++) { |
|
60 | tlb_invalidate_all(); |
68 | cp0_index_write(i); |
- | 69 | tlbwi(); |
|
- | 70 | } |
|
61 | 71 | ||
62 | /* |
72 | /* |
63 | * The kernel is going to make use of some wired |
73 | * The kernel is going to make use of some wired |
64 | * entries (e.g. mapping kernel stacks in kseg3). |
74 | * entries (e.g. mapping kernel stacks in kseg3). |
65 | */ |
75 | */ |
Line 293... | Line 303... | ||
293 | if (s) |
303 | if (s) |
294 | symbol = s; |
304 | symbol = s; |
295 | panic("%X: TLB Modified Exception at %X(%s)\n", cp0_badvaddr_read(), pstate->epc, symbol); |
305 | panic("%X: TLB Modified Exception at %X(%s)\n", cp0_badvaddr_read(), pstate->epc, symbol); |
296 | } |
306 | } |
297 | 307 | ||
298 | /** Invalidate TLB entries with specified ASID |
- | |
299 | * |
- | |
300 | * Invalidate TLB entries with specified ASID. |
- | |
301 | * |
- | |
302 | * @param asid ASID. |
- | |
303 | */ |
- | |
304 | void tlb_invalidate(asid_t asid) |
- | |
305 | { |
- | |
306 | entry_hi_t hi; |
- | |
307 | ipl_t ipl; |
- | |
308 | int i; |
- | |
309 | - | ||
310 | ASSERT(asid != ASID_INVALID); |
- | |
311 | - | ||
312 | ipl = interrupts_disable(); |
- | |
313 | - | ||
314 | for (i = 0; i < TLB_ENTRY_COUNT; i++) { |
- | |
315 | cp0_index_write(i); |
- | |
316 | tlbr(); |
- | |
317 | - | ||
318 | hi.value = cp0_entry_hi_read(); |
- | |
319 | if (hi.asid == asid) { |
- | |
320 | cp0_pagemask_write(TLB_PAGE_MASK_16K); |
- | |
321 | cp0_entry_hi_write(0); |
- | |
322 | cp0_entry_lo0_write(0); |
- | |
323 | cp0_entry_lo1_write(0); |
- | |
324 | tlbwi(); |
- | |
325 | } |
- | |
326 | } |
- | |
327 | - | ||
328 | interrupts_restore(ipl); |
- | |
329 | } |
- | |
330 | - | ||
331 | /** Try to find PTE for faulting address |
308 | /** Try to find PTE for faulting address |
332 | * |
309 | * |
333 | * Try to find PTE for faulting address. |
310 | * Try to find PTE for faulting address. |
334 | * The VM->lock must be held on entry to this function. |
311 | * The VM->lock must be held on entry to this function. |
335 | * |
312 | * |
Line 412... | Line 389... | ||
412 | } |
389 | } |
413 | 390 | ||
414 | /** Invalidate all TLB entries. */ |
391 | /** Invalidate all TLB entries. */ |
415 | void tlb_invalidate_all(void) |
392 | void tlb_invalidate_all(void) |
416 | { |
393 | { |
- | 394 | ipl_t ipl; |
|
- | 395 | entry_lo_t lo0, lo1; |
|
417 | int i; |
396 | int i; |
418 | 397 | ||
419 | cp0_entry_hi_write(0); |
- | |
420 | cp0_entry_lo0_write(0); |
- | |
421 | cp0_entry_lo1_write(0); |
398 | ipl = interrupts_disable(); |
422 | 399 | ||
423 | for (i = 0; i < TLB_ENTRY_COUNT; i++) { |
400 | for (i = 0; i < TLB_ENTRY_COUNT; i++) { |
424 | cp0_index_write(i); |
401 | cp0_index_write(i); |
- | 402 | tlbr(); |
|
- | 403 | ||
- | 404 | lo0.value = cp0_entry_lo0_read(); |
|
- | 405 | lo1.value = cp0_entry_lo1_read(); |
|
- | 406 | ||
- | 407 | lo0.v = 0; |
|
- | 408 | lo1.v = 0; |
|
- | 409 | ||
- | 410 | cp0_entry_lo0_write(lo0.value); |
|
- | 411 | cp0_entry_lo1_write(lo1.value); |
|
- | 412 | ||
425 | tlbwi(); |
413 | tlbwi(); |
426 | } |
414 | } |
- | 415 | ||
- | 416 | interrupts_restore(ipl); |
|
427 | } |
417 | } |
428 | 418 | ||
429 | /** Invalidate all TLB entries belonging to specified address space. |
419 | /** Invalidate all TLB entries belonging to specified address space. |
430 | * |
420 | * |
431 | * @param asid Address space identifier. |
421 | * @param asid Address space identifier. |
432 | */ |
422 | */ |
433 | void tlb_invalidate_asid(asid_t asid) |
423 | void tlb_invalidate_asid(asid_t asid) |
434 | { |
424 | { |
- | 425 | ipl_t ipl; |
|
- | 426 | entry_lo_t lo0, lo1; |
|
435 | entry_hi_t hi; |
427 | entry_hi_t hi; |
436 | int i; |
428 | int i; |
437 | 429 | ||
- | 430 | ASSERT(asid != ASID_INVALID); |
|
- | 431 | ||
- | 432 | ipl = interrupts_disable(); |
|
- | 433 | ||
438 | for (i = 0; i < TLB_ENTRY_COUNT; i++) { |
434 | for (i = 0; i < TLB_ENTRY_COUNT; i++) { |
439 | cp0_index_write(i); |
435 | cp0_index_write(i); |
440 | tlbr(); |
436 | tlbr(); |
441 | 437 | ||
- | 438 | hi.value = cp0_entry_hi_read(); |
|
- | 439 | ||
442 | if (hi.asid == asid) { |
440 | if (hi.asid == asid) { |
- | 441 | lo0.value = cp0_entry_lo0_read(); |
|
- | 442 | lo1.value = cp0_entry_lo1_read(); |
|
- | 443 | ||
- | 444 | lo0.v = 0; |
|
- | 445 | lo1.v = 0; |
|
- | 446 | ||
443 | cp0_entry_lo0_write(0); |
447 | cp0_entry_lo0_write(lo0.value); |
444 | cp0_entry_lo1_write(0); |
448 | cp0_entry_lo1_write(lo1.value); |
- | 449 | ||
445 | tlbwi(); |
450 | tlbwi(); |
446 | } |
451 | } |
447 | } |
452 | } |
448 | 453 | ||
- | 454 | interrupts_restore(ipl); |
|
449 | } |
455 | } |
450 | 456 | ||
451 | /** Invalidate TLB entry for specified page belonging to specified address space. |
457 | /** Invalidate TLB entry for specified page belonging to specified address space. |
452 | * |
458 | * |
453 | * @param asid Address space identifier. |
459 | * @param asid Address space identifier. |
454 | * @param page Page whose TLB entry is to be invalidated. |
460 | * @param page Page whose TLB entry is to be invalidated. |
455 | */ |
461 | */ |
456 | void tlb_invalidate_page(asid_t asid, __address page) |
462 | void tlb_invalidate_page(asid_t asid, __address page) |
457 | { |
463 | { |
- | 464 | ipl_t ipl; |
|
- | 465 | entry_lo_t lo0, lo1; |
|
458 | entry_hi_t hi; |
466 | entry_hi_t hi; |
459 | tlb_index_t index; |
467 | tlb_index_t index; |
- | 468 | ||
- | 469 | ASSERT(asid != ASID_INVALID); |
|
- | 470 | ||
460 | int i; |
471 | ipl = interrupts_disable(); |
461 | 472 | ||
462 | hi.value = 0; |
473 | hi.value = 0; |
463 | prepare_entry_hi(&hi, asid, page); |
474 | prepare_entry_hi(&hi, asid, page); |
- | 475 | cp0_entry_hi_write(hi.value); |
|
464 | 476 | ||
465 | tlbp(); |
477 | tlbp(); |
466 | index.value = cp0_index_read(); |
478 | index.value = cp0_index_read(); |
467 | 479 | ||
468 | if (!index.p) { |
480 | if (!index.p) { |
469 | /* Entry was found, index register contains valid index. */ |
481 | /* Entry was found, index register contains valid index. */ |
- | 482 | tlbr(); |
|
- | 483 | ||
- | 484 | lo0.value = cp0_entry_lo0_read(); |
|
- | 485 | lo1.value = cp0_entry_lo1_read(); |
|
- | 486 | ||
- | 487 | lo0.v = 0; |
|
- | 488 | lo1.v = 0; |
|
- | 489 | ||
470 | cp0_entry_lo0_write(0); |
490 | cp0_entry_lo0_write(lo0.value); |
471 | cp0_entry_lo1_write(0); |
491 | cp0_entry_lo1_write(lo1.value); |
- | 492 | ||
472 | tlbwi(); |
493 | tlbwi(); |
473 | } |
494 | } |
- | 495 | ||
- | 496 | interrupts_restore(ipl); |
|
474 | } |
497 | } |