From 2904fb0420ec6ce9fb4f3d43a53be3b56ce62f7b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 31 Aug 2014 12:50:05 -0600 Subject: [PATCH] Clean up some kernel build heap allocation issues. The Cortex-A kernel build now compiles without errors (but cannot link until brk() and sbrk() are implemented). --- arch/arm/src/sama5/sam_allocateheap.c | 162 +++++++------------------- include/nuttx/arch.h | 9 +- include/nuttx/kmalloc.h | 6 +- include/nuttx/mm.h | 23 +++- sched/init/os_start.c | 6 +- sched/sched/sched_free.c | 5 +- 6 files changed, 75 insertions(+), 136 deletions(-) diff --git a/arch/arm/src/sama5/sam_allocateheap.c b/arch/arm/src/sama5/sam_allocateheap.c index 44c32fcd4e..616b6f0fde 100644 --- a/arch/arm/src/sama5/sam_allocateheap.c +++ b/arch/arm/src/sama5/sam_allocateheap.c @@ -57,6 +57,30 @@ /**************************************************************************** * Private Definitions ****************************************************************************/ +/* Configuration ************************************************************/ +/* Terminology. In the flat build (CONFIG_BUILD_FLAT=y), there is only a + * single heap access with the standard allocations (malloc/free). This + * heap is referred to as the user heap. In the protected build + * (CONFIG_BUILD_PROTECTED=y) where an MPU is used to protect a region of + * otherwise flat memory, there will be two allocators: One that allocates + * protected (kernel) memory and one that allocates unprotected (user) + * memory. These are referred to as the kernel and user heaps, + * respectively. + * + * The ARMv7 has no MPU but does have an MMU. With this MMU, it can support + * the kernel build (CONFIG_BUILD_KERNEL=y). In this configuration, there + * is again only one heap but, retaining the terminology, this is the kernel + * heap. + */ + +#if defined(CONFIG_MM_USER_HEAP) && defined(CONFIG_MM_KERNEL_HEAP) +# error "Cannot support both user and kernel heaps" +#elif defined(CONFIG_MM_KERNEL_HEAP) +# define MM_ADDREGION kmm_addregion +#else +# define MM_ADDREGION umm_addregion +#endif + /* The Primary Heap *********************************************************/ /* The physical address of the primary heap is defined by CONFIG_RAM_START, * CONFIG_RAM_SIZE, and CONFIG_RAM_END where: @@ -213,60 +237,23 @@ ****************************************************************************/ /**************************************************************************** - * Name: up_allocate_heap + * Name: up_allocate_heap/up_allocate_kheap * * Description: * This function will be called to dynamically set aside the heap region. - * - * For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel- and - * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the - * size of the unprotected, user-space heap. - * - * If a protected kernel-space heap is provided, the kernel heap must be - * allocated by an analogous up_allocate_kheap(). A custom version of this - * file is needed if memory protection of the kernel heap is required. - * - * The following memory map is assumed for the flat build: - * - * .data region. Size determined at link time. - * .bss region Size determined at link time. - * IDLE thread stack. Size determined by CONFIG_IDLETHREAD_STACKSIZE. - * Heap. Extends to the end of SRAM. - * - * The following memory map is assumed for the kernel build: - * - * Kernel .data region. Size determined at link time. - * Kernel .bss region Size determined at link time. - * Kernel IDLE thread stack. Size determined by CONFIG_IDLETHREAD_STACKSIZE. - * Padding for alignment - * User .data region. Size determined at link time. - * User .bss region Size determined at link time. - * Kernel heap. Size determined by CONFIG_MM_KERNEL_HEAPSIZE. - * User heap. Extends to the end of SRAM. + * For the flat build, this heap is referred to as the user heap (for + * compatibility with other platforms). For the kernel build + * (CONFIG_BUILD_KERNEL=y) this is referred to a the kernel heap. * ****************************************************************************/ +#if defined(CONFIG_MM_USER_HEAP) void up_allocate_heap(FAR void **heap_start, size_t *heap_size) +#elif defined(CONFIG_MM_KERNEL_HEAP) +void up_allocate_kheap(FAR void **heap_start, size_t *heap_size) +#endif { -#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) - /* Get the unaligned size and position of the user-space heap. - * This heap begins after the user-space .bss section at an offset - * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). - */ - - uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend + CONFIG_MM_KERNEL_HEAPSIZE; - size_t usize = SAMA5_PRIMARY_HEAP_END - ubase; - int log2; - - DEBUGASSERT(ubase < (uintptr_t)SAMA5_PRIMARY_HEAP_END); - - /* Return the user-space heap settings */ - - board_led_on(LED_HEAPALLOCATE); - *heap_start = (FAR void*)ubase; - *heap_size = usize; - -#elif defined(CONFIG_BOOT_SDRAM_DATA) +#if defined(CONFIG_BOOT_SDRAM_DATA) /* In this case, the IDLE stack is in ISRAM, but data is in SDRAM. The * heap is at the end of BSS through the configured end of SDRAM. */ @@ -286,40 +273,6 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size) #endif } -/**************************************************************************** - * Name: up_allocate_kheap - * - * Description: - * For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel- and - * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates - * the kernel-space heap. A custom version of this function is need if - * memory protection of the kernel heap is required. - * - ****************************************************************************/ - -#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) -void up_allocate_kheap(FAR void **heap_start, size_t *heap_size) -{ - /* Get the unaligned size and position of the user-space heap. - * This heap begins after the user-space .bss section at an offset - * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). - */ - - uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend + CONFIG_MM_KERNEL_HEAPSIZE; - size_t usize = SAMA5_PRIMARY_HEAP_END - ubase; - int log2; - - DEBUGASSERT(ubase < (uintptr_t)SAMA5_PRIMARY_HEAP_END); - - /* Return the kernel heap settings (i.e., the part of the heap region - * that was not dedicated to the user heap). - */ - - *heap_start = (FAR void*)USERSPACE->us_bssend; - *heap_size = ubase - (uintptr_t)USERSPACE->us_bssend; -} -#endif - /**************************************************************************** * Name: up_addregion * @@ -340,16 +293,9 @@ void up_addregion(void) vaddr = (uintptr_t)SAM_ISRAM0_VADDR size = SAM_ISRAM0_SIZE + SAM_ISRAM1_SIZE; -#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) - /* Allow user-mode access to the ISRAM heap */ - - sam_uheap(vaddr, size); - -#endif - /* Add the ISRAM user heap region. */ - kumm_addregion((void *)vaddr, size); + MM_ADDREGION((void *)vaddr, size); nregions--; #endif @@ -359,15 +305,9 @@ void up_addregion(void) vaddr = (uintptr_t)SAM_DDRCS_VSECTION + SAMA5_DDRCS_HEAP_OFFSET; size = SAMA5_DDRCS_HEAP_SIZE; -#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) - /* Allow user-mode access to the DDR-SDRAM heap */ - - sam_uheap(vaddr, size); -#endif - /* Add the DDR-SDRAM user heap region. */ - kumm_addregion((void *)vaddr, size); + MM_ADDREGION((void *)vaddr, size); nregions--; } else @@ -384,15 +324,9 @@ void up_addregion(void) vaddr = (uintptr_t)SAM_EBICS0_VSECTION + SAMA5_EBICS0_HEAP_OFFSET; size = SAMA5_EBICS0_HEAP_SIZE; -#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) - /* Allow user-mode access to the EBICS0 heap */ - - sam_uheap(vaddr, size); -#endif - /* Add the EBICS0 user heap region. */ - kumm_addregion((void *)vaddr, size); + MM_ADDREGION((void *)vaddr, size); nregions--; } else @@ -409,15 +343,9 @@ void up_addregion(void) vaddr = (uintptr_t)SAM_EBICS1_VSECTION + SAMA5_EBICS1_HEAP_OFFSET; size = SAMA5_EBICS1_HEAP_SIZE; -#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) - /* Allow user-mode access to the EBICS1 heap */ - - sam_uheap(vaddr, size); -#endif - /* Add the EBICS1 user heap region. */ - kumm_addregion((void *)vaddr, size); + MM_ADDREGION((void *)vaddr, size); nregions--; } else @@ -434,15 +362,9 @@ void up_addregion(void) vaddr = (uintptr_t)SAM_EBICS2_VSECTION + SAMA5_EBICS2_HEAP_OFFSET; size = SAMA5_EBICS2_HEAP_SIZE; -#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) - /* Allow user-mode access to the EBICS2 heap */ - - sam_uheap(vaddr, size); -#endif - /* Add the EBICS2 user heap region. */ - kumm_addregion((void *)vaddr, size); + MM_ADDREGION((void *)vaddr, size); nregions--; } else @@ -459,15 +381,9 @@ void up_addregion(void) vaddr = (uintptr_t)SAM_EBICS3_VSECTION + SAMA5_EBICS3_HEAP_OFFSET; size = SAMA5_EBICS3_HEAP_SIZE; -#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) - /* Allow user-mode access to the EBICS3 heap */ - - sam_uheap(vaddr, size); -#endif - /* Add the EBICS3 user heap region. */ - kumm_addregion(vaddr, size); + MM_ADDREGION(vaddr, size); nregions--; } else diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 63670d27c8..0393f66192 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -645,13 +645,14 @@ void up_allocate_heap(FAR void **heap_start, size_t *heap_size); * Name: up_allocate_kheap * * Description: - * For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and - * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates - * (and protects) the kernel-space heap. + * For the kernel builds (CONFIG_BUILD_PROTECTED=y or + * CONFIG_BUILD_KERNEL=y) there may be both kernel- and user-space heaps + * as determined by CONFIG_MM_KERNEL_HEAP=y. This function allocates (and + * protects) the kernel-space heap. * ****************************************************************************/ -#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) +#ifdef CONFIG_MM_KERNEL_HEAP void up_allocate_kheap(FAR void **heap_start, size_t *heap_size); #endif diff --git a/include/nuttx/kmalloc.h b/include/nuttx/kmalloc.h index 50aa802075..c26fb521e7 100644 --- a/include/nuttx/kmalloc.h +++ b/include/nuttx/kmalloc.h @@ -135,7 +135,7 @@ extern "C" #elif !defined(CONFIG_MM_KERNEL_HEAP) /* If this the kernel phase of a kernel build, and there are only user-space * allocators, then the following are defined in userspace.h as macros that - * call into user-space via a header at the begining of the user-space blob. + * call into user-space via a header at the beginning of the user-space blob. */ # define kmm_initialize(h,s) /* Initialization done by kumm_initialize */ @@ -178,9 +178,11 @@ bool kmm_heapmember(FAR void *mem); * sched_garbagecollection(). */ +#ifdef CONFIG_MM_USER_HEAP void sched_ufree(FAR void *address); +#endif -#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) +#if defined(CONFIG_MM_KERNEL_HEAP) && defined(__KERNEL__) void sched_kfree(FAR void *address); #else # define sched_kfree(a) sched_ufree(a) diff --git a/include/nuttx/mm.h b/include/nuttx/mm.h index de217e550d..cfafc8381e 100644 --- a/include/nuttx/mm.h +++ b/include/nuttx/mm.h @@ -65,10 +65,27 @@ # define CONFIG_MM_SMALL 1 #endif +/* Decide if there is a user heap. CONFIG_MM_USER_HEAP=n does not not + * really that there is no user heap but, rather, that there is no + * user heap available from within the kernel. The user heap is + * Available if: + * + * 1. The code is begin build for kernel space and this is a FLAT build + * (CONFIG_BUILD_FLAT=y), + * 2. The code is begin build for kernel space and this is a protected + * build (CONFIG_BUILD_PROTECTED=y), OR + * 3. The code is begin build for user space. + */ + #undef CONFIG_MM_USER_HEAP -#if (!defined(CONFIG_BUILD_PROTECTED) || !defined(__KERNEL__)) && \ - !defined(CONFIG_BUILD_KERNEL) -# define CONFIG_MM_USER_HEAP +#if !defined(CONFIG_BUILD_KERNEL) || !defined(__KERNEL__) +# define CONFIG_MM_USER_HEAP 1 +#endif + +/* The kernel heap is never accessible from user code */ + +#ifndef __KERNEL__ +# undef CONFIG_MM_KERNEL_HEAP #endif /* Chunk Header Definitions *************************************************/ diff --git a/sched/init/os_start.c b/sched/init/os_start.c index b1ac5af2f6..4f6da4ea57 100644 --- a/sched/init/os_start.c +++ b/sched/init/os_start.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -346,15 +347,16 @@ void os_start(void) FAR void *heap_start; size_t heap_size; +#ifdef CONFIG_MM_USER_HEAP /* Get the user-mode heap from the platform specific code and configure * the user-mode memory allocator. */ up_allocate_heap(&heap_start, &heap_size); kumm_initialize(heap_start, heap_size); +#endif -#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \ - defined(CONFIG_MM_KERNEL_HEAP) +#ifdef CONFIG_MM_KERNEL_HEAP /* Get the kernel-mode heap from the platform specific code and configure * the kernel-mode memory allocator. */ diff --git a/sched/sched/sched_free.c b/sched/sched/sched_free.c index 97f1429f69..6456d099b3 100644 --- a/sched/sched/sched_free.c +++ b/sched/sched/sched_free.c @@ -82,6 +82,7 @@ * ************************************************************************/ +#ifdef CONFIG_MM_USER_HEAP void sched_ufree(FAR void *address) { irqstate_t flags; @@ -122,9 +123,9 @@ void sched_ufree(FAR void *address) kumm_givesemaphore(); } } +#endif -#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \ - defined(CONFIG_MM_KERNEL_HEAP) +#ifdef CONFIG_MM_KERNEL_HEAP void sched_kfree(FAR void *address) { irqstate_t flags;