* Set the physical protection on the * specified range of this map as requested. */
| 3284 | * specified range of this map as requested. |
| 3285 | */ |
| 3286 | void |
| 3287 | pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) |
| 3288 | { |
| 3289 | vm_offset_t va, va_next; |
| 3290 | pd_entry_t *l0, *l1, *l2; |
| 3291 | pt_entry_t *l3p, l3, mask, nbits; |
| 3292 | |
| 3293 | PMAP_ASSERT_STAGE1(pmap); |
| 3294 | KASSERT((prot & ~VM_PROT_ALL) == 0, ("invalid prot %x", prot)); |
| 3295 | if (prot == VM_PROT_NONE) { |
| 3296 | pmap_remove(pmap, sva, eva); |
| 3297 | return; |
| 3298 | } |
| 3299 | |
| 3300 | mask = nbits = 0; |
| 3301 | if ((prot & VM_PROT_WRITE) == 0) { |
| 3302 | mask |= ATTR_S1_AP_RW_BIT | ATTR_SW_DBM; |
| 3303 | nbits |= ATTR_S1_AP(ATTR_S1_AP_RO); |
| 3304 | } |
| 3305 | if ((prot & VM_PROT_EXECUTE) == 0) { |
| 3306 | mask |= ATTR_S1_XN; |
| 3307 | nbits |= ATTR_S1_XN; |
| 3308 | } |
| 3309 | if (mask == 0) |
| 3310 | return; |
| 3311 | |
| 3312 | PMAP_LOCK(pmap); |
| 3313 | for (; sva < eva; sva = va_next) { |
| 3314 | l0 = pmap_l0(pmap, sva); |
| 3315 | if (pmap_load(l0) == 0) { |
| 3316 | va_next = (sva + L0_SIZE) & ~L0_OFFSET; |
| 3317 | if (va_next < sva) |
| 3318 | va_next = eva; |
| 3319 | continue; |
| 3320 | } |
| 3321 | |
| 3322 | va_next = (sva + L1_SIZE) & ~L1_OFFSET; |
| 3323 | if (va_next < sva) |
| 3324 | va_next = eva; |
| 3325 | l1 = pmap_l0_to_l1(l0, sva); |
| 3326 | if (pmap_load(l1) == 0) |
| 3327 | continue; |
| 3328 | if ((pmap_load(l1) & ATTR_DESCR_MASK) == L1_BLOCK) { |
| 3329 | KASSERT(va_next <= eva, |
| 3330 | ("partial update of non-transparent 1G page " |
| 3331 | "l1 %#lx sva %#lx eva %#lx va_next %#lx", |
| 3332 | pmap_load(l1), sva, eva, va_next)); |
| 3333 | MPASS((pmap_load(l1) & ATTR_SW_MANAGED) == 0); |
| 3334 | if ((pmap_load(l1) & mask) != nbits) { |
| 3335 | pmap_store(l1, (pmap_load(l1) & ~mask) | nbits); |
| 3336 | pmap_invalidate_page(pmap, sva); |
| 3337 | } |
| 3338 | continue; |
| 3339 | } |
| 3340 | |
| 3341 | va_next = (sva + L2_SIZE) & ~L2_OFFSET; |
| 3342 | if (va_next < sva) |
| 3343 | va_next = eva; |
nothing calls this directly
no test coverage detected