* Unlocks fs.first_object and fs.map on success. */
| 295 | * Unlocks fs.first_object and fs.map on success. |
| 296 | */ |
| 297 | static int |
| 298 | vm_fault_soft_fast(struct faultstate *fs) |
| 299 | { |
| 300 | vm_page_t m, m_map; |
| 301 | #if VM_NRESERVLEVEL > 0 |
| 302 | vm_page_t m_super; |
| 303 | int flags; |
| 304 | #endif |
| 305 | int psind, rv; |
| 306 | vm_offset_t vaddr; |
| 307 | |
| 308 | MPASS(fs->vp == NULL); |
| 309 | vaddr = fs->vaddr; |
| 310 | vm_object_busy(fs->first_object); |
| 311 | m = vm_page_lookup(fs->first_object, fs->first_pindex); |
| 312 | /* A busy page can be mapped for read|execute access. */ |
| 313 | if (m == NULL || ((fs->prot & VM_PROT_WRITE) != 0 && |
| 314 | vm_page_busied(m)) || !vm_page_all_valid(m)) { |
| 315 | rv = KERN_FAILURE; |
| 316 | goto out; |
| 317 | } |
| 318 | m_map = m; |
| 319 | psind = 0; |
| 320 | #if VM_NRESERVLEVEL > 0 |
| 321 | if ((m->flags & PG_FICTITIOUS) == 0 && |
| 322 | (m_super = vm_reserv_to_superpage(m)) != NULL && |
| 323 | rounddown2(vaddr, pagesizes[m_super->psind]) >= fs->entry->start && |
| 324 | roundup2(vaddr + 1, pagesizes[m_super->psind]) <= fs->entry->end && |
| 325 | (vaddr & (pagesizes[m_super->psind] - 1)) == (VM_PAGE_TO_PHYS(m) & |
| 326 | (pagesizes[m_super->psind] - 1)) && !fs->wired && |
| 327 | pmap_ps_enabled(fs->map->pmap)) { |
| 328 | flags = PS_ALL_VALID; |
| 329 | if ((fs->prot & VM_PROT_WRITE) != 0) { |
| 330 | /* |
| 331 | * Create a superpage mapping allowing write access |
| 332 | * only if none of the constituent pages are busy and |
| 333 | * all of them are already dirty (except possibly for |
| 334 | * the page that was faulted on). |
| 335 | */ |
| 336 | flags |= PS_NONE_BUSY; |
| 337 | if ((fs->first_object->flags & OBJ_UNMANAGED) == 0) |
| 338 | flags |= PS_ALL_DIRTY; |
| 339 | } |
| 340 | if (vm_page_ps_test(m_super, flags, m)) { |
| 341 | m_map = m_super; |
| 342 | psind = m_super->psind; |
| 343 | vaddr = rounddown2(vaddr, pagesizes[psind]); |
| 344 | /* Preset the modified bit for dirty superpages. */ |
| 345 | if ((flags & PS_ALL_DIRTY) != 0) |
| 346 | fs->fault_type |= VM_PROT_WRITE; |
| 347 | } |
| 348 | } |
| 349 | #endif |
| 350 | rv = pmap_enter(fs->map->pmap, vaddr, m_map, fs->prot, fs->fault_type | |
| 351 | PMAP_ENTER_NOSLEEP | (fs->wired ? PMAP_ENTER_WIRED : 0), psind); |
| 352 | if (rv != KERN_SUCCESS) |
| 353 | goto out; |
| 354 | if (fs->m_hold != NULL) { |
no test coverage detected