81 lines
2.1 KiB
C++
81 lines
2.1 KiB
C++
#include <cstdint>
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
|
|
#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");
|
|
}
|