* Remove the given range of addresses from the specified map. * * It is assumed that the start and end are properly * rounded to the page size. */
| 4159 | * rounded to the page size. |
| 4160 | */ |
| 4161 | void |
| 4162 | pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) |
| 4163 | { |
| 4164 | vm_offset_t nextva; |
| 4165 | pt1_entry_t *pte1p, pte1; |
| 4166 | pt2_entry_t *pte2p, pte2; |
| 4167 | struct spglist free; |
| 4168 | |
| 4169 | /* |
| 4170 | * Perform an unsynchronized read. This is, however, safe. |
| 4171 | */ |
| 4172 | if (pmap->pm_stats.resident_count == 0) |
| 4173 | return; |
| 4174 | |
| 4175 | SLIST_INIT(&free); |
| 4176 | |
| 4177 | rw_wlock(&pvh_global_lock); |
| 4178 | sched_pin(); |
| 4179 | PMAP_LOCK(pmap); |
| 4180 | |
| 4181 | /* |
| 4182 | * Special handling of removing one page. A very common |
| 4183 | * operation and easy to short circuit some code. |
| 4184 | */ |
| 4185 | if (sva + PAGE_SIZE == eva) { |
| 4186 | pte1 = pte1_load(pmap_pte1(pmap, sva)); |
| 4187 | if (pte1_is_link(pte1)) { |
| 4188 | pmap_remove_page(pmap, sva, &free); |
| 4189 | goto out; |
| 4190 | } |
| 4191 | } |
| 4192 | |
| 4193 | for (; sva < eva; sva = nextva) { |
| 4194 | /* |
| 4195 | * Calculate address for next L2 page table. |
| 4196 | */ |
| 4197 | nextva = pte1_trunc(sva + PTE1_SIZE); |
| 4198 | if (nextva < sva) |
| 4199 | nextva = eva; |
| 4200 | if (pmap->pm_stats.resident_count == 0) |
| 4201 | break; |
| 4202 | |
| 4203 | pte1p = pmap_pte1(pmap, sva); |
| 4204 | pte1 = pte1_load(pte1p); |
| 4205 | |
| 4206 | /* |
| 4207 | * Weed out invalid mappings. Note: we assume that the L1 page |
| 4208 | * table is always allocated, and in kernel virtual. |
| 4209 | */ |
| 4210 | if (pte1 == 0) |
| 4211 | continue; |
| 4212 | |
| 4213 | if (pte1_is_section(pte1)) { |
| 4214 | /* |
| 4215 | * Are we removing the entire large page? If not, |
| 4216 | * demote the mapping and fall through. |
| 4217 | */ |
| 4218 | if (sva + PTE1_SIZE == nextva && eva >= nextva) { |
no test coverage detected