diff options
author | Richard Braun <rbraun@sceen.net> | 2016-01-23 19:52:24 +0100 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2016-01-23 21:24:25 +0100 |
commit | e835160b6b95f3b904fbc429392a63be1e4ed6b8 (patch) | |
tree | 28c0dd9f3b460b09ce1d9f8e7926b02bb93576b1 /linux/dev/init/main.c | |
parent | 451b007174d87aae30872b1269fc922331665b9c (diff) |
Use vm_page as the physical memory allocator
This change replaces the historical page allocator with a buddy allocator
implemented in vm/vm_page.c. This allocator allows easy contiguous allocations
and also manages memory inside segments. In a future change, these segments
will be used to service requests with special constraints, such as "usable
for 16-bits DMA" or "must be part of the direct physical mapping".
* Makefrag.am (libkernel_a_SOURCES): Add vm/vm_page.c.
* i386/Makefrag.am (libkernel_a_SOURCES): Add i386/i386at/biosmem.{c,h}.
* i386/i386/vm_param.h: Include kern/macros.h.
(VM_PAGE_DMA_LIMIT, VM_PAGE_MAX_SEGS, VM_PAGE_DMA32_LIMIT,
VM_PAGE_DIRECTMAP_LIMIT, VM_PAGE_HIGHMEM_LIMIT, VM_PAGE_SEG_DMA,
VM_PAGE_SEG_DMA32, VM_PAGE_SEG_DIRECTMAP, VM_PAGE_SEG_HIGHMEM): New macros.
* i386/i386at/model_dep.c: Include i386at/biosmem.h.
(avail_next, avail_remaining): Remove variables.
(mem_size_init): Remove function.
(i386at_init): Initialize and use the biosmem module for early physical
memory management.
(pmap_free_pages): Return phys_last_addr instead of avail_remaining.
(init_alloc_aligned): Turn into a wrapper for biosmem_bootalloc.
(pmap_grab_page): Directly call init_alloc_aligned instead of pmap_next_page.
* i386/include/mach/i386/vm_types.h (phys_addr_t): New type.
* kern/bootstrap.c (free_bootstrap_pages): New function.
(bootstrap_create): Call free_bootstrap_pages instead of vm_page_create.
* kern/cpu_number.h (CPU_L1_SIZE): New macro.
* kern/slab.h: Include kern/cpu_number.h.
(CPU_L1_SIZE): Remove macro, moved to kern/cpu_number.h.
* kern/startup.c (setup_main): Change the value of machine_info.memory_size.
* linux/dev/glue/glue.h (alloc_contig_mem, free_contig_mem): Update prototypes.
* linux/dev/glue/kmem.c (linux_kmem_init): Don't use defunct page queue.
* linux/dev/init/main.c (linux_init): Don't free unused memory.
(alloc_contig_mem, free_contig_mem): Turn into wrappers for the vm_page
allocator.
* linux/pcmcia-cs/glue/ds.c (PAGE_SHIFT): Don't undefine.
* vm/pmap.h (pmap_startup, pmap_next_page): Remove prototypes.
* vm/vm_fault.c (vm_fault_page): Update calls to vm_page_convert.
* vm/vm_init.c (vm_mem_init): Call vm_page_info_all.
* vm/vm_object.c (vm_object_page_map): Update call to vm_page_init.
* vm/vm_page.h (vm_page_queue_free): Remove variable declaration.
(vm_page_create, vm_page_release_fictitious, vm_page_release): Remove
declarations.
(vm_page_convert, vm_page_init): Update prototypes.
(vm_page_grab_contig, vm_page_free_contig): New prototypes.
* vm/vm_resident.c (vm_page_template, vm_page_queue_free,
vm_page_big_pagenum): Remove variables.
(vm_page_bootstrap): Update and call vm_page_setup.
(pmap_steal_memory): Update and call vm_page_bootalloc.
(pmap_startup, vm_page_create, vm_page_grab_contiguous_pages): Remove functions.
(vm_page_init_template, vm_page_grab_contig,
vm_page_free_contig): New functions.
(vm_page_init): Update and call vm_page_init_template.
(vm_page_release_fictitious): Make static.
(vm_page_more_fictitious): Update call to vm_page_init.
(vm_page_convert): Rewrite to comply with vm_page.
(vm_page_grab): Update and call vm_page_alloc_pa.
(vm_page_release): Update and call vm_page_free_pa.
Diffstat (limited to 'linux/dev/init/main.c')
-rw-r--r-- | linux/dev/init/main.c | 143 |
1 files changed, 12 insertions, 131 deletions
diff --git a/linux/dev/init/main.c b/linux/dev/init/main.c index 8737b62..d69b3fc 100644 --- a/linux/dev/init/main.c +++ b/linux/dev/init/main.c @@ -98,7 +98,7 @@ void linux_init (void) { int addr; - unsigned memory_start, memory_end; + unsigned long memory_start, memory_end; vm_page_t pages; /* @@ -131,9 +131,7 @@ linux_init (void) /* * Allocate contiguous memory below 16 MB. */ - memory_start = (unsigned long) alloc_contig_mem (CONTIG_ALLOC, - 16 * 1024 * 1024, - 0, &pages); + memory_start = alloc_contig_mem (CONTIG_ALLOC, 16 * 1024 * 1024, 0, &pages); if (memory_start == 0) panic ("linux_init: alloc_contig_mem failed"); memory_end = memory_start + CONTIG_ALLOC; @@ -147,14 +145,6 @@ linux_init (void) panic ("linux_init: ran out memory"); /* - * Free unused memory. - */ - while (pages && phystokv(pages->phys_addr) < round_page (memory_start)) - pages = (vm_page_t) pages->pageq.next; - if (pages) - free_contig_mem (pages); - - /* * Initialize devices. */ #ifdef CONFIG_INET @@ -182,140 +172,31 @@ linux_init (void) /* * Allocate contiguous memory with the given constraints. - * This routine is horribly inefficient but it is presently - * only used during initialization so it's not that bad. */ -void * +unsigned long alloc_contig_mem (unsigned size, unsigned limit, unsigned mask, vm_page_t * pages) { - int i, j, bits_len; - unsigned *bits, len; - void *m; - vm_page_t p, page_list, tail, prev; - vm_offset_t addr = 0, max_addr; - - if (size == 0) - return (NULL); - size = round_page (size); - if ((size >> PAGE_SHIFT) > vm_page_free_count) - return (NULL); - - /* Allocate bit array. */ - max_addr = phys_last_addr; - if (max_addr > limit) - max_addr = limit; - bits_len = ((((max_addr >> PAGE_SHIFT) + NBPW - 1) / NBPW) - * sizeof (unsigned)); - bits = (unsigned *) kalloc (bits_len); - if (!bits) - return (NULL); - memset (bits, 0, bits_len); + vm_page_t p; - /* - * Walk the page free list and set a bit for every usable page. - */ - simple_lock (&vm_page_queue_free_lock); - p = vm_page_queue_free; - while (p) - { - if (p->phys_addr < limit) - (bits[(p->phys_addr >> PAGE_SHIFT) / NBPW] - |= 1 << ((p->phys_addr >> PAGE_SHIFT) % NBPW)); - p = (vm_page_t) p->pageq.next; - } + p = vm_page_grab_contig(size, VM_PAGE_SEL_DMA); - /* - * Scan bit array for contiguous pages. - */ - len = 0; - m = NULL; - for (i = 0; len < size && i < bits_len / sizeof (unsigned); i++) - for (j = 0; len < size && j < NBPW; j++) - if (!(bits[i] & (1 << j))) - { - len = 0; - m = NULL; - } - else - { - if (len == 0) - { - addr = ((vm_offset_t) (i * NBPW + j) - << PAGE_SHIFT); - if ((addr & mask) == 0) - { - len += PAGE_SIZE; - m = (void *) addr; - } - } - else - len += PAGE_SIZE; - } - - if (len != size) - { - simple_unlock (&vm_page_queue_free_lock); - kfree ((vm_offset_t) bits, bits_len); - return (NULL); - } - - /* - * Remove pages from free list - * and construct list to return to caller. - */ - page_list = NULL; - for (len = 0; len < size; len += PAGE_SIZE, addr += PAGE_SIZE) - { - prev = NULL; - for (p = vm_page_queue_free; p; p = (vm_page_t) p->pageq.next) - { - if (p->phys_addr == addr) - break; - prev = p; - } - if (!p) - panic ("alloc_contig_mem: page not on free list"); - if (prev) - prev->pageq.next = p->pageq.next; - else - vm_page_queue_free = (vm_page_t) p->pageq.next; - p->free = FALSE; - p->pageq.next = NULL; - if (!page_list) - page_list = tail = p; - else - { - tail->pageq.next = (queue_entry_t) p; - tail = p; - } - vm_page_free_count--; - } + if (p == NULL) + return 0; - simple_unlock (&vm_page_queue_free_lock); - kfree ((vm_offset_t) bits, bits_len); if (pages) - *pages = page_list; - return (void *) phystokv(m); + *pages = p; + + return phystokv(vm_page_to_pa(p)); } /* * Free memory allocated by alloc_contig_mem. */ void -free_contig_mem (vm_page_t pages) +free_contig_mem (vm_page_t pages, unsigned size) { - int i; - vm_page_t p; - - for (p = pages, i = 0; p->pageq.next; p = (vm_page_t) p->pageq.next, i++) - p->free = TRUE; - p->free = TRUE; - simple_lock (&vm_page_queue_free_lock); - vm_page_free_count += i + 1; - p->pageq.next = (queue_entry_t) vm_page_queue_free; - vm_page_queue_free = pages; - simple_unlock (&vm_page_queue_free_lock); + vm_page_free_contig(pages, size); } /* This is the number of bits of precision for the loops_per_second. Each |