* Allocates a contiguous set of physical pages of the given size "npages" * from existing or newly created reservations. All of the physical pages * must be at or above the given physical address "low" and below the given * physical address "high". The given value "alignment" determines the * alignment of the first physical page in the set. If the given value * "boundary" is non-zero, then
| 623 | * The object must be locked. |
| 624 | */ |
| 625 | vm_page_t |
| 626 | vm_reserv_alloc_contig(vm_object_t object, vm_pindex_t pindex, int domain, |
| 627 | int req, vm_page_t mpred, u_long npages, vm_paddr_t low, vm_paddr_t high, |
| 628 | u_long alignment, vm_paddr_t boundary) |
| 629 | { |
| 630 | struct vm_domain *vmd; |
| 631 | vm_paddr_t pa, size; |
| 632 | vm_page_t m, m_ret, msucc; |
| 633 | vm_pindex_t first, leftcap, rightcap; |
| 634 | vm_reserv_t rv; |
| 635 | u_long allocpages, maxpages, minpages; |
| 636 | int i, index, n; |
| 637 | |
| 638 | VM_OBJECT_ASSERT_WLOCKED(object); |
| 639 | KASSERT(npages != 0, ("vm_reserv_alloc_contig: npages is 0")); |
| 640 | |
| 641 | /* |
| 642 | * Is a reservation fundamentally impossible? |
| 643 | */ |
| 644 | if (pindex < VM_RESERV_INDEX(object, pindex) || |
| 645 | pindex + npages > object->size) |
| 646 | return (NULL); |
| 647 | |
| 648 | /* |
| 649 | * All reservations of a particular size have the same alignment. |
| 650 | * Assuming that the first page is allocated from a reservation, the |
| 651 | * least significant bits of its physical address can be determined |
| 652 | * from its offset from the beginning of the reservation and the size |
| 653 | * of the reservation. |
| 654 | * |
| 655 | * Could the specified index within a reservation of the smallest |
| 656 | * possible size satisfy the alignment and boundary requirements? |
| 657 | */ |
| 658 | pa = VM_RESERV_INDEX(object, pindex) << PAGE_SHIFT; |
| 659 | if ((pa & (alignment - 1)) != 0) |
| 660 | return (NULL); |
| 661 | size = npages << PAGE_SHIFT; |
| 662 | if (((pa ^ (pa + size - 1)) & ~(boundary - 1)) != 0) |
| 663 | return (NULL); |
| 664 | |
| 665 | /* |
| 666 | * Look for an existing reservation. |
| 667 | */ |
| 668 | rv = vm_reserv_from_object(object, pindex, mpred, &msucc); |
| 669 | if (rv != NULL) { |
| 670 | KASSERT(object != kernel_object || rv->domain == domain, |
| 671 | ("vm_reserv_alloc_contig: domain mismatch")); |
| 672 | index = VM_RESERV_INDEX(object, pindex); |
| 673 | /* Does the allocation fit within the reservation? */ |
| 674 | if (index + npages > VM_LEVEL_0_NPAGES) |
| 675 | return (NULL); |
| 676 | domain = rv->domain; |
| 677 | vmd = VM_DOMAIN(domain); |
| 678 | vm_reserv_lock(rv); |
| 679 | /* Handle reclaim race. */ |
| 680 | if (rv->object != object) |
| 681 | goto out; |
| 682 | m = &rv->pages[index]; |
no test coverage detected