Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_reserv.c
Show First 20 Lines • Show All 991 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Searches the partially populated reservation queue for the least recently | * Searches the partially populated reservation queue for the least recently | ||||
* changed reservation with free pages that satisfy the given request for | * changed reservation with free pages that satisfy the given request for | ||||
* contiguous physical memory. If a satisfactory reservation is found, it is | * contiguous physical memory. If a satisfactory reservation is found, it is | ||||
* broken. Returns true if a reservation is broken and false otherwise. | * broken. Returns true if a reservation is broken and false otherwise. | ||||
*/ | */ | ||||
bool | vm_page_t | ||||
vm_reserv_reclaim_contig(int domain, u_long npages, vm_paddr_t low, | vm_reserv_reclaim_contig(int domain, u_long npages, vm_paddr_t low, | ||||
vm_paddr_t high, u_long alignment, vm_paddr_t boundary) | vm_paddr_t high, u_long alignment, vm_paddr_t boundary) | ||||
{ | { | ||||
struct vm_reserv_queue *queue; | struct vm_reserv_queue *queue; | ||||
vm_paddr_t pa, size; | vm_paddr_t pa, size; | ||||
vm_page_t m_ret; | |||||
vm_reserv_t marker, rv, rvn; | vm_reserv_t marker, rv, rvn; | ||||
int hi, lo, posn, ppn_align, ppn_bound; | int hi, lo, posn, ppn_align, ppn_bound; | ||||
KASSERT(npages > 0, ("npages is 0")); | KASSERT(npages > 0, ("npages is 0")); | ||||
KASSERT(powerof2(alignment), ("alignment is not a power of 2")); | KASSERT(powerof2(alignment), ("alignment is not a power of 2")); | ||||
KASSERT(powerof2(boundary), ("boundary is not a power of 2")); | KASSERT(powerof2(boundary), ("boundary is not a power of 2")); | ||||
if (npages > VM_LEVEL_0_NPAGES - 1) | if (npages > VM_LEVEL_0_NPAGES - 1) | ||||
return (false); | return (false); | ||||
size = npages << PAGE_SHIFT; | size = npages << PAGE_SHIFT; | ||||
/* | /* | ||||
* Ensure that a free range starting at a boundary-multiple | * Ensure that a free range starting at a boundary-multiple | ||||
* doesn't include a boundary-multiple within it. Otherwise, | * doesn't include a boundary-multiple within it. Otherwise, | ||||
* no boundary-constrained allocation is possible. | * no boundary-constrained allocation is possible. | ||||
*/ | */ | ||||
if (size > boundary) | if (size > boundary) | ||||
return (false); | return (NULL); | ||||
marker = &vm_rvd[domain].marker; | marker = &vm_rvd[domain].marker; | ||||
queue = &vm_rvd[domain].partpop; | queue = &vm_rvd[domain].partpop; | ||||
/* | /* | ||||
* Compute shifted alignment, boundary values for page-based | * Compute shifted alignment, boundary values for page-based | ||||
* calculations. Constrain to range [1, VM_LEVEL_0_NPAGES] to | * calculations. Constrain to range [1, VM_LEVEL_0_NPAGES] to | ||||
* avoid overflow. | * avoid overflow. | ||||
*/ | */ | ||||
ppn_align = (int)(ulmin(ulmax(PAGE_SIZE, alignment), | ppn_align = (int)(ulmin(ulmax(PAGE_SIZE, alignment), | ||||
Show All 36 Lines | |||||
vm_reserv_domain_unlock(domain); | vm_reserv_domain_unlock(domain); | ||||
lo = (pa >= low) ? 0 : | lo = (pa >= low) ? 0 : | ||||
(int)((low + PAGE_MASK - pa) >> PAGE_SHIFT); | (int)((low + PAGE_MASK - pa) >> PAGE_SHIFT); | ||||
hi = (pa + VM_LEVEL_0_SIZE <= high) ? VM_LEVEL_0_NPAGES : | hi = (pa + VM_LEVEL_0_SIZE <= high) ? VM_LEVEL_0_NPAGES : | ||||
(int)((high - pa) >> PAGE_SHIFT); | (int)((high - pa) >> PAGE_SHIFT); | ||||
posn = vm_reserv_find_contig(rv, (int)npages, lo, hi, | posn = vm_reserv_find_contig(rv, (int)npages, lo, hi, | ||||
ppn_align, ppn_bound); | ppn_align, ppn_bound); | ||||
if (posn >= 0) { | if (posn >= 0) { | ||||
pa = VM_PAGE_TO_PHYS(&rv->pages[posn]); | m_ret = &rv->pages[posn]; | ||||
pa = VM_PAGE_TO_PHYS(m_ret); | |||||
KASSERT((pa & (alignment - 1)) == 0, | KASSERT((pa & (alignment - 1)) == 0, | ||||
("%s: adjusted address does not align to %lx", | ("%s: adjusted address does not align to %lx", | ||||
__func__, alignment)); | __func__, alignment)); | ||||
KASSERT(((pa ^ (pa + size - 1)) & -boundary) == 0, | KASSERT(((pa ^ (pa + size - 1)) & -boundary) == 0, | ||||
("%s: adjusted address spans boundary to %jx", | ("%s: adjusted address spans boundary to %jx", | ||||
__func__, (uintmax_t)boundary)); | __func__, (uintmax_t)boundary)); | ||||
alc: This could all be performed after the reservation is unlocked. | |||||
/* Allocate requested space */ | |||||
rv->popcnt += npages; | |||||
while (npages-- > 0) | |||||
popmap_set(rv->popmap, posn + npages); | |||||
vm_reserv_domain_scan_unlock(domain); | vm_reserv_domain_scan_unlock(domain); | ||||
alcUnsubmitted Done Inline ActionsThis can be done before marking the pages as allocated. alc: This can be done before marking the pages as allocated. | |||||
vm_reserv_reclaim(rv); | vm_reserv_reclaim(rv); | ||||
vm_reserv_unlock(rv); | vm_reserv_unlock(rv); | ||||
return (true); | return (m_ret); | ||||
} | } | ||||
vm_reserv_domain_lock(domain); | vm_reserv_domain_lock(domain); | ||||
rvn = TAILQ_NEXT(rv, partpopq); | rvn = TAILQ_NEXT(rv, partpopq); | ||||
vm_reserv_unlock(rv); | vm_reserv_unlock(rv); | ||||
} | } | ||||
vm_reserv_domain_unlock(domain); | vm_reserv_domain_unlock(domain); | ||||
vm_reserv_domain_scan_unlock(domain); | vm_reserv_domain_scan_unlock(domain); | ||||
return (false); | return (NULL); | ||||
} | } | ||||
/* | /* | ||||
* Transfers the reservation underlying the given page to a new object. | * Transfers the reservation underlying the given page to a new object. | ||||
* | * | ||||
* The object must be locked. | * The object must be locked. | ||||
*/ | */ | ||||
void | void | ||||
▲ Show 20 Lines • Show All 121 Lines • Show Last 20 Lines |
This could all be performed after the reservation is unlocked.