* pmap_protect_l2: do the things to protect a 2MB page in a pmap */
| 3234 | * pmap_protect_l2: do the things to protect a 2MB page in a pmap |
| 3235 | */ |
| 3236 | static void |
| 3237 | pmap_protect_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, pt_entry_t mask, |
| 3238 | pt_entry_t nbits) |
| 3239 | { |
| 3240 | pd_entry_t old_l2; |
| 3241 | vm_page_t m, mt; |
| 3242 | |
| 3243 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 3244 | PMAP_ASSERT_STAGE1(pmap); |
| 3245 | KASSERT((sva & L2_OFFSET) == 0, |
| 3246 | ("pmap_protect_l2: sva is not 2mpage aligned")); |
| 3247 | old_l2 = pmap_load(l2); |
| 3248 | KASSERT((old_l2 & ATTR_DESCR_MASK) == L2_BLOCK, |
| 3249 | ("pmap_protect_l2: L2e %lx is not a block mapping", old_l2)); |
| 3250 | |
| 3251 | /* |
| 3252 | * Return if the L2 entry already has the desired access restrictions |
| 3253 | * in place. |
| 3254 | */ |
| 3255 | retry: |
| 3256 | if ((old_l2 & mask) == nbits) |
| 3257 | return; |
| 3258 | |
| 3259 | /* |
| 3260 | * When a dirty read/write superpage mapping is write protected, |
| 3261 | * update the dirty field of each of the superpage's constituent 4KB |
| 3262 | * pages. |
| 3263 | */ |
| 3264 | if ((old_l2 & ATTR_SW_MANAGED) != 0 && |
| 3265 | (nbits & ATTR_S1_AP(ATTR_S1_AP_RO)) != 0 && |
| 3266 | pmap_pte_dirty(pmap, old_l2)) { |
| 3267 | m = PHYS_TO_VM_PAGE(old_l2 & ~ATTR_MASK); |
| 3268 | for (mt = m; mt < &m[L2_SIZE / PAGE_SIZE]; mt++) |
| 3269 | vm_page_dirty(mt); |
| 3270 | } |
| 3271 | |
| 3272 | if (!atomic_fcmpset_64(l2, &old_l2, (old_l2 & ~mask) | nbits)) |
| 3273 | goto retry; |
| 3274 | |
| 3275 | /* |
| 3276 | * Since a promotion must break the 4KB page mappings before making |
| 3277 | * the 2MB page mapping, a pmap_invalidate_page() suffices. |
| 3278 | */ |
| 3279 | pmap_invalidate_page(pmap, sva); |
| 3280 | } |
| 3281 | |
| 3282 | /* |
| 3283 | * Set the physical protection on the |
no test coverage detected