summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_phys.c
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2015-01-02 17:45:52 +0000
committeralc <alc@FreeBSD.org>2015-01-02 17:45:52 +0000
commitd5a13901bff0d31efdcb363925086b0e00bea32b (patch)
treefa41565eff257f888b11c0e324e0bc2f147f72ad /sys/vm/vm_phys.c
parent5309e52c3c33e83023a6edac5ef5dea2b34b5c55 (diff)
downloadFreeBSD-src-d5a13901bff0d31efdcb363925086b0e00bea32b.zip
FreeBSD-src-d5a13901bff0d31efdcb363925086b0e00bea32b.tar.gz
MFC r273701, r274556
By the time that pmap_init() runs, vm_phys_segs[] has been initialized. Obtaining the end of memory address from vm_phys_segs[] is a little easier than obtaining it from phys_avail[]. Enable the use of VM_PHYSSEG_SPARSE on amd64 and i386, making it the default on i386 PAE. (The use of VM_PHYSSEG_SPARSE on i386 PAE saves us some precious kernel virtual address space that would have been wasted on unused vm_page structures.)
Diffstat (limited to 'sys/vm/vm_phys.c')
-rw-r--r--sys/vm/vm_phys.c101
1 files changed, 56 insertions, 45 deletions
diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c
index b354a8d..aad2e13 100644
--- a/sys/vm/vm_phys.c
+++ b/sys/vm/vm_phys.c
@@ -246,29 +246,19 @@ static void
_vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end, int flind, int domain)
{
struct vm_phys_seg *seg;
-#ifdef VM_PHYSSEG_SPARSE
- long pages;
- int segind;
- pages = 0;
- for (segind = 0; segind < vm_phys_nsegs; segind++) {
- seg = &vm_phys_segs[segind];
- pages += atop(seg->end - seg->start);
- }
-#endif
KASSERT(vm_phys_nsegs < VM_PHYSSEG_MAX,
("vm_phys_create_seg: increase VM_PHYSSEG_MAX"));
KASSERT(domain < vm_ndomains,
("vm_phys_create_seg: invalid domain provided"));
seg = &vm_phys_segs[vm_phys_nsegs++];
+ while (seg > vm_phys_segs && (seg - 1)->start >= end) {
+ *seg = *(seg - 1);
+ seg--;
+ }
seg->start = start;
seg->end = end;
seg->domain = domain;
-#ifdef VM_PHYSSEG_SPARSE
- seg->first_page = &vm_page_array[pages];
-#else
- seg->first_page = PHYS_TO_VM_PAGE(start);
-#endif
seg->free_queues = &vm_phys_free_queues[domain][flind];
}
@@ -302,47 +292,68 @@ vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end, int flind)
}
/*
- * Initialize the physical memory allocator.
+ * Add a physical memory segment.
*/
void
-vm_phys_init(void)
+vm_phys_add_seg(vm_paddr_t start, vm_paddr_t end)
{
- struct vm_freelist *fl;
- int dom, flind, i, oind, pind;
- for (i = 0; phys_avail[i + 1] != 0; i += 2) {
+ KASSERT((start & PAGE_MASK) == 0,
+ ("vm_phys_define_seg: start is not page aligned"));
+ KASSERT((end & PAGE_MASK) == 0,
+ ("vm_phys_define_seg: end is not page aligned"));
#ifdef VM_FREELIST_ISADMA
- if (phys_avail[i] < 16777216) {
- if (phys_avail[i + 1] > 16777216) {
- vm_phys_create_seg(phys_avail[i], 16777216,
- VM_FREELIST_ISADMA);
- vm_phys_create_seg(16777216, phys_avail[i + 1],
- VM_FREELIST_DEFAULT);
- } else {
- vm_phys_create_seg(phys_avail[i],
- phys_avail[i + 1], VM_FREELIST_ISADMA);
- }
- if (VM_FREELIST_ISADMA >= vm_nfreelists)
- vm_nfreelists = VM_FREELIST_ISADMA + 1;
+ if (start < 16777216) {
+ if (end > 16777216) {
+ vm_phys_create_seg(start, 16777216,
+ VM_FREELIST_ISADMA);
+ vm_phys_create_seg(16777216, end, VM_FREELIST_DEFAULT);
} else
+ vm_phys_create_seg(start, end, VM_FREELIST_ISADMA);
+ if (VM_FREELIST_ISADMA >= vm_nfreelists)
+ vm_nfreelists = VM_FREELIST_ISADMA + 1;
+ } else
#endif
#ifdef VM_FREELIST_HIGHMEM
- if (phys_avail[i + 1] > VM_HIGHMEM_ADDRESS) {
- if (phys_avail[i] < VM_HIGHMEM_ADDRESS) {
- vm_phys_create_seg(phys_avail[i],
- VM_HIGHMEM_ADDRESS, VM_FREELIST_DEFAULT);
- vm_phys_create_seg(VM_HIGHMEM_ADDRESS,
- phys_avail[i + 1], VM_FREELIST_HIGHMEM);
- } else {
- vm_phys_create_seg(phys_avail[i],
- phys_avail[i + 1], VM_FREELIST_HIGHMEM);
- }
- if (VM_FREELIST_HIGHMEM >= vm_nfreelists)
- vm_nfreelists = VM_FREELIST_HIGHMEM + 1;
+ if (end > VM_HIGHMEM_ADDRESS) {
+ if (start < VM_HIGHMEM_ADDRESS) {
+ vm_phys_create_seg(start, VM_HIGHMEM_ADDRESS,
+ VM_FREELIST_DEFAULT);
+ vm_phys_create_seg(VM_HIGHMEM_ADDRESS, end,
+ VM_FREELIST_HIGHMEM);
} else
+ vm_phys_create_seg(start, end, VM_FREELIST_HIGHMEM);
+ if (VM_FREELIST_HIGHMEM >= vm_nfreelists)
+ vm_nfreelists = VM_FREELIST_HIGHMEM + 1;
+ } else
+#endif
+ vm_phys_create_seg(start, end, VM_FREELIST_DEFAULT);
+}
+
+/*
+ * Initialize the physical memory allocator.
+ */
+void
+vm_phys_init(void)
+{
+ struct vm_freelist *fl;
+ struct vm_phys_seg *seg;
+#ifdef VM_PHYSSEG_SPARSE
+ long pages;
+#endif
+ int dom, flind, oind, pind, segind;
+
+#ifdef VM_PHYSSEG_SPARSE
+ pages = 0;
+#endif
+ for (segind = 0; segind < vm_phys_nsegs; segind++) {
+ seg = &vm_phys_segs[segind];
+#ifdef VM_PHYSSEG_SPARSE
+ seg->first_page = &vm_page_array[pages];
+ pages += atop(seg->end - seg->start);
+#else
+ seg->first_page = PHYS_TO_VM_PAGE(seg->start);
#endif
- vm_phys_create_seg(phys_avail[i], phys_avail[i + 1],
- VM_FREELIST_DEFAULT);
}
for (dom = 0; dom < vm_ndomains; dom++) {
for (flind = 0; flind < vm_nfreelists; flind++) {
OpenPOWER on IntegriCloud