diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html
index 9ebccab1b2e..279bb57f0f0 100644
--- a/Documentation/NuttxPortingGuide.html
+++ b/Documentation/NuttxPortingGuide.html
@@ -116,10 +116,10 @@
4.4.8 up_addrenv_clone()
4.4.9 up_addrenv_attach()
4.4.10 up_addrenv_detach()
- 4.4.11 up_addrenv_stackalloc()
- 4.4.12 up_addrenv_stackfree()
- 4.4.13 up_addrenv_vstack()
- 4.4.14 up_addrenv_stackselect()
+ 4.4.11 up_addrenv_ustackalloc()
+ 4.4.12 up_addrenv_ustackfree()
+ 4.4.13 up_addrenv_vustack()
+ 4.4.14 up_addrenv_ustackselect()
4.5 APIs Exported by NuttX to Architecture-Specific Logic
@@ -2985,16 +2985,16 @@ VxWorks provides the following comparable interface:
@@ -3208,16 +3208,16 @@ VxWorks provides the following comparable interface:
Zero (OK) on success; a negated errno value on failure.
-
+
Function Prototype:
- int up_addrenv_stackalloc(FAR struct tcb_s *tcb, size_t stacksize);
+ int up_addrenv_ustackalloc(FAR struct tcb_s *tcb, size_t stacksize);
Description:
This function is called when a new thread is created in order to instantiate an address environment for the new thread's stack.
- up_addrenv_stackalloc() is essentially the allocator of the physical memory for the new task's stack.
+ up_addrenv_ustackalloc() is essentially the allocator of the physical memory for the new task's stack.
Input Parameters:
@@ -3230,10 +3230,10 @@ VxWorks provides the following comparable interface:
Zero (OK) on success; a negated errno value on failure.
-
+
Function Prototype:
- int up_addrenv_stackfree(FAR struct tcb_s *tcb);
+ int up_addrenv_ustackfree(FAR struct tcb_s *tcb);
Description:
@@ -3251,10 +3251,10 @@ VxWorks provides the following comparable interface:
Zero (OK) on success; a negated errno value on failure.
-
+
Function Prototype:
- int up_addrenv_vstack(FAR const struct tcb_s *tcb, FAR void **vstack);
+ int up_addrenv_vustack(FAR const struct tcb_s *tcb, FAR void **vstack);
Description:
@@ -3272,15 +3272,15 @@ VxWorks provides the following comparable interface:
Zero (OK) on success; a negated errno value on failure.
-
+
Function Prototype:
- int up_addrenv_stackselect(FAR const struct tcb_s *tcb);
+ int up_addrenv_ustackselect(FAR const struct tcb_s *tcb);
Description:
- After an address environment has been established for a task's stack (via up_addrenv_stackalloc().
+ After an address environment has been established for a task's stack (via up_addrenv_ustackalloc().
This function may be called to instantiate that address environment in the virtual address space.
This is a necessary step before each context switch to the newly created thread (including the initial thread startup).
diff --git a/arch/Kconfig b/arch/Kconfig
index 76daa181001..e552869e448 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -224,10 +224,9 @@ config ARCH_HEAP_NPAGES
the heap virtual address space. Default is 1.
config ARCH_STACK_DYNAMIC
- bool "Dynamic stack"
- default n if !BUILD_KERNEL || !LIBC_EXECFUNCS
- default y if BUILD_KERNEL && LIBC_EXECFUNCS
- depends on EXPERIMENTAL
+ bool "Dynamic user stack"
+ default n
+ depends on BUILD_KERNEL && EXPERIMENTAL
---help---
Select this option if the user process stack resides in its own
address space. The naming of this selection implies that dynamic
@@ -236,10 +235,9 @@ config ARCH_STACK_DYNAMIC
general meaning of this configuration environment is simply that the
stack has its own address space.
- NOTE: This option is also *required* if BUILD_KERNEL and
- 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: This option not yet fully implemented in the code base.
+ Hence, it is marked EXPERIMENTAL: Do not enable it unless you plan
+ finish the implementation.
if ARCH_STACK_DYNAMIC
@@ -258,6 +256,39 @@ config ARCH_STACK_NPAGES
endif # ARCH_STACK_DYNAMIC
+config ARCH_KERNEL_STACK
+ bool "Kernel process stack"
+ default n if !LIBC_EXECFUNCS
+ default y if LIBC_EXECFUNCS
+ depends on BUILD_KERNEL
+ ---help---
+ It this option is selected, then every user process will have two
+ stacks: A large, potentially dynamically sized user stack and small
+ kernel stack that is used during system call process.
+
+ If this option is not selected, then kernel system calls will simply
+ use the caller's user stack. So, in most cases, this option is not
+ required. However, this option is *required* if both BUILD_KERNEL
+ and 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.
+
+ When this option is selected, the smaller kernel stack stays in
+ place during system call processing event though the original user
+ stack may or may not be accessible.
+
+if ARCH_KERNEL_STACK
+
+config ARCH_KERNEL_STACKSIZE
+ int "Kernel stack size"
+ default 1568
+ ---help---
+ The common size of each process' kernel stack
+
+endif # ARCH_KERNEL_STACK
+
config ARCH_PGPOOL_MAPPING
bool "Have page pool mapping"
default n
diff --git a/arch/arm/include/armv7-a/irq.h b/arch/arm/include/armv7-a/irq.h
index f9d5225b3a4..612f4cbeaed 100755
--- a/arch/arm/include/armv7-a/irq.h
+++ b/arch/arm/include/armv7-a/irq.h
@@ -274,14 +274,27 @@ struct xcptcontext
struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST];
#endif
-#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_STACK_DYNAMIC)
+#ifdef CONFIG_ARCH_ADDRENV
+#ifdef CONFIG_ARCH_STACK_DYNAMIC
/* This table holds the physical address of the level 2 page table used
* to map the thread's stack memory. This array will be initially of
* zeroed and would be back-up up with pages during page fault exception
* handling to support dynamically sized stacks for each thread.
*/
- FAR uintptr_t *stack[ARCH_STACK_NSECTS];
+ FAR uintptr_t *ustack[ARCH_STACK_NSECTS];
+#endif
+#ifdef CONFIG_ARCH_KERNEL_STACK
+ /* In this configuration, all syscalls execute from an internal kernel
+ * stack. 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.
+ */
+
+ FAR uintptr_t *kstack;
+#endif
#endif
};
#endif
diff --git a/arch/arm/src/a1x/Make.defs b/arch/arm/src/a1x/Make.defs
index 22f50654468..d7d5dfbc45a 100644
--- a/arch/arm/src/a1x/Make.defs
+++ b/arch/arm/src/a1x/Make.defs
@@ -93,7 +93,10 @@ endif
ifeq ($(CONFIG_ARCH_ADDRENV),y)
CMN_CSRCS += arm_addrenv.c arm_addrenv_utils.c arm_pgalloc.c
ifeq ($(CONFIG_ARCH_STACK_DYNAMIC),y)
-CMN_CSRCS += arm_addrenv_stack.c
+CMN_CSRCS += arm_addrenv_ustack.c
+endif
+ifeq ($(CONFIG_ARCH_KERNEL_STACK),y)
+CMN_CSRCS += arm_addrenv_kstack.c
endif
endif
diff --git a/arch/arm/src/armv7-a/arm_addrenv.c b/arch/arm/src/armv7-a/arm_addrenv.c
index 257a14a36ab..fcc1eb1f15a 100644
--- a/arch/arm/src/armv7-a/arm_addrenv.c
+++ b/arch/arm/src/armv7-a/arm_addrenv.c
@@ -79,10 +79,10 @@
* If CONFIG_ARCH_STACK_DYNAMIC=y is selected then the platform specific
* code must export these additional interfaces:
*
- * up_addrenv_stackalloc - Create a stack address environment
- * up_addrenv_stackfree - Destroy a stack address environment.
- * up_addrenv_vstack - Returns the virtual base address of the stack
- * up_addrenv_stackselect - Instantiate a stack address environment
+ * 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
*
****************************************************************************/
diff --git a/arch/arm/src/armv7-a/arm_addrenv_stack.c b/arch/arm/src/armv7-a/arm_addrenv_ustack.c
similarity index 88%
rename from arch/arm/src/armv7-a/arm_addrenv_stack.c
rename to arch/arm/src/armv7-a/arm_addrenv_ustack.c
index 225906f8179..e30dfa4e37b 100644
--- a/arch/arm/src/armv7-a/arm_addrenv_stack.c
+++ b/arch/arm/src/armv7-a/arm_addrenv_ustack.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * arch/arm/src/armv7/arm_addrenv_stack.c
+ * arch/arm/src/armv7/arm_addrenv_ustack.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt
@@ -79,10 +79,10 @@
* If CONFIG_ARCH_STACK_DYNAMIC=y is selected then the platform specific
* code must export these additional interfaces:
*
- * up_addrenv_stackalloc - Create a stack address environment
- * up_addrenv_stackfree - Destroy a stack address environment.
- * up_addrenv_vstack - Returns the virtual base address of the stack
- * up_addrenv_stackselect - Instantiate a stack address environment
+ * 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
*
****************************************************************************/
@@ -129,12 +129,12 @@
****************************************************************************/
/****************************************************************************
- * Name: up_addrenv_stackalloc
+ * Name: up_addrenv_ustackalloc
*
* Description:
* This function is called when a new thread is created in order to
* instantiate an address environment for the new thread's stack.
- * up_addrenv_stackalloc() is essentially the allocator of the physical
+ * up_addrenv_ustackalloc() is essentially the allocator of the physical
* memory for the new task's stack.
*
* Input Parameters:
@@ -147,7 +147,7 @@
*
****************************************************************************/
-int up_addrenv_stackalloc(FAR struct tcb_s *tcb, size_t stacksize)
+int up_addrenv_ustackalloc(FAR struct tcb_s *tcb, size_t stacksize)
{
int ret;
@@ -157,7 +157,7 @@ int up_addrenv_stackalloc(FAR struct tcb_s *tcb, size_t stacksize)
/* Initialize the address environment list to all zeroes */
- memset(tcb->xcp.stack, 0, ARCH_STACK_NSECTS * sizeof(uintptr_t *));
+ memset(tcb->xcp.ustack, 0, ARCH_STACK_NSECTS * sizeof(uintptr_t *));
/* Back the allocation up with physical pages and set up the level 2 mapping
* (which of course does nothing until the L2 page table is hooked into
@@ -166,13 +166,13 @@ int up_addrenv_stackalloc(FAR struct tcb_s *tcb, size_t stacksize)
/* Allocate .text space pages */
- ret = arm_addrenv_create_region(tcb->xcp.stack, ARCH_STACK_NSECTS,
+ ret = arm_addrenv_create_region(tcb->xcp.ustack, ARCH_STACK_NSECTS,
CONFIG_ARCH_STACK_VBASE, stacksize,
MMU_L2_UDATAFLAGS);
if (ret < 0)
{
bdbg("ERROR: Failed to create stack region: %d\n", ret);
- up_addrenv_stackfree(tcb);
+ up_addrenv_ustackfree(tcb);
return ret;
}
@@ -180,7 +180,7 @@ int up_addrenv_stackalloc(FAR struct tcb_s *tcb, size_t stacksize)
}
/****************************************************************************
- * Name: up_addrenv_stackfree
+ * Name: up_addrenv_ustackfree
*
* Description:
* This function is called when any thread exits. This function then
@@ -196,22 +196,22 @@ int up_addrenv_stackalloc(FAR struct tcb_s *tcb, size_t stacksize)
*
****************************************************************************/
-int up_addrenv_stackfree(FAR struct tcb_s *tcb)
+int up_addrenv_ustackfree(FAR struct tcb_s *tcb)
{
bvdbg("tcb=%p\n", tcb);
DEBUGASSERT(tcb);
/* Destroy the stack region */
- arm_addrenv_destroy_region(tcb->xcp.stack, ARCH_STACK_NSECTS,
+ arm_addrenv_destroy_region(tcb->xcp.ustack, ARCH_STACK_NSECTS,
CONFIG_ARCH_STACK_VBASE);
- memset(tcb->xcp.stack, 0, ARCH_STACK_NSECTS * sizeof(uintptr_t *));
+ memset(tcb->xcp.ustack, 0, ARCH_STACK_NSECTS * sizeof(uintptr_t *));
return OK;
}
/****************************************************************************
- * Name: up_addrenv_vstack
+ * Name: up_addrenv_vustack
*
* Description:
* Return the virtual address associated with the newly create stack
@@ -227,7 +227,7 @@ int up_addrenv_stackfree(FAR struct tcb_s *tcb)
*
****************************************************************************/
-int up_addrenv_vstack(FAR const struct tcb_s *tcb, FAR void **vstack)
+int up_addrenv_vustack(FAR const struct tcb_s *tcb, FAR void **vstack)
{
bvdbg("Return=%p\n", (FAR void *)CONFIG_ARCH_STACK_VBASE);
@@ -239,11 +239,11 @@ int up_addrenv_vstack(FAR const struct tcb_s *tcb, FAR void **vstack)
}
/****************************************************************************
- * Name: up_addrenv_stackselect
+ * Name: up_addrenv_ustackselect
*
* Description:
* After an address environment has been established for a task's stack
- * (via up_addrenv_stackalloc(). This function may be called to instantiate
+ * (via up_addrenv_ustackalloc(). This function may be called to instantiate
* that address environment in the virtual address space. This is a
* necessary step before each context switch to the newly created thread
* (including the initial thread startup).
@@ -257,7 +257,7 @@ int up_addrenv_vstack(FAR const struct tcb_s *tcb, FAR void **vstack)
*
****************************************************************************/
-int up_addrenv_stackselect(FAR const struct tcb_s *tcb)
+int up_addrenv_ustackselect(FAR const struct tcb_s *tcb)
{
uintptr_t vaddr;
uintptr_t paddr;
@@ -271,7 +271,7 @@ int up_addrenv_stackselect(FAR const struct tcb_s *tcb)
{
/* Set (or clear) the new page table entry */
- paddr = (uintptr_t)tcb->xcp.stack[i];
+ paddr = (uintptr_t)tcb->xcp.ustack[i];
if (paddr)
{
mmu_l1_setentry(paddr, vaddr, MMU_L1_PGTABFLAGS);
diff --git a/arch/arm/src/sama5/Make.defs b/arch/arm/src/sama5/Make.defs
index 59654e5e3cc..748ebf9870c 100644
--- a/arch/arm/src/sama5/Make.defs
+++ b/arch/arm/src/sama5/Make.defs
@@ -95,7 +95,10 @@ endif
ifeq ($(CONFIG_ARCH_ADDRENV),y)
CMN_CSRCS += arm_addrenv.c arm_addrenv_utils.c arm_pgalloc.c
ifeq ($(CONFIG_ARCH_STACK_DYNAMIC),y)
-CMN_CSRCS += arm_addrenv_stack.c
+CMN_CSRCS += arm_addrenv_ustack.c
+endif
+ifeq ($(CONFIG_ARCH_KERNEL_STACK),y)
+CMN_CSRCS += arm_addrenv_kstack.c
endif
endif
diff --git a/include/nuttx/addrenv.h b/include/nuttx/addrenv.h
index 936b7ee14cc..ac5dce56e6c 100644
--- a/include/nuttx/addrenv.h
+++ b/include/nuttx/addrenv.h
@@ -139,7 +139,7 @@
#define ARCH_HEAP_VEND (CONFIG_ARCH_HEAP_VBASE + ARCH_HEAP_SIZE)
#ifdef CONFIG_ARCH_STACK_DYNAMIC
- /* Stack region */
+ /* User stack region */
# ifndef CONFIG_ARCH_STACK_VBASE
# error CONFIG_ARCH_STACK_VBASE not defined
@@ -158,6 +158,14 @@
# define ARCH_STACK_SIZE (CONFIG_ARCH_STACK_NPAGES * CONFIG_MM_PGSIZE)
# define ARCH_STACK_VEND (CONFIG_ARCH_STACK_VBASE + ARCH_STACK_SIZE)
+#ifdef CONFIG_ARCH_KERNEL_STACK
+/* Kernel stack */
+
+# ifndef CONFIG_ARCH_KERNEL_STACKSIZE
+# define CONFIG_ARCH_KERNEL_STACKSIZE 1568
+# endif
+#endif
+
/* A single page scratch region used for temporary mappings */
# define ARCH_SCRATCH_VBASE ARCH_STACK_VEND
@@ -290,10 +298,10 @@ struct addrenv_reserve_s
* If CONFIG_ARCH_STACK_DYNAMIC=y is selected then the platform specific
* code must export these additional interfaces:
*
- * up_addrenv_stackalloc - Create a stack address environment
- * up_addrenv_stackfree - Destroy a stack address environment.
- * up_addrenv_vstack - Returns the virtual base address of the stack
- * up_addrenv_stackselect - Instantiate a stack address environment
+ * 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
*
****************************************************************************/
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index d626e230a6b..7199b836b42 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -763,10 +763,10 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages);
* If CONFIG_ARCH_STACK_DYNAMIC=y is selected then the platform specific
* code must export these additional interfaces:
*
- * up_addrenv_stackalloc - Create a stack address environment
- * up_addrenv_stackfree - Destroy a stack address environment.
- * up_addrenv_vstack - Returns the virtual base address of the stack
- * up_addrenv_stackselect - Instantiate a stack address environment
+ * 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
*
****************************************************************************/
/****************************************************************************
@@ -1044,12 +1044,12 @@ int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);
#endif
/****************************************************************************
- * Name: up_addrenv_stackalloc
+ * Name: up_addrenv_ustackalloc
*
* Description:
* This function is called when a new thread is created in order to
* instantiate an address environment for the new thread's stack.
- * up_addrenv_stackalloc() is essentially the allocator of the physical
+ * up_addrenv_ustackalloc() is essentially the allocator of the physical
* memory for the new task's stack.
*
* Input Parameters:
@@ -1063,11 +1063,11 @@ int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb);
****************************************************************************/
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_STACK_DYNAMIC)
-int up_addrenv_stackalloc(FAR struct tcb_s *tcb, size_t stacksize);
+int up_addrenv_ustackalloc(FAR struct tcb_s *tcb, size_t stacksize);
#endif
/****************************************************************************
- * Name: up_addrenv_stackfree
+ * Name: up_addrenv_ustackfree
*
* Description:
* This function is called when any thread exits. This function then
@@ -1084,11 +1084,11 @@ int up_addrenv_stackalloc(FAR struct tcb_s *tcb, size_t stacksize);
****************************************************************************/
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_STACK_DYNAMIC)
-int up_addrenv_stackfree(FAR struct tcb_s *tcb);
+int up_addrenv_ustackfree(FAR struct tcb_s *tcb);
#endif
/****************************************************************************
- * Name: up_addrenv_vstack
+ * Name: up_addrenv_vustack
*
* Description:
* Return the virtual address associated with the newly create stack
@@ -1105,15 +1105,15 @@ int up_addrenv_stackfree(FAR struct tcb_s *tcb);
****************************************************************************/
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_STACK_DYNAMIC)
-int up_addrenv_vstack(FAR const struct tcb_s *tcb, FAR void **vstack);
+int up_addrenv_vustack(FAR const struct tcb_s *tcb, FAR void **vstack);
#endif
/****************************************************************************
- * Name: up_addrenv_stackselect
+ * Name: up_addrenv_ustackselect
*
* Description:
* After an address environment has been established for a task's stack
- * (via up_addrenv_stackalloc(). This function may be called to instantiate
+ * (via up_addrenv_ustackalloc(). This function may be called to instantiate
* that address environment in the virtual address space. This is a
* necessary step before each context switch to the newly created thread
* (including the initial thread startup).
@@ -1128,7 +1128,7 @@ int up_addrenv_vstack(FAR const struct tcb_s *tcb, FAR void **vstack);
****************************************************************************/
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_STACK_DYNAMIC)
-int up_addrenv_stackselect(FAR const struct tcb_s *tcb);
+int up_addrenv_ustackselect(FAR const struct tcb_s *tcb);
#endif
/****************************************************************************
diff --git a/libc/spawn/lib_psa_init.c b/libc/spawn/lib_psa_init.c
index 815376e7b8b..afa993179a8 100644
--- a/libc/spawn/lib_psa_init.c
+++ b/libc/spawn/lib_psa_init.c
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/string/lib_psa_init.c
*
- * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt
*
* Redistribution and use in source and binary forms, with or without