diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-09-14 09:53:54 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-09-14 09:53:54 -0600 |
commit | def9063a49cb5c309b03ad0dcd858d71a31a0ad5 (patch) | |
tree | db1a6538db4823142b5e4ca2817f64e06f163a78 | |
parent | 659cb309b3e0dde2ce2f69320569bcd3ebda93af (diff) | |
download | nuttx-def9063a49cb5c309b03ad0dcd858d71a31a0ad5.tar.gz nuttx-def9063a49cb5c309b03ad0dcd858d71a31a0ad5.tar.bz2 nuttx-def9063a49cb5c309b03ad0dcd858d71a31a0ad5.zip |
Add the initial implementation of the process kernel stack logic. Not yet integrated into the main OS logic nor tested.
-rw-r--r-- | nuttx/Documentation/NuttxPortingGuide.html | 68 | ||||
-rwxr-xr-x | nuttx/arch/arm/include/armv7-a/irq.h | 2 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-a/arm_addrenv.c | 19 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-a/arm_addrenv_kstack.c | 200 | ||||
-rw-r--r-- | nuttx/arch/arm/src/armv7-a/arm_addrenv_ustack.c | 6 | ||||
-rw-r--r-- | nuttx/include/nuttx/addrenv.h | 15 | ||||
-rw-r--r-- | nuttx/include/nuttx/arch.h | 55 |
7 files changed, 357 insertions, 8 deletions
diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index 279bb57f0..0a336ec00 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -12,7 +12,7 @@ <h1><big><font color="#3c34ec"> <i>NuttX RTOS Porting Guide</i> </font></big></h1> - <p>Last Updated: September 13, 2014</p> + <p>Last Updated: September 14, 2014</p> </td> </tr> </table> @@ -119,7 +119,9 @@ <a href="#up_addrenv_ustackalloc">4.4.11 <code>up_addrenv_ustackalloc()</code></a></br> <a href="#up_addrenv_ustackfree">4.4.12 <code>up_addrenv_ustackfree()</code></a></br> <a href="#up_addrenv_vustack">4.4.13 <code>up_addrenv_vustack()</code></a></br> - <a href="#up_addrenv_ustackselect">4.4.14 <code>up_addrenv_ustackselect()</code></a> + <a href="#up_addrenv_ustackselect">4.4.14 <code>up_addrenv_ustackselect()</code></a></br> + <a href="#up_addrenv_kstackalloc">4.4.15 <code>up_addrenv_kstackalloc()</code></a></br> + <a href="#up_addrenv_kstackfree">4.4.16 <code>up_addrenv_kstackfree()</code></a> </ul> <a href="#exports">4.5 APIs Exported by NuttX to Architecture-Specific Logic</a> <ul> @@ -2987,15 +2989,36 @@ VxWorks provides the following comparable interface: <li> <a href="#up_addrenv_ustackalloc">4.4.11 <code>up_addrenv_ustackalloc()</code></a>: Create a stack address environment + </li> <li> <a href="#up_addrenv_ustackfree">4.4.12 <code>up_addrenv_ustackfree()</code></a>: Destroy a stack address environment. + </li> <li> <a href="#up_addrenv_vustack">4.4.13 <code>up_addrenv_vustack()</code></a>: Returns the virtual base address of the stack + </li> <li> <a href="#up_addrenv_ustackselect">4.4.14 <code>up_addrenv_ustackselect()</code></a>: Instantiate a stack address environment + </li> + </ul> + </li> + <li> + <p> + If <code>CONFIG_ARCH_KERNEL_STACK</code> 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 <i>required</i> if both <code>CONFIG_BUILD_KERNEL</code> and <code>CONFIG_LIBC_EXECFUNCS</code> 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. + </p> + <p> + If <code>CONFIG_ARCH_KERNEL_STACK=y</code> is selected then the platform specific code must export these additional interfaces: + </p> + <ul> + <li> + <a href="#up_addrenv_kstackalloc">4.4.15 <code>up_addrenv_kstackalloc()</code></a>: + Allocate the process kernel stack. + </li> + <a href="#up_addrenv_kstackfree">4.4.16 <code>up_addrenv_kstackfree()</code></a>: + Free the process kernel stack. + </li> </ul> </li> </ol> @@ -3294,6 +3317,47 @@ VxWorks provides the following comparable interface: Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. </ul> +<h3><a name="up_addrenv_kstackalloc">4.4.15 <code>up_addrenv_kstackalloc()</code></a></h3> +<p><b>Function Prototype</b>:<p> +<ul> + <code>int up_addrenv_kstackalloc(FAR struct tcb_s *tcb, size_t stacksize);</code> +</ul> +<p><b>Description</b>:</p> +<ul> + <p> + This function is called when a new thread is created to allocate the new thread's kernel stack. + </p> +</ul> +<p><b>Input Parameters</b>:</p> +<ul> + <li><code>tcb</code>: The TCB of the thread that requires the kernel stack.</li> + <li><code>stacksize</code>: The size (in bytes) of the kernel stack needed by the thread.</li> +</ul> +<p><b>Returned Value</b>:</p> +<ul> + Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. +</ul> + +<h3><a name="up_addrenv_kstackfree">4.4.16 <code>up_addrenv_kstackfree()</code></a></h3> +<p><b>Function Prototype</b>:<p> +<ul> + <code>int up_addrenv_kstackfree(FAR struct tcb_s *tcb);</code> +</ul> +<p><b>Description</b>:</p> +<ul> + <p> + This function is called when any thread exits. This function frees the kernel stack. + </p> +</ul> +<p><b>Input Parameters</b>:</p> +<ul> + <li><code>tcb</code>: The TCB of the thread that no longer requires the kernel stack.</li> +</ul> +<p><b>Returned Value</b>:</p> +<ul> + Zero (<code>OK</code>) on success; a negated <code>errno</code> value on failure. +</ul> + <h2><a name="exports">4.5 APIs Exported by NuttX to Architecture-Specific Logic</a></h2> <p> These are standard interfaces that are exported by the OS diff --git a/nuttx/arch/arm/include/armv7-a/irq.h b/nuttx/arch/arm/include/armv7-a/irq.h index 612f4cbea..46303c016 100755 --- a/nuttx/arch/arm/include/armv7-a/irq.h +++ b/nuttx/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/nuttx/arch/arm/src/armv7-a/arm_addrenv.c b/nuttx/arch/arm/src/armv7-a/arm_addrenv.c index fcc1eb1f1..d1ff06c52 100644 --- a/nuttx/arch/arm/src/armv7-a/arm_addrenv.c +++ b/nuttx/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/nuttx/arch/arm/src/armv7-a/arm_addrenv_kstack.c b/nuttx/arch/arm/src/armv7-a/arm_addrenv_kstack.c new file mode 100644 index 000000000..2102e0ad2 --- /dev/null +++ b/nuttx/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 <gnutt@nuttx.org> + * + * 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 <nuttx/config.h> + +#include <errno.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/sched.h> +#include <nuttx/kmalloc.h> +#include <nuttx/addrenv.h> +#include <nuttx/arch.h> + +#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/nuttx/arch/arm/src/armv7-a/arm_addrenv_ustack.c b/nuttx/arch/arm/src/armv7-a/arm_addrenv_ustack.c index e30dfa4e3..02bc18cea 100644 --- a/nuttx/arch/arm/src/armv7-a/arm_addrenv_ustack.c +++ b/nuttx/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 */ diff --git a/nuttx/include/nuttx/addrenv.h b/nuttx/include/nuttx/addrenv.h index ac5dce56e..77c7463a6 100644 --- a/nuttx/include/nuttx/addrenv.h +++ b/nuttx/include/nuttx/addrenv.h @@ -303,6 +303,21 @@ struct addrenv_reserve_s * 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_STACK_DYNAMIC=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. + * ****************************************************************************/ /* Prototyped in include/nuttx/arch.h as part of the OS/platform interface */ diff --git a/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h index 7199b836b..d4b55d841 100644 --- a/nuttx/include/nuttx/arch.h +++ b/nuttx/include/nuttx/arch.h @@ -768,6 +768,21 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages); * 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. + * ****************************************************************************/ /**************************************************************************** * Name: up_addrenv_create @@ -1132,6 +1147,46 @@ int up_addrenv_ustackselect(FAR const struct tcb_s *tcb); #endif /**************************************************************************** + * 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. + * + ****************************************************************************/ + +#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK) +int up_addrenv_kstackalloc(FAR struct tcb_s *tcb, size_t stacksize); +#endif + +/**************************************************************************** + * 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. + * + ****************************************************************************/ + +#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK) +int up_addrenv_kstackfree(FAR struct tcb_s *tcb); +#endif + +/**************************************************************************** * Name: up_interrupt_context * * Description: |