#include #include #include #include "cortexa8.hh" #include "phys_mm.hh" #include "util.hh" #include "mm.hh" extern uint32_t __scratch_start, __scratch_end, __io_start, __io_end, __heap_start, __heap_end, __pc_start, __pc_end; static const uintptr_t scratch_start = (uintptr_t)&__scratch_start; static const uintptr_t scratch_end = (uintptr_t)&__scratch_end; static const uintptr_t io_start = (uintptr_t)&__io_start; static const uintptr_t io_end = (uintptr_t)&__io_end; static const uintptr_t heap_start = (uintptr_t)&__heap_start; static const uintptr_t heap_end = (uintptr_t)&__heap_end; static const uintptr_t pc_start = (uintptr_t)&__pc_start; static const uintptr_t pc_end = (uintptr_t)&__pc_end; static uintptr_t heap_top, io_top, pc_top; void mm::init() { heap_top = phys_mm::get_end_of_kernel_alloc(); /* Map unused area of kernel image RAM to heap The space between the end of the kernel and the end of the power-of-2 block allocated for it by physical allocater is lost otherwise */ uintptr_t heap_start_align = ((heap_start&0xfff)==0)?heap_start:((heap_start&~0xfff)+4096); cortexa8::map_pages(heap_start_align, heap_start_align, (heap_top-heap_start)/4096); io_top = io_start; pc_top = pc_start; } uintptr_t mm::virtalloc_io(unsigned pages) { if(io_top+0x1000*pages >= io_end) throw bad_alloc{}; uintptr_t ret = io_top; io_top += 0x1000*pages; return ret; } uintptr_t mm::grow_heap(unsigned pages) { // Allocations are done in powers to 2, so round up pages to next power of 2 pages = _pow2(_ln2(pages)); if(heap_top+0x1000*pages >= heap_end) throw bad_alloc{}; uintptr_t newphys = phys_mm::alloc(pages); cortexa8::map_pages(heap_top, newphys, pages); heap_top += 0x1000*pages; return heap_top; } uintptr_t mm::get_heap_end() { return heap_top; } uintptr_t mm::virtalloc_pc(unsigned pages) { if(pc_top+0x1000*pages >= pc_end) throw bad_alloc{}; uintptr_t ret = pc_top; pc_top += 0x1000*pages; return ret; } void mm::virtfree_pc(uintptr_t base) { printf("NYI: virtfree_pc\n"); }