diff --git a/arch/arm/include/armv7-a/irq.h b/arch/arm/include/armv7-a/irq.h index 612f4cbeae..46303c0160 100755 --- a/arch/arm/include/armv7-a/irq.h +++ b/arch/arm/include/armv7-a/irq.h @@ -293,7 +293,7 @@ struct xcptcontext * stack in place. */ - FAR uintptr_t *kstack; + FAR uint32_t *kstack; #endif #endif }; diff --git a/arch/arm/src/armv7-a/arm_addrenv.c b/arch/arm/src/armv7-a/arm_addrenv.c index fcc1eb1f15..d1ff06c526 100644 --- a/arch/arm/src/armv7-a/arm_addrenv.c +++ b/arch/arm/src/armv7-a/arm_addrenv.c @@ -58,9 +58,9 @@ * * up_addrenv_attach - Clone the address environment assigned to one TCB * to another. This operation is done when a pthread - * is created that share's the same address + * is created that share's the same group address * environment. - * up_addrenv_detach - Release the threads reference to an address + * up_addrenv_detach - Release the thread's reference to an address * environment when a task/thread exits. * * CONFIG_ARCH_STACK_DYNAMIC=y indicates that the user process stack resides @@ -84,6 +84,21 @@ * up_addrenv_vustack - Returns the virtual base address of the stack * up_addrenv_ustackselect - Instantiate a stack address environment * + * If CONFIG_ARCH_KERNEL_STACK is selected, then each user process will have + * two stacks: (1) a large (and possibly dynamic) user stack and (2) a + * smaller kernel stack. However, this option is *required* if both + * CONFIG_BUILD_KERNEL and CONFIG_LIBC_EXECFUNCS are selected. Why? Because + * when we instantiate and initialize the address environment of the new + * user process, we will temporarily lose the address environment of the old + * user process, including its stack contents. The kernel C logic will crash + * immediately with no valid stack in place. + * + * If CONFIG_ARCH_KERNEL_STACK=y is selected then the platform specific + * code must export these additional interfaces: + * + * up_addrenv_kstackalloc - Create a stack in the kernel address environment + * up_addrenv_kstackfree - Destroy the kernel stack. + * ****************************************************************************/ /**************************************************************************** diff --git a/arch/arm/src/armv7-a/arm_addrenv_kstack.c b/arch/arm/src/armv7-a/arm_addrenv_kstack.c new file mode 100644 index 0000000000..2102e0ad26 --- /dev/null +++ b/arch/arm/src/armv7-a/arm_addrenv_kstack.c @@ -0,0 +1,200 @@ +/**************************************************************************** + * arch/arm/src/armv7/arm_addrenv_kstack.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +/**************************************************************************** + * Address Environment Interfaces + * + * Low-level interfaces used in binfmt/ to instantiate tasks with address + * environments. These interfaces all operate on type group_addrenv_t which + * is an abstract representation of a task group's address environment and + * must be defined in arch/arch.h if CONFIG_ARCH_ADDRENV is defined. + * + * up_addrenv_create - Create an address environment + * up_addrenv_destroy - Destroy an address environment. + * up_addrenv_vtext - Returns the virtual base address of the .text + * address environment + * up_addrenv_vdata - Returns the virtual base address of the .bss/.data + * address environment + * up_addrenv_heapsize - Returns the size of the initial heap allocation. + * up_addrenv_select - Instantiate an address environment + * up_addrenv_restore - Restore an address environment + * up_addrenv_clone - Copy an address environment from one location to + * another. + * + * Higher-level interfaces used by the tasking logic. These interfaces are + * used by the functions in sched/ and all operate on the thread which whose + * group been assigned an address environment by up_addrenv_clone(). + * + * up_addrenv_attach - Clone the address environment assigned to one TCB + * to another. This operation is done when a pthread + * is created that share's the same group address + * environment. + * up_addrenv_detach - Release the thread's reference to an address + * environment when a task/thread exits. + * + * CONFIG_ARCH_STACK_DYNAMIC=y indicates that the user process stack resides + * in its own address space. This options is also *required* if + * CONFIG_BUILD_KERNEL and CONFIG_LIBC_EXECFUNCS are selected. Why? + * Because the caller's stack must be preserved in its own address space + * when we instantiate the environment of the new process in order to + * initialize it. + * + * NOTE: The naming of the CONFIG_ARCH_STACK_DYNAMIC selection implies that + * dynamic stack allocation is supported. Certainly this option must be set + * if dynamic stack allocation is supported by a platform. But the more + * general meaning of this configuration environment is simply that the + * stack has its own address space. + * + * If CONFIG_ARCH_STACK_DYNAMIC=y is selected then the platform specific + * code must export these additional interfaces: + * + * up_addrenv_ustackalloc - Create a stack address environment + * up_addrenv_ustackfree - Destroy a stack address environment. + * up_addrenv_vustack - Returns the virtual base address of the stack + * up_addrenv_ustackselect - Instantiate a stack address environment + * + * If CONFIG_ARCH_KERNEL_STACK is selected, then each user process will have + * two stacks: (1) a large (and possibly dynamic) user stack and (2) a + * smaller kernel stack. However, this option is *required* if both + * CONFIG_BUILD_KERNEL and CONFIG_LIBC_EXECFUNCS are selected. Why? Because + * when we instantiate and initialize the address environment of the new + * user process, we will temporarily lose the address environment of the old + * user process, including its stack contents. The kernel C logic will crash + * immediately with no valid stack in place. + * + * If CONFIG_ARCH_KERNEL_STACK=y is selected then the platform specific + * code must export these additional interfaces: + * + * up_addrenv_kstackalloc - Create a stack in the kernel address environment + * up_addrenv_kstackfree - Destroy the kernel stack. + * up_addrenv_vkstack - Return the base address of the kernel stack + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_addrenv_kstackalloc + * + * Description: + * This function is called when a new thread is created to allocate + * the new thread's kernel stack. + * + * Input Parameters: + * tcb - The TCB of the thread that requires the kernel stack. + * stacksize - The size (in bytes) of the kernel stack needed by the + * thread. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int up_addrenv_kstackalloc(FAR struct tcb_s *tcb, size_t stacksize) +{ + bvdbg("tcb=%p stacksize=%lu\n", tcb, (unsigned long)stacksize); + + DEBUGASSERT(tcb && tcb->xcp.kstack == 0 && stackize > 0); + + /* Allocate the kernel stack */ + + tcb->xcp.kstack = (FAR uint32_t *)kmm_memalign(8, stacksize); + if (!tcb->xcp.kstack) + { + bdbg("ERROR: Failed to allocate the kernel stack\n"); + return -ENOMEM; + } + + return OK; +} + +/**************************************************************************** + * Name: up_addrenv_kstackfree + * + * Description: + * This function is called when any thread exits. This function frees + * the kernel stack. + * + * Input Parameters: + * tcb - The TCB of the thread that no longer requires the kernel stack. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int up_addrenv_kstackfree(FAR struct tcb_s *tcb) +{ + bvdbg("tcb=%p\n", tcb); + DEBUGASSERT(tcb && tcb->xcp.kstack); + + /* Free the kernel stack */ + + kmm_free(tcb->xcp.kstack); + tcb->xcp.kstack = NULL; + return OK; +} + +#endif /* CONFIG_ARCH_ADDRENV && CONFIG_ARCH_KERNEL_STACK */ diff --git a/arch/arm/src/armv7-a/arm_addrenv_ustack.c b/arch/arm/src/armv7-a/arm_addrenv_ustack.c index e30dfa4e37..02bc18ceaa 100644 --- a/arch/arm/src/armv7-a/arm_addrenv_ustack.c +++ b/arch/arm/src/armv7-a/arm_addrenv_ustack.c @@ -76,7 +76,7 @@ * general meaning of this configuration environment is simply that the * stack has its own address space. * - * If CONFIG_ARCH_STACK_DYNAMIC=y is selected then the platform specific + * If CONFIG_ARCH_KERNEL_STACK=y is selected then the platform specific * code must export these additional interfaces: * * up_addrenv_ustackalloc - Create a stack address environment @@ -214,7 +214,7 @@ int up_addrenv_ustackfree(FAR struct tcb_s *tcb) * Name: up_addrenv_vustack * * Description: - * Return the virtual address associated with the newly create stack + * Return the virtual address associated with the newly created stack * address environment. * * Input Parameters: @@ -285,4 +285,4 @@ int up_addrenv_ustackselect(FAR const struct tcb_s *tcb) return OK; } -#endif /* CONFIG_ARCH_ADDRENV */ +#endif /* CONFIG_ARCH_ADDRENV && CONFIG_ARCH_STACK_DYNAMIC */