X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootcensus;a=blobdiff_plain;f=src%2Fmem.c;h=a01360777d7b5096a74b84406eb4f620a37835b9;hp=bfc1b3c867338da747e91057875929c530cdd4c0;hb=81c11bdd80190ec319a82b0402173cfb65fcbf72;hpb=a7a5ced32b6e0bd417ee7839fac245de29a81fe5 diff --git a/src/mem.c b/src/mem.c index bfc1b3c..a013607 100644 --- a/src/mem.c +++ b/src/mem.c @@ -17,6 +17,7 @@ along with this program. If not, see . */ #include #include +#include "config.h" #include "panic.h" #include "mem.h" #include "intr.h" @@ -37,6 +38,8 @@ struct mem_range { uint32_t size; }; +void move_stack(uint32_t newaddr); /* defined in startup.s */ + static void mark_page(int pg, int used); static void add_memory(uint32_t start, size_t size); @@ -49,7 +52,7 @@ extern uint32_t _mem_start; /* A bitmap is used to track which physical memory pages are used, and which - * are available for allocation by alloc_phys_page. + * are available for allocation by alloc_ppage. * * last_alloc_idx keeps track of the last 32bit element in the bitmap array * where a free page was found. It's guaranteed that all the elements before @@ -63,7 +66,7 @@ static int bmsize, last_alloc_idx; void init_mem(void) { - int i, pg, max_pg = 0; + int i, pg, max_used_pg, end_pg = 0; uint32_t used_end, start, end, sz, total = 0, rem; const char *suffix[] = {"bytes", "KB", "MB", "GB"}; @@ -107,8 +110,8 @@ void init_mem(void) total += sz; pg = ADDR_TO_PAGE(end); - if(max_pg < pg) { - max_pg = pg; + if(end_pg < pg) { + end_pg = pg; } } @@ -120,66 +123,40 @@ void init_mem(void) } printf("Total usable RAM: %u.%u %s\n", total, 100 * rem / 1024, suffix[i]); - bmsize = max_pg / 8; /* size of the useful bitmap in bytes */ + /* size of the useful part of the bitmap in bytes padded to 4-byte + * boundaries to allow 32bit at a time operations. + */ + bmsize = (end_pg / 32) * 4; - /* mark all pages occupied by the bitmap as usef */ + /* mark all pages occupied by the bitmap as used */ used_end = (uint32_t)bitmap + bmsize - 1; - printf("marking pages up to %x (page: %d) as used\n", used_end, ADDR_TO_PAGE(used_end)); - - for(i=0; i<=used_end; i++) { + max_used_pg = ADDR_TO_PAGE(used_end); + printf("marking pages up to %x (page: %d) as used\n", used_end, max_used_pg); + for(i=0; i<=max_used_pg; i++) { mark_page(i, USED); } -} -/* alloc_phys_page finds the first available page of physical memory, - * marks it as used in the bitmap, and returns its number. If there's - * no unused physical page, -1 is returned. - */ -int alloc_ppage(void) -{ - int i, idx, max, intr_state; - - intr_state = get_intr_flag(); - disable_intr(); - - idx = last_alloc_idx; - max = bmsize / 4; - - while(idx <= max) { - /* if at least one bit is 0 then we have at least - * one free page. find it and allocate it. - */ - if(bitmap[idx] != 0xffffffff) { - for(i=0; i<32; i++) { - int pg = idx * 32 + i; - - if(IS_FREE(pg)) { - mark_page(pg, USED); - - last_alloc_idx = idx; - - /*printf("alloc_phys_page() -> %x (page: %d)\n", PAGE_TO_ADDR(pg), pg);*/ - - set_intr_flag(intr_state); - return pg; - } - } - panic("can't happen: alloc_ppage (mem.c)\n"); - } - idx++; +#ifdef MOVE_STACK_RAMTOP + /* allocate space for the stack at the top of RAM and move it there */ + if((pg = alloc_ppages(STACK_PAGES, MEM_STACK)) != -1) { + printf("moving stack-top to: %x (%d pages)\n", PAGE_TO_ADDR(end_pg) - 4, STACK_PAGES); + move_stack(PAGE_TO_ADDR(pg + STACK_PAGES) - 4); } +#endif +} - set_intr_flag(intr_state); - return -1; +int alloc_ppage(int area) +{ + return alloc_ppages(1, area); } /* free_ppage marks the physical page, free in the allocation bitmap. * * CAUTION: no checks are done that this page should actually be freed or not. - * If you call free_phys_page with the address of some part of memory that was + * If you call free_ppage with the address of some part of memory that was * originally reserved due to it being in a memory hole or part of the kernel - * image or whatever, it will be subsequently allocatable by alloc_phys_page. + * image or whatever, it will be subsequently allocatable by alloc_ppage. */ void free_ppage(int pg) { @@ -201,9 +178,69 @@ void free_ppage(int pg) } +int alloc_ppages(int count, int area) +{ + int i, dir, pg, idx, max, intr_state, found_free = 0; + + intr_state = get_intr_flag(); + disable_intr(); + + if(area == MEM_STACK) { + idx = (bmsize - 1) / 4; + max = -1; + dir = -1; + } else { + idx = last_alloc_idx; + max = bmsize / 4; + dir = 1; + } + + while(idx != max) { + /* if at least one bit is 0 then we have at least + * one free page. find it and try to allocate a range starting from there + */ + if(bitmap[idx] != 0xffffffff) { + pg = idx * 32; + if(dir < 0) pg += 31; + + for(i=0; i<32; i++) { + if(IS_FREE(pg)) { + if(!found_free && dir > 0) { + last_alloc_idx = idx; + found_free = 1; + } + + if(alloc_ppage_range(pg, count) != -1) { + set_intr_flag(intr_state); + return pg; + } + } + pg += dir; + } + } + idx += dir; + } + + set_intr_flag(intr_state); + return -1; +} + +void free_ppages(int pg0, int count) +{ + int i; + + for(i=0; i