Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_reserv.c
Show First 20 Lines • Show All 327 Lines • ▼ Show 20 Lines | sysctl_vm_reserv_fullpop(SYSCTL_HANDLER_ARGS) | ||||
struct vm_phys_seg *seg; | struct vm_phys_seg *seg; | ||||
vm_reserv_t rv; | vm_reserv_t rv; | ||||
int fullpop, segind; | int fullpop, segind; | ||||
fullpop = 0; | fullpop = 0; | ||||
for (segind = 0; segind < vm_phys_nsegs; segind++) { | for (segind = 0; segind < vm_phys_nsegs; segind++) { | ||||
seg = &vm_phys_segs[segind]; | seg = &vm_phys_segs[segind]; | ||||
paddr = roundup2(seg->start, VM_LEVEL_0_SIZE); | paddr = roundup2(seg->start, VM_LEVEL_0_SIZE); | ||||
#ifdef VM_PHYSSEG_SPARSE | |||||
rv = seg->first_reserv + (paddr >> VM_LEVEL_0_SHIFT) - | |||||
(seg->start >> VM_LEVEL_0_SHIFT); | |||||
#else | |||||
rv = &vm_reserv_array[paddr >> VM_LEVEL_0_SHIFT]; | |||||
#endif | |||||
while (paddr + VM_LEVEL_0_SIZE > paddr && paddr + | while (paddr + VM_LEVEL_0_SIZE > paddr && paddr + | ||||
VM_LEVEL_0_SIZE <= seg->end) { | VM_LEVEL_0_SIZE <= seg->end) { | ||||
rv = &vm_reserv_array[paddr >> VM_LEVEL_0_SHIFT]; | |||||
fullpop += rv->popcnt == VM_LEVEL_0_NPAGES; | fullpop += rv->popcnt == VM_LEVEL_0_NPAGES; | ||||
paddr += VM_LEVEL_0_SIZE; | paddr += VM_LEVEL_0_SIZE; | ||||
rv++; | |||||
} | } | ||||
} | } | ||||
return (sysctl_handle_int(oidp, &fullpop, 0, req)); | return (sysctl_handle_int(oidp, &fullpop, 0, req)); | ||||
} | } | ||||
/* | /* | ||||
* Describes the current state of the partially populated reservation queue. | * Describes the current state of the partially populated reservation queue. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Returns the reservation to which the given page might belong. | * Returns the reservation to which the given page might belong. | ||||
*/ | */ | ||||
static __inline vm_reserv_t | static __inline vm_reserv_t | ||||
vm_reserv_from_page(vm_page_t m) | vm_reserv_from_page(vm_page_t m) | ||||
{ | { | ||||
#ifdef VM_PHYSSEG_SPARSE | |||||
struct vm_phys_seg *seg; | |||||
seg = &vm_phys_segs[m->segind]; | |||||
return (seg->first_reserv + (VM_PAGE_TO_PHYS(m) >> VM_LEVEL_0_SHIFT) - | |||||
(seg->start >> VM_LEVEL_0_SHIFT)); | |||||
#else | |||||
return (&vm_reserv_array[VM_PAGE_TO_PHYS(m) >> VM_LEVEL_0_SHIFT]); | return (&vm_reserv_array[VM_PAGE_TO_PHYS(m) >> VM_LEVEL_0_SHIFT]); | ||||
#endif | |||||
} | } | ||||
/* | /* | ||||
* Returns an existing reservation or NULL and initialized successor pointer. | * Returns an existing reservation or NULL and initialized successor pointer. | ||||
*/ | */ | ||||
static vm_reserv_t | static vm_reserv_t | ||||
vm_reserv_from_object(vm_object_t object, vm_pindex_t pindex, | vm_reserv_from_object(vm_object_t object, vm_pindex_t pindex, | ||||
vm_page_t mpred, vm_page_t *msuccp) | vm_page_t mpred, vm_page_t *msuccp) | ||||
▲ Show 20 Lines • Show All 540 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
void | void | ||||
vm_reserv_init(void) | vm_reserv_init(void) | ||||
{ | { | ||||
vm_paddr_t paddr; | vm_paddr_t paddr; | ||||
struct vm_phys_seg *seg; | struct vm_phys_seg *seg; | ||||
struct vm_reserv *rv; | struct vm_reserv *rv; | ||||
struct vm_reserv_domain *rvd; | struct vm_reserv_domain *rvd; | ||||
#ifdef VM_PHYSSEG_SPARSE | |||||
vm_pindex_t used; | |||||
#endif | |||||
int i, j, segind; | int i, j, segind; | ||||
/* | /* | ||||
* Initialize the reservation array. Specifically, initialize the | * Initialize the reservation array. Specifically, initialize the | ||||
* "pages" field for every element that has an underlying superpage. | * "pages" field for every element that has an underlying superpage. | ||||
*/ | */ | ||||
#ifdef VM_PHYSSEG_SPARSE | |||||
used = 0; | |||||
#endif | |||||
for (segind = 0; segind < vm_phys_nsegs; segind++) { | for (segind = 0; segind < vm_phys_nsegs; segind++) { | ||||
seg = &vm_phys_segs[segind]; | seg = &vm_phys_segs[segind]; | ||||
#ifdef VM_PHYSSEG_SPARSE | |||||
seg->first_reserv = &vm_reserv_array[used]; | |||||
used += howmany(seg->end, VM_LEVEL_0_SIZE) - | |||||
seg->start / VM_LEVEL_0_SIZE; | |||||
#else | |||||
seg->first_reserv = | |||||
&vm_reserv_array[seg->start >> VM_LEVEL_0_SHIFT]; | |||||
#endif | |||||
paddr = roundup2(seg->start, VM_LEVEL_0_SIZE); | paddr = roundup2(seg->start, VM_LEVEL_0_SIZE); | ||||
rv = seg->first_reserv + (paddr >> VM_LEVEL_0_SHIFT) - | |||||
(seg->start >> VM_LEVEL_0_SHIFT); | |||||
while (paddr + VM_LEVEL_0_SIZE > paddr && paddr + | while (paddr + VM_LEVEL_0_SIZE > paddr && paddr + | ||||
VM_LEVEL_0_SIZE <= seg->end) { | VM_LEVEL_0_SIZE <= seg->end) { | ||||
rv = &vm_reserv_array[paddr >> VM_LEVEL_0_SHIFT]; | |||||
rv->pages = PHYS_TO_VM_PAGE(paddr); | rv->pages = PHYS_TO_VM_PAGE(paddr); | ||||
rv->domain = seg->domain; | rv->domain = seg->domain; | ||||
mtx_init(&rv->lock, "vm reserv", NULL, MTX_DEF); | mtx_init(&rv->lock, "vm reserv", NULL, MTX_DEF); | ||||
paddr += VM_LEVEL_0_SIZE; | paddr += VM_LEVEL_0_SIZE; | ||||
rv++; | |||||
} | } | ||||
} | } | ||||
for (i = 0; i < MAXMEMDOM; i++) { | for (i = 0; i < MAXMEMDOM; i++) { | ||||
rvd = &vm_rvd[i]; | rvd = &vm_rvd[i]; | ||||
mtx_init(&rvd->lock, "vm reserv domain", NULL, MTX_DEF); | mtx_init(&rvd->lock, "vm reserv domain", NULL, MTX_DEF); | ||||
TAILQ_INIT(&rvd->partpop); | TAILQ_INIT(&rvd->partpop); | ||||
mtx_init(&rvd->marker.lock, "vm reserv marker", NULL, MTX_DEF); | mtx_init(&rvd->marker.lock, "vm reserv marker", NULL, MTX_DEF); | ||||
▲ Show 20 Lines • Show All 314 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Allocates the virtual and physical memory required by the reservation | * Allocates the virtual and physical memory required by the reservation | ||||
* management system's data structures, in particular, the reservation array. | * management system's data structures, in particular, the reservation array. | ||||
*/ | */ | ||||
vm_paddr_t | vm_paddr_t | ||||
vm_reserv_startup(vm_offset_t *vaddr, vm_paddr_t end) | vm_reserv_startup(vm_offset_t *vaddr, vm_paddr_t end) | ||||
{ | { | ||||
vm_paddr_t new_end, high_water; | vm_paddr_t new_end; | ||||
vm_pindex_t count; | |||||
size_t size; | size_t size; | ||||
int i; | int i; | ||||
high_water = phys_avail[1]; | count = 0; | ||||
for (i = 0; i < vm_phys_nsegs; i++) { | for (i = 0; i < vm_phys_nsegs; i++) { | ||||
if (vm_phys_segs[i].end > high_water) | #ifdef VM_PHYSSEG_SPARSE | ||||
high_water = vm_phys_segs[i].end; | count += howmany(vm_phys_segs[i].end, VM_LEVEL_0_SIZE) - | ||||
vm_phys_segs[i].start / VM_LEVEL_0_SIZE; | |||||
#else | |||||
count = MAX(count, | |||||
howmany(vm_phys_segs[i].end, VM_LEVEL_0_SIZE)); | |||||
#endif | |||||
} | } | ||||
/* Skip the first chunk. It is already accounted for. */ | for (i = 0; phys_avail[i + 1] != 0; i += 2) { | ||||
for (i = 2; phys_avail[i + 1] != 0; i += 2) { | #ifdef VM_PHYSSEG_SPARSE | ||||
if (phys_avail[i + 1] > high_water) | count += howmany(phys_avail[i + 1], VM_LEVEL_0_SIZE) - | ||||
high_water = phys_avail[i + 1]; | phys_avail[i] / VM_LEVEL_0_SIZE; | ||||
#else | |||||
count = MAX(count, | |||||
howmany(phys_avail[i + 1], VM_LEVEL_0_SIZE)); | |||||
#endif | |||||
} | } | ||||
/* | /* | ||||
* Calculate the size (in bytes) of the reservation array. Round up | * Calculate the size (in bytes) of the reservation array. Rounding up | ||||
* from "high_water" because every small page is mapped to an element | * for partial superpages at boundaries, as every small page is mapped | ||||
* in the reservation array based on its physical address. Thus, the | * to an element in the reservation array based on its physical address. | ||||
* number of elements in the reservation array can be greater than the | * Thus, the number of elements in the reservation array can be greater | ||||
* number of superpages. | * than the number of superpages. | ||||
*/ | */ | ||||
size = howmany(high_water, VM_LEVEL_0_SIZE) * sizeof(struct vm_reserv); | size = count * sizeof(struct vm_reserv); | ||||
/* | /* | ||||
* Allocate and map the physical memory for the reservation array. The | * Allocate and map the physical memory for the reservation array. The | ||||
* next available virtual address is returned by reference. | * next available virtual address is returned by reference. | ||||
*/ | */ | ||||
new_end = end - round_page(size); | new_end = end - round_page(size); | ||||
vm_reserv_array = (void *)(uintptr_t)pmap_map(vaddr, new_end, end, | vm_reserv_array = (void *)(uintptr_t)pmap_map(vaddr, new_end, end, | ||||
VM_PROT_READ | VM_PROT_WRITE); | VM_PROT_READ | VM_PROT_WRITE); | ||||
Show All 27 Lines |