diff options
-rw-r--r-- | include/kernel/novm.h | 3 | ||||
-rw-r--r-- | kernel/novm.c | 142 | ||||
-rw-r--r-- | lib/heap/heap_wrapper.c | 63 | ||||
-rw-r--r-- | lib/heap/miniheap/miniheap.c | 6 | ||||
-rw-r--r-- | lib/heap/page_alloc.c | 2 | ||||
-rw-r--r-- | platform/stm32f7xx/rules.mk | 2 | ||||
-rw-r--r-- | top/main.c | 4 |
7 files changed, 100 insertions, 122 deletions
diff --git a/include/kernel/novm.h b/include/kernel/novm.h index adce5b52..eabc9ba7 100644 --- a/include/kernel/novm.h +++ b/include/kernel/novm.h @@ -29,10 +29,11 @@ #define PAGE_ALIGN(x) ALIGN(x, PAGE_SIZE) #define IS_PAGE_ALIGNED(x) IS_ALIGNED(x, PAGE_SIZE) -void novm_init(void); void *novm_alloc_pages(size_t pages); void novm_free_pages(void* address, size_t pages); +status_t novm_alloc_specific_pages(void *address, size_t pages); + // You can call this once and it will give you some possibly unaligned memory // that would otherwise go to waste. The memory can't be freed. void *novm_alloc_unaligned(size_t *size_return); diff --git a/kernel/novm.c b/kernel/novm.c index 5a55e83a..294932aa 100644 --- a/kernel/novm.c +++ b/kernel/novm.c @@ -25,55 +25,32 @@ #include <assert.h> #include <kernel/mutex.h> +#include <trace.h> #include <stdlib.h> #include <string.h> +#include <lk/init.h> +#include <err.h> -#if WITH_STATIC_HEAP - -#define DEFAULT_MAP_SIZE (HEAP_LEN >> PAGE_SIZE_SHIFT) - -#else +struct novm_arena { + mutex_t lock; + size_t pages; + char *map; + char *base; + size_t size; +}; /* not a static vm, not using the kernel vm */ extern int _end; extern int _end_of_ram; -/* default to using up the rest of memory after the kernel ends */ -/* may be modified by other parts of the system */ - -#define HEAP_START ((uintptr_t)&_end) -#define HEAP_LEN ((uintptr_t)&_end_of_ram - HEAP_START) - -#define MAP_SIZE (HEAP_LEN >> PAGE_SIZE_SHIFT) -// The map is one byte per page, but we can't statically size that because -// the C compiler doesn't think the difference between two addresses is a -// compile time constant. -// Instead, the default bytemap starts with this many bytes, which covers a -// quarter megabyte if page size is 4k. If that's not enough, we steal the -// first of the plentiful pages for the map. -#define DEFAULT_MAP_SIZE 64 - -#endif +#define MEM_START ((uintptr_t)&_end) +#define MEM_SIZE ((MEMBASE + MEMSIZE) - MEM_START) +#define DEFAULT_MAP_SIZE (MEMSIZE >> PAGE_SIZE_SHIFT) static char allocation_map[DEFAULT_MAP_SIZE]; -struct novm { - mutex_t lock; - size_t pages; - char* map; - char* heap_base; - uintptr_t heap_size; -}; - -static bool in_heap(struct novm *n, void* p) -{ - char *ptr = (char *)p; - char *base = n->heap_base; - return ptr >= base && ptr < base + n->heap_size; -} - -struct novm sram_heap; -struct novm sdram_heap; +struct novm_arena mem_arena; +struct novm_arena sdram_arena; // We divide the memory up into pages. If there is memory we can use before // the first aligned page address, then we record it here and the heap will use @@ -94,8 +71,15 @@ void *novm_alloc_unaligned(size_t *size_return) return novm_alloc_pages(1); } +static bool in_arena(struct novm_arena *n, void* p) +{ + char *ptr = (char *)p; + char *base = n->base; + return ptr >= base && ptr < base + n->size; +} + void novm_init_helper( - struct novm* n, uintptr_t heap_start, + struct novm_arena* n, uintptr_t heap_start, uintptr_t heap_size, char* default_map, size_t default_map_size) { uintptr_t start = ROUNDUP(heap_start, PAGE_SIZE); @@ -123,22 +107,30 @@ void novm_init_helper( n->map = map; memset(n->map, 0, map_size); n->pages = map_size; - n->heap_base = (char *)start; - n->heap_size = size; + n->base = (char *)start; + n->size = size; } -void novm_init(void) +void novm_init_preheap(uint level) { - novm_init_helper(&sram_heap, HEAP_START, HEAP_LEN, allocation_map, DEFAULT_MAP_SIZE); + novm_init_helper(&mem_arena, MEM_START, MEM_SIZE, allocation_map, DEFAULT_MAP_SIZE); #ifdef SDRAM_BASE #define SDRAM_MAP_SIZE (SDRAM_SIZE >> PAGE_SIZE_SHIFT) static char sdram_map[SDRAM_MAP_SIZE]; - novm_init_helper(&sdram_heap, SDRAM_BASE, SDRAM_SIZE, sdram_map, SDRAM_MAP_SIZE); + novm_init_helper(&sdram_arena, SDRAM_BASE, SDRAM_SIZE, sdram_map, SDRAM_MAP_SIZE); +#endif + +#if 0 + /* mark pieces of the novm as used */ + novm_alloc_specific_pages(&__data_start, + ROUNDUP((uintptr_t)&_end - (uintptr_t)&__data_start, PAGE_SIZE) / PAGE_SIZE); #endif } -void *novm_alloc_helper(struct novm *n, size_t pages) +LK_INIT_HOOK(novm_preheap, &novm_init_preheap, LK_INIT_LEVEL_HEAP - 1); + +void *novm_alloc_helper(struct novm_arena *n, size_t pages) { mutex_acquire(&n->lock); for (size_t i = 0; i <= n->pages - pages; i++) { @@ -153,7 +145,7 @@ void *novm_alloc_helper(struct novm *n, size_t pages) if (found) { memset(n->map + i, 1, pages); mutex_release(&n->lock); - return n->heap_base + (i << PAGE_SIZE_SHIFT); + return n->base + (i << PAGE_SIZE_SHIFT); } } mutex_release(&n->lock); @@ -162,26 +154,25 @@ void *novm_alloc_helper(struct novm *n, size_t pages) void* novm_alloc_pages(size_t pages) { - void* result = novm_alloc_helper(&sram_heap, pages); + void* result = novm_alloc_helper(&mem_arena, pages); if (result != NULL) return result; #ifdef SDRAM_BASE - return novm_alloc_helper(&sdram_heap, pages); + return novm_alloc_helper(&sdram_arena, pages); #endif return NULL; } - void novm_free_pages(void* address, size_t pages) { #ifdef SDRAM_BASE - struct novm *n = in_heap(&sram_heap, address) ? &sram_heap : &sdram_heap; + struct novm_arena *n = in_arena(&mem_arena, address) ? &mem_arena : &sdram_arena; #else - struct novm *n = &sram_heap; + struct novm_arena *n = &mem_arena; #endif - DEBUG_ASSERT(in_heap(n, address)); + DEBUG_ASSERT(in_arena(n, address)); - size_t index = ((char *)address - (char*)(n->heap_base)) >> PAGE_SIZE_SHIFT; + size_t index = ((char *)address - (char*)(n->base)) >> PAGE_SIZE_SHIFT; char *map = n->map; mutex_acquire(&n->lock); @@ -189,6 +180,37 @@ void novm_free_pages(void* address, size_t pages) mutex_release(&n->lock); } +status_t novm_alloc_specific_pages(void *address, size_t pages) +{ + TRACEF("address %p, pages %zu\n", address, pages); + + struct novm_arena *n = in_arena(&mem_arena, address) ? &mem_arena : NULL; +#ifdef SDRAM_BASE + if (!n) + n = in_arena(&sdram_arena, address) ? &sdram_arena : NULL; +#endif + if (!n) + return ERR_NOT_FOUND; + + size_t index = ((char *)address - (char*)(n->base)) >> PAGE_SIZE_SHIFT; + char *map = n->map; + + status_t err = NO_ERROR; + + mutex_acquire(&n->lock); + for (size_t i = 0; i < pages; i++) { + if (map[index + i] != 0) { + err = ERR_NO_MEMORY; + break; + } + map[index + i] = 1; + } + mutex_release(&n->lock); + + return err; +} + + #if LK_DEBUGLEVEL > 1 #if WITH_LIB_CONSOLE @@ -222,11 +244,11 @@ usage: return 0; } -static void novm_dump_area(struct novm *n) +static void novm_dump_area(struct novm_arena *n) { mutex_acquire(&n->lock); printf(" %d pages, each %zdk (%zdk in all)\n", n->pages, PAGE_SIZE >> 10, (PAGE_SIZE * n->pages) >> 10); - printf(" %p-%p\n", (void *)n->heap_base, (char *)n->heap_base + n->heap_size); + printf(" %p-%p\n", (void *)n->base, (char *)n->base + n->size); #define MAX_PRINT 1024u unsigned i; for (i = 0; i < MAX_PRINT && i < n->pages; i++) { @@ -241,16 +263,14 @@ static void novm_dump_area(struct novm *n) static void novm_dump(void) { - printf("SRAM area:\n"); - novm_dump_area(&sram_heap); + printf("main memory arena:\n"); + novm_dump_area(&mem_arena); #ifdef SDRAM_BASE - printf("SDRAM area:\n"); - novm_dump_area(&sdram_heap); + printf("SDRAM arena:\n"); + novm_dump_area(&sdram_arena); #endif } #endif #endif -/* vim: set ts=4 sw=4 noexpandtab: */ - diff --git a/lib/heap/heap_wrapper.c b/lib/heap/heap_wrapper.c index 8ba101aa..071a3586 100644 --- a/lib/heap/heap_wrapper.c +++ b/lib/heap/heap_wrapper.c @@ -33,7 +33,7 @@ #include <lib/console.h> #include <lib/page_alloc.h> -#define LOCAL_TRACE 1 +#define LOCAL_TRACE 0 /* delayed free list */ struct list_node delayed_free_list = LIST_INITIAL_VALUE(delayed_free_list); @@ -45,7 +45,12 @@ spin_lock_t delayed_free_lock = SPIN_LOCK_INITIAL_VALUE; #define HEAP_ALLOC miniheap_alloc #define HEAP_FREE miniheap_free -static inline void HEAP_INIT(void) { miniheap_init(NULL, 0); } +static inline void HEAP_INIT(void) { + /* start the heap off with some spare memory in the page allocator */ + size_t len; + void *ptr = page_first_alloc(&len); + miniheap_init(ptr, len); +} #define HEAP_DUMP miniheap_dump static inline void HEAP_TRIM(void) {} @@ -91,35 +96,14 @@ static inline void HEAP_TRIM(void) { dlmalloc_trim(0); } #error need to select valid heap implementation or provide wrapper #endif -#if WITH_KERNEL_VM - -#include <kernel/vm.h> - -/* we will use kalloc routines to back our heap */ -#if !defined(HEAP_GROW_SIZE) -#define HEAP_GROW_SIZE (64 * 1024) /* size the heap grows by when it runs out of memory */ -#endif - -STATIC_ASSERT(IS_PAGE_ALIGNED(HEAP_GROW_SIZE)); +#if WITH_STATIC_HEAP -#elif WITH_STATIC_HEAP +#error "fix static heap post page allocator and novm stuff" #if !defined(HEAP_START) || !defined(HEAP_LEN) #error WITH_STATIC_HEAP set but no HEAP_START or HEAP_LEN defined #endif -#else -/* not a static vm, not using the kernel vm */ -extern int _end; -extern int _end_of_ram; - -/* default to using up the rest of memory after the kernel ends */ -/* may be modified by other parts of the system */ -uintptr_t _heap_start = (uintptr_t)&_end; -uintptr_t _heap_end = (uintptr_t)&_end_of_ram; - -#define HEAP_START ((uintptr_t)_heap_start) -#define HEAP_LEN ((uintptr_t)_heap_end - HEAP_START) #endif static void heap_free_delayed_list(void) @@ -212,35 +196,6 @@ ssize_t heap_grow_memory(void **ptr, size_t size) LTRACEF("returning ptr %p\n", *ptr); return size; - -#if 0 - LTRACEF("ptr %p, size 0x%zx\n", ptr, size); - -#if WITH_KERNEL_VM && !WITH_STATIC_HEAP - size = ROUNDUP(size, PAGE_SIZE); - LTRACEF("size now 0x%zx\n", size); - - *ptr = pmm_alloc_kpages(size / PAGE_SIZE, NULL); - if (!*ptr) { - TRACEF("failed to grow kernel heap by 0x%zx bytes\n", size); - return ERR_NO_MEMORY; - } -#else - static bool have_asked_for_memory = false; - - if (have_asked_for_memory) - return ERR_NO_MEMORY; - - // XXX dont return all of the range on the first call - *ptr = (void *)HEAP_START; - size = HEAP_LEN; - have_asked_for_memory = true; -#endif - - LTRACEF("returning %p, size 0x%zx\n", *ptr, size); - - return size; -#endif } void heap_free_memory(void *ptr, size_t len) diff --git a/lib/heap/miniheap/miniheap.c b/lib/heap/miniheap/miniheap.c index f1baf7e8..7e9f61b4 100644 --- a/lib/heap/miniheap/miniheap.c +++ b/lib/heap/miniheap/miniheap.c @@ -385,7 +385,7 @@ static ssize_t heap_grow(size_t size) void miniheap_init(void *ptr, size_t len) { - LTRACE_ENTRY; + LTRACEF("ptr %p, len %zu\n", ptr, len); // create a mutex mutex_init(&theheap.lock); @@ -398,5 +398,9 @@ void miniheap_init(void *ptr, size_t len) theheap.len = len; theheap.remaining = 0; // will get set by heap_insert_free_chunk() theheap.low_watermark = 0; + + // if passed a default range, use it + if (len > 0) + heap_insert_free_chunk(heap_create_free_chunk(ptr, len, true)); } diff --git a/lib/heap/page_alloc.c b/lib/heap/page_alloc.c index 3ba15c76..b418506c 100644 --- a/lib/heap/page_alloc.c +++ b/lib/heap/page_alloc.c @@ -64,13 +64,13 @@ void page_free(void *ptr, size_t pages) { void *page_first_alloc(size_t *size_return) { #if WITH_KERNEL_VM + *size_return = PAGE_SIZE; return page_alloc(1); #else return novm_alloc_unaligned(size_return); #endif } - #if LK_DEBUGLEVEL > 1 #if WITH_LIB_CONSOLE diff --git a/platform/stm32f7xx/rules.mk b/platform/stm32f7xx/rules.mk index 4836af17..d63eff1a 100644 --- a/platform/stm32f7xx/rules.mk +++ b/platform/stm32f7xx/rules.mk @@ -23,6 +23,8 @@ ifeq ($(FOUND_CHIP),) $(error unknown STM32F7xx chip $(STM32_CHIP)) endif +LK_HEAP_IMPLEMENTATION ?= miniheap + GLOBAL_DEFINES += \ PLATFORM_SUPPORTS_PANIC_SHELL=1 @@ -103,10 +103,6 @@ void lk_main(ulong arg0, ulong arg1, ulong arg2, ulong arg3) dprintf(INFO, "boot args 0x%lx 0x%lx 0x%lx 0x%lx\n", lk_boot_args[0], lk_boot_args[1], lk_boot_args[2], lk_boot_args[3]); -#if !WITH_KERNEL_VM - novm_init(); -#endif - // bring up the kernel heap dprintf(SPEW, "initializing heap\n"); lk_primary_cpu_init_level(LK_INIT_LEVEL_TARGET_EARLY, LK_INIT_LEVEL_HEAP - 1); |