Initial integration of kernel stack (does not work)

This commit is contained in:
Gregory Nutt 2014-09-14 11:19:34 -06:00
parent 16ddffc941
commit 946b916f69
4 changed files with 61 additions and 16 deletions

View File

@ -276,7 +276,7 @@ struct xcptcontext
#ifdef CONFIG_ARCH_ADDRENV
#ifdef CONFIG_ARCH_STACK_DYNAMIC
/* This table holds the physical address of the level 2 page table used
/* This array 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.
@ -284,6 +284,7 @@ struct xcptcontext
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
@ -293,7 +294,8 @@ struct xcptcontext
* stack in place.
*/
FAR uint32_t *kstack;
FAR uint32_t *ustkptr; /* Saved user stack pointer */
FAR uint32_t *kstack; /* Allocate base of the (aligned) kernel stack */
#endif
#endif
};

View File

@ -51,6 +51,12 @@
* Pre-processor Definitions
****************************************************************************/
/* Aligned size of the kernel stack */
#ifdef CONFIG_ARCH_KERNEL_STACK
# define ARCH_KERNEL_STACKSIZE ((CONFIG_ARCH_KERNEL_STACKSIZE + 7) & ~7)
#endif
/* Using a 4KiB page size, each 1MiB section maps to a PTE containing
* 256*2KiB entries
*/

View File

@ -117,6 +117,8 @@
#include <nuttx/addrenv.h>
#include <nuttx/arch.h>
#include "addrenv.h"
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK)
/****************************************************************************
@ -140,27 +142,27 @@
*
* Description:
* This function is called when a new thread is created to allocate
* the new thread's kernel stack.
* the new thread's kernel stack. This function may be called for certain
* terminating threads which have no kernel stack. It must be tolerant of
* that case.
*
* 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)
int up_addrenv_kstackalloc(FAR struct tcb_s *tcb)
{
bvdbg("tcb=%p stacksize=%lu\n", tcb, (unsigned long)stacksize);
bvdbg("tcb=%p stacksize=%u\n", tcb, ARCH_KERNEL_STACKSIZE);
DEBUGASSERT(tcb && tcb->xcp.kstack == 0 && stackize > 0);
DEBUGASSERT(tcb && tcb->xcp.kstack == 0);
/* Allocate the kernel stack */
tcb->xcp.kstack = (FAR uint32_t *)kmm_memalign(8, stacksize);
tcb->xcp.kstack = (FAR uint32_t *)kmm_memalign(8, ARCH_KERNEL_STACKSIZE);
if (!tcb->xcp.kstack)
{
bdbg("ERROR: Failed to allocate the kernel stack\n");
@ -188,12 +190,18 @@ int up_addrenv_kstackalloc(FAR struct tcb_s *tcb, size_t stacksize)
int up_addrenv_kstackfree(FAR struct tcb_s *tcb)
{
bvdbg("tcb=%p\n", tcb);
DEBUGASSERT(tcb && tcb->xcp.kstack);
DEBUGASSERT(tcb);
/* Free the kernel stack */
/* Does the exiting thread have a kernel stack? */
if (tcb->xcp.kstack)
{
/* Yes.. Free the kernel stack */
kmm_free(tcb->xcp.kstack);
tcb->xcp.kstack = NULL;
}
kmm_free(tcb->xcp.kstack);
tcb->xcp.kstack = NULL;
return OK;
}

View File

@ -51,6 +51,7 @@
#include "arm.h"
#include "svcall.h"
#include "addrenv.h"
#include "up_internal.h"
/****************************************************************************
@ -219,13 +220,27 @@ uint32_t *arm_syscall(uint32_t *regs)
#ifdef CONFIG_BUILD_KERNEL
regs[REG_CPSR] = rtcb->xcp.syscall[index].cpsr;
#endif
rtcb->xcp.nsyscalls = index;
/* The return value must be in R0-R1. dispatch_syscall() temporarily
* moved the value for R0 into R2.
*/
regs[REG_R0] = regs[REG_R2];
#ifdef CONFIG_ARCH_KERNEL_STACK
/* If this is the outermost SYSCALL and if there is a saved user stack
* pointer, then restore the user stack pointer on this final return to
* user code.
*/
if (index == 0 && rtcb->xcp.ustkptr != NULL)
{
regs[REG_SP] = (uint32_t)rtcb->xcp.ustkptr;
rtcb->xcp.ustkptr = NULL;
}
#endif
/* Save the new SYSCALL nesting level */
rtcb->xcp.nsyscalls = index;
}
break;
@ -421,7 +436,6 @@ uint32_t *arm_syscall(uint32_t *regs)
#ifdef CONFIG_BUILD_KERNEL
rtcb->xcp.syscall[index].cpsr = regs[REG_CPSR];
#endif
rtcb->xcp.nsyscalls = index + 1;
regs[REG_PC] = (uint32_t)dispatch_syscall;
#ifdef CONFIG_BUILD_KERNEL
@ -434,6 +448,21 @@ uint32_t *arm_syscall(uint32_t *regs)
#else
svcdbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]);
#endif
#ifdef CONFIG_ARCH_KERNEL_STACK
/* If this is the first SYSCALL and if there is an allocated
* kernel stack, then switch to the kernel stack.
*/
if (index == 0 && rtcb->xcp.kstack != NULL)
{
rtcb->xcp.ustkptr = (FAR uint32_t *)regs[REG_SP];
regs[REG_SP] = (uint32_t)rtcb->xcp.kstack + ARCH_KERNEL_STACKSIZE;
}
#endif
/* Save the new SYSCALL nesting level */
rtcb->xcp.nsyscalls = index + 1;
}
break;
}