* Performs a break-before-make update of a pmap entry. This is needed when * either promoting or demoting pages to ensure the TLB doesn't get into an * inconsistent state. */
| 3437 | * inconsistent state. |
| 3438 | */ |
| 3439 | static void |
| 3440 | pmap_update_entry(pmap_t pmap, pd_entry_t *pte, pd_entry_t newpte, |
| 3441 | vm_offset_t va, vm_size_t size) |
| 3442 | { |
| 3443 | register_t intr; |
| 3444 | |
| 3445 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 3446 | |
| 3447 | /* |
| 3448 | * Ensure we don't get switched out with the page table in an |
| 3449 | * inconsistent state. We also need to ensure no interrupts fire |
| 3450 | * as they may make use of an address we are about to invalidate. |
| 3451 | */ |
| 3452 | intr = intr_disable(); |
| 3453 | |
| 3454 | /* |
| 3455 | * Clear the old mapping's valid bit, but leave the rest of the entry |
| 3456 | * unchanged, so that a lockless, concurrent pmap_kextract() can still |
| 3457 | * lookup the physical address. |
| 3458 | */ |
| 3459 | pmap_clear_bits(pte, ATTR_DESCR_VALID); |
| 3460 | pmap_invalidate_range(pmap, va, va + size); |
| 3461 | |
| 3462 | /* Create the new mapping */ |
| 3463 | pmap_store(pte, newpte); |
| 3464 | dsb(ishst); |
| 3465 | |
| 3466 | intr_restore(intr); |
| 3467 | } |
| 3468 | |
| 3469 | #if VM_NRESERVLEVEL > 0 |
| 3470 | /* |
no test coverage detected