version 1.4.6.5, 2016/12/05 10:55:30 |
version 1.4.6.6, 2017/02/05 13:41:01 |
Line 112 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 112 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/atomic.h> |
#include <sys/atomic.h> |
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
|
#include <uvm/uvm_physseg.h> |
|
|
#if defined(MULTIPROCESSOR) && defined(PMAP_VIRTUAL_CACHE_ALIASES) \ |
#if defined(MULTIPROCESSOR) && defined(PMAP_VIRTUAL_CACHE_ALIASES) \ |
&& !defined(PMAP_NO_PV_UNCACHED) |
&& !defined(PMAP_NO_PV_UNCACHED) |
Line 452 pmap_steal_memory(vsize_t size, vaddr_t |
|
Line 453 pmap_steal_memory(vsize_t size, vaddr_t |
|
size_t npgs; |
size_t npgs; |
paddr_t pa; |
paddr_t pa; |
vaddr_t va; |
vaddr_t va; |
struct vm_physseg *maybe_seg = NULL; |
|
u_int maybe_bank = vm_nphysseg; |
uvm_physseg_t maybe_bank = UVM_PHYSSEG_TYPE_INVALID; |
|
|
size = round_page(size); |
size = round_page(size); |
npgs = atop(size); |
npgs = atop(size); |
|
|
aprint_debug("%s: need %zu pages\n", __func__, npgs); |
aprint_debug("%s: need %zu pages\n", __func__, npgs); |
|
|
for (u_int bank = 0; bank < vm_nphysseg; bank++) { |
for (uvm_physseg_t bank = uvm_physseg_get_first(); |
struct vm_physseg * const seg = VM_PHYSMEM_PTR(bank); |
uvm_physseg_valid_p(bank); |
|
bank = uvm_physseg_get_next(bank)) { |
|
|
if (uvm.page_init_done == true) |
if (uvm.page_init_done == true) |
panic("pmap_steal_memory: called _after_ bootstrap"); |
panic("pmap_steal_memory: called _after_ bootstrap"); |
|
|
aprint_debug("%s: seg %u: %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR"\n", |
aprint_debug("%s: seg %"PRIxPHYSSEG": %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR" %#"PRIxPADDR"\n", |
__func__, bank, |
__func__, bank, |
seg->avail_start, seg->start, |
uvm_physseg_get_avail_start(bank), uvm_physseg_get_start(bank), |
seg->avail_end, seg->end); |
uvm_physseg_get_avail_end(bank), uvm_physseg_get_end(bank)); |
|
|
if (seg->avail_start != seg->start |
if (uvm_physseg_get_avail_start(bank) != uvm_physseg_get_start(bank) |
|| seg->avail_start >= seg->avail_end) { |
|| uvm_physseg_get_avail_start(bank) >= uvm_physseg_get_avail_end(bank)) { |
aprint_debug("%s: seg %u: bad start\n", __func__, bank); |
aprint_debug("%s: seg %"PRIxPHYSSEG": bad start\n", __func__, bank); |
continue; |
continue; |
} |
} |
|
|
if (seg->avail_end - seg->avail_start < npgs) { |
if (uvm_physseg_get_avail_end(bank) - uvm_physseg_get_avail_start(bank) < npgs) { |
aprint_debug("%s: seg %u: too small for %zu pages\n", |
aprint_debug("%s: seg %"PRIxPHYSSEG": too small for %zu pages\n", |
__func__, bank, npgs); |
__func__, bank, npgs); |
continue; |
continue; |
} |
} |
|
|
if (!pmap_md_ok_to_steal_p(seg, npgs)) { |
if (!pmap_md_ok_to_steal_p(bank, npgs)) { |
continue; |
continue; |
} |
} |
|
|
Line 490 pmap_steal_memory(vsize_t size, vaddr_t |
|
Line 493 pmap_steal_memory(vsize_t size, vaddr_t |
|
* Always try to allocate from the segment with the least |
* Always try to allocate from the segment with the least |
* amount of space left. |
* amount of space left. |
*/ |
*/ |
#define VM_PHYSMEM_SPACE(s) ((s)->avail_end - (s)->avail_start) |
#define VM_PHYSMEM_SPACE(b) ((uvm_physseg_get_avail_end(b)) - (uvm_physseg_get_avail_start(b))) |
if (maybe_seg == NULL |
if (uvm_physseg_valid_p(maybe_bank) == false |
|| VM_PHYSMEM_SPACE(seg) < VM_PHYSMEM_SPACE(maybe_seg)) { |
|| VM_PHYSMEM_SPACE(bank) < VM_PHYSMEM_SPACE(maybe_bank)) { |
maybe_seg = seg; |
|
maybe_bank = bank; |
maybe_bank = bank; |
} |
} |
} |
} |
|
|
if (maybe_seg) { |
if (uvm_physseg_valid_p(maybe_bank)) { |
struct vm_physseg * const seg = maybe_seg; |
const uvm_physseg_t bank = maybe_bank; |
u_int bank = maybe_bank; |
|
|
|
/* |
/* |
* There are enough pages here; steal them! |
* There are enough pages here; steal them! |
*/ |
*/ |
pa = ptoa(seg->avail_start); |
pa = ptoa(uvm_physseg_get_start(bank)); |
seg->avail_start += npgs; |
uvm_physseg_unplug(atop(pa), npgs); |
seg->start += npgs; |
|
|
|
/* |
|
* Have we used up this segment? |
|
*/ |
|
if (seg->avail_start == seg->end) { |
|
if (vm_nphysseg == 1) |
|
panic("pmap_steal_memory: out of memory!"); |
|
|
|
aprint_debug("%s: seg %u: %zu pages stolen (removed)\n", |
aprint_debug("%s: seg %"PRIxPHYSSEG": %zu pages stolen (%#"PRIxPADDR" left)\n", |
__func__, bank, npgs); |
__func__, bank, npgs, VM_PHYSMEM_SPACE(bank)); |
/* Remove this segment from the list. */ |
|
vm_nphysseg--; |
|
for (u_int x = bank; x < vm_nphysseg; x++) { |
|
/* structure copy */ |
|
VM_PHYSMEM_PTR_SWAP(x, x + 1); |
|
} |
|
} else { |
|
aprint_debug("%s: seg %u: %zu pages stolen (%#"PRIxPADDR" left)\n", |
|
__func__, bank, npgs, VM_PHYSMEM_SPACE(seg)); |
|
} |
|
|
|
va = pmap_md_map_poolpage(pa, size); |
va = pmap_md_map_poolpage(pa, size); |
memset((void *)va, 0, size); |
memset((void *)va, 0, size); |