aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/kernel/novm.h3
-rw-r--r--kernel/novm.c142
-rw-r--r--lib/heap/heap_wrapper.c63
-rw-r--r--lib/heap/miniheap/miniheap.c6
-rw-r--r--lib/heap/page_alloc.c2
-rw-r--r--platform/stm32f7xx/rules.mk2
-rw-r--r--top/main.c4
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
diff --git a/top/main.c b/top/main.c
index df6675c9..3e6c3091 100644
--- a/top/main.c
+++ b/top/main.c
@@ -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);