Initial integration of kernel stack (does not work)
This commit is contained in:
parent
25ee232fd4
commit
3649dab9bd
@ -3320,18 +3320,19 @@ VxWorks provides the following comparable interface:
|
|||||||
<h3><a name="up_addrenv_kstackalloc">4.4.15 <code>up_addrenv_kstackalloc()</code></a></h3>
|
<h3><a name="up_addrenv_kstackalloc">4.4.15 <code>up_addrenv_kstackalloc()</code></a></h3>
|
||||||
<p><b>Function Prototype</b>:<p>
|
<p><b>Function Prototype</b>:<p>
|
||||||
<ul>
|
<ul>
|
||||||
<code>int up_addrenv_kstackalloc(FAR struct tcb_s *tcb, size_t stacksize);</code>
|
<code>int up_addrenv_kstackalloc(FAR struct tcb_s *tcb);</code>
|
||||||
</ul>
|
</ul>
|
||||||
<p><b>Description</b>:</p>
|
<p><b>Description</b>:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<p>
|
<p>
|
||||||
This function is called when a new thread is created to allocate the new thread's kernel stack.
|
This function is called when a new thread is created to allocate 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.
|
||||||
</p>
|
</p>
|
||||||
</ul>
|
</ul>
|
||||||
<p><b>Input Parameters</b>:</p>
|
<p><b>Input Parameters</b>:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>tcb</code>: The TCB of the thread that requires the kernel stack.</li>
|
<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>
|
</ul>
|
||||||
<p><b>Returned Value</b>:</p>
|
<p><b>Returned Value</b>:</p>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -276,7 +276,7 @@ struct xcptcontext
|
|||||||
|
|
||||||
#ifdef CONFIG_ARCH_ADDRENV
|
#ifdef CONFIG_ARCH_ADDRENV
|
||||||
#ifdef CONFIG_ARCH_STACK_DYNAMIC
|
#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
|
* 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
|
* zeroed and would be back-up up with pages during page fault exception
|
||||||
* handling to support dynamically sized stacks for each thread.
|
* handling to support dynamically sized stacks for each thread.
|
||||||
@ -284,6 +284,7 @@ struct xcptcontext
|
|||||||
|
|
||||||
FAR uintptr_t *ustack[ARCH_STACK_NSECTS];
|
FAR uintptr_t *ustack[ARCH_STACK_NSECTS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||||
/* In this configuration, all syscalls execute from an internal kernel
|
/* In this configuration, all syscalls execute from an internal kernel
|
||||||
* stack. Why? Because when we instantiate and initialize the address
|
* stack. Why? Because when we instantiate and initialize the address
|
||||||
@ -293,7 +294,8 @@ struct xcptcontext
|
|||||||
* stack in place.
|
* 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
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -51,6 +51,12 @@
|
|||||||
* Pre-processor Definitions
|
* 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
|
/* Using a 4KiB page size, each 1MiB section maps to a PTE containing
|
||||||
* 256*2KiB entries
|
* 256*2KiB entries
|
||||||
*/
|
*/
|
||||||
|
@ -117,6 +117,8 @@
|
|||||||
#include <nuttx/addrenv.h>
|
#include <nuttx/addrenv.h>
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
|
|
||||||
|
#include "addrenv.h"
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK)
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -140,27 +142,27 @@
|
|||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This function is called when a new thread is created to allocate
|
* 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:
|
* Input Parameters:
|
||||||
* tcb - The TCB of the thread that requires the kernel stack.
|
* 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:
|
* Returned Value:
|
||||||
* Zero (OK) on success; a negated errno value on failure.
|
* 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 */
|
/* 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)
|
if (!tcb->xcp.kstack)
|
||||||
{
|
{
|
||||||
bdbg("ERROR: Failed to allocate the kernel stack\n");
|
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)
|
int up_addrenv_kstackfree(FAR struct tcb_s *tcb)
|
||||||
{
|
{
|
||||||
bvdbg("tcb=%p\n", 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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
#include "svcall.h"
|
#include "svcall.h"
|
||||||
|
#include "addrenv.h"
|
||||||
#include "up_internal.h"
|
#include "up_internal.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -219,13 +220,27 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||||||
#ifdef CONFIG_BUILD_KERNEL
|
#ifdef CONFIG_BUILD_KERNEL
|
||||||
regs[REG_CPSR] = rtcb->xcp.syscall[index].cpsr;
|
regs[REG_CPSR] = rtcb->xcp.syscall[index].cpsr;
|
||||||
#endif
|
#endif
|
||||||
rtcb->xcp.nsyscalls = index;
|
|
||||||
|
|
||||||
/* The return value must be in R0-R1. dispatch_syscall() temporarily
|
/* The return value must be in R0-R1. dispatch_syscall() temporarily
|
||||||
* moved the value for R0 into R2.
|
* moved the value for R0 into R2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
regs[REG_R0] = regs[REG_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;
|
break;
|
||||||
|
|
||||||
@ -421,7 +436,6 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||||||
#ifdef CONFIG_BUILD_KERNEL
|
#ifdef CONFIG_BUILD_KERNEL
|
||||||
rtcb->xcp.syscall[index].cpsr = regs[REG_CPSR];
|
rtcb->xcp.syscall[index].cpsr = regs[REG_CPSR];
|
||||||
#endif
|
#endif
|
||||||
rtcb->xcp.nsyscalls = index + 1;
|
|
||||||
|
|
||||||
regs[REG_PC] = (uint32_t)dispatch_syscall;
|
regs[REG_PC] = (uint32_t)dispatch_syscall;
|
||||||
#ifdef CONFIG_BUILD_KERNEL
|
#ifdef CONFIG_BUILD_KERNEL
|
||||||
@ -434,6 +448,21 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||||||
#else
|
#else
|
||||||
svcdbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]);
|
svcdbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]);
|
||||||
#endif
|
#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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,8 @@ int exec_module(FAR const struct binary_s *binp)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
#ifdef CONFIG_ARCH_ADDRENV
|
||||||
|
#ifdef CONFIG_BUILD_KERNEL
|
||||||
/* Instantiate the address environment containing the user heap */
|
/* Instantiate the address environment containing the user heap */
|
||||||
|
|
||||||
ret = up_addrenv_select(&binp->addrenv, &oldenv);
|
ret = up_addrenv_select(&binp->addrenv, &oldenv);
|
||||||
@ -182,6 +183,19 @@ int exec_module(FAR const struct binary_s *binp)
|
|||||||
up_addrenv_heapsize(&binp->addrenv));
|
up_addrenv_heapsize(&binp->addrenv));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||||
|
/* Allocate the kernel stack */
|
||||||
|
|
||||||
|
ret = up_addrenv_kstackalloc(&tcb->cmn);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
bdbg("ERROR: up_addrenv_select() failed: %d\n", ret);
|
||||||
|
err = -ret;
|
||||||
|
goto errout_with_addrenv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Allocate the stack for the new task.
|
/* Allocate the stack for the new task.
|
||||||
*
|
*
|
||||||
* REVISIT: This allocation is currently always from the user heap. That
|
* REVISIT: This allocation is currently always from the user heap. That
|
||||||
@ -192,7 +206,7 @@ int exec_module(FAR const struct binary_s *binp)
|
|||||||
if (!stack)
|
if (!stack)
|
||||||
{
|
{
|
||||||
err = ENOMEM;
|
err = ENOMEM;
|
||||||
goto errout_with_addrenv;
|
goto errout_with_kstack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the task */
|
/* Initialize the task */
|
||||||
@ -203,7 +217,7 @@ int exec_module(FAR const struct binary_s *binp)
|
|||||||
{
|
{
|
||||||
err = get_errno();
|
err = get_errno();
|
||||||
bdbg("task_init() failed: %d\n", err);
|
bdbg("task_init() failed: %d\n", err);
|
||||||
goto errout_with_stack;
|
goto errout_with_kstack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that tcb->flags are not modified. 0=normal task */
|
/* Note that tcb->flags are not modified. 0=normal task */
|
||||||
@ -229,7 +243,7 @@ int exec_module(FAR const struct binary_s *binp)
|
|||||||
{
|
{
|
||||||
err = -ret;
|
err = -ret;
|
||||||
bdbg("ERROR: up_addrenv_clone() failed: %d\n", ret);
|
bdbg("ERROR: up_addrenv_clone() failed: %d\n", ret);
|
||||||
goto errout_with_stack;
|
goto errout_with_tcbinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark that this group has an address environment */
|
/* Mark that this group has an address environment */
|
||||||
@ -257,7 +271,7 @@ int exec_module(FAR const struct binary_s *binp)
|
|||||||
{
|
{
|
||||||
err = get_errno();
|
err = get_errno();
|
||||||
bdbg("task_activate() failed: %d\n", err);
|
bdbg("task_activate() failed: %d\n", err);
|
||||||
goto errout_with_stack;
|
goto errout_with_tcbinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||||
@ -268,24 +282,31 @@ int exec_module(FAR const struct binary_s *binp)
|
|||||||
{
|
{
|
||||||
bdbg("ERROR: up_addrenv_select() failed: %d\n", ret);
|
bdbg("ERROR: up_addrenv_select() failed: %d\n", ret);
|
||||||
err = -ret;
|
err = -ret;
|
||||||
goto errout_with_stack;
|
goto errout_with_tcbinit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (int)pid;
|
return (int)pid;
|
||||||
|
|
||||||
errout_with_stack:
|
errout_with_tcbinit:
|
||||||
tcb->cmn.stack_alloc_ptr = NULL;
|
tcb->cmn.stack_alloc_ptr = NULL;
|
||||||
sched_releasetcb(&tcb->cmn, TCB_FLAG_TTYPE_TASK);
|
sched_releasetcb(&tcb->cmn, TCB_FLAG_TTYPE_TASK);
|
||||||
kumm_free(stack);
|
kumm_free(stack);
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
||||||
|
errout_with_kstack:
|
||||||
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||||
|
(void)up_addrenv_kstackfree(tcb);
|
||||||
|
|
||||||
errout_with_addrenv:
|
errout_with_addrenv:
|
||||||
|
#endif
|
||||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||||
(void)up_addrenv_restore(&oldenv);
|
(void)up_addrenv_restore(&oldenv);
|
||||||
|
|
||||||
errout_with_tcb:
|
errout_with_tcb:
|
||||||
#endif
|
#endif
|
||||||
kmm_free(tcb);
|
kmm_free(tcb);
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
set_errno(err);
|
set_errno(err);
|
||||||
bdbg("returning errno: %d\n", err);
|
bdbg("returning errno: %d\n", err);
|
||||||
|
@ -1151,7 +1151,9 @@ int up_addrenv_ustackselect(FAR const struct tcb_s *tcb);
|
|||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This function is called when a new thread is created to allocate
|
* 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:
|
* Input Parameters:
|
||||||
* tcb - The TCB of the thread that requires the kernel stack.
|
* tcb - The TCB of the thread that requires the kernel stack.
|
||||||
@ -1164,7 +1166,7 @@ int up_addrenv_ustackselect(FAR const struct tcb_s *tcb);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK)
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK)
|
||||||
int up_addrenv_kstackalloc(FAR struct tcb_s *tcb, size_t stacksize);
|
int up_addrenv_kstackalloc(FAR struct tcb_s *tcb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -114,13 +114,13 @@ int sched_releasetcb(FAR struct tcb_s *tcb, uint8_t ttype)
|
|||||||
|
|
||||||
if (tcb)
|
if (tcb)
|
||||||
{
|
{
|
||||||
/* Relase any timers that the task might hold. We do this
|
#ifndef CONFIG_DISABLE_POSIX_TIMERS
|
||||||
|
/* Release any timers that the task might hold. We do this
|
||||||
* before release the PID because it may still be trying to
|
* before release the PID because it may still be trying to
|
||||||
* deliver signals (although interrupts are should be
|
* deliver signals (although interrupts are should be
|
||||||
* disabled here).
|
* disabled here).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_POSIX_TIMERS
|
|
||||||
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
|
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
|
||||||
if (timer_deleteall != NULL)
|
if (timer_deleteall != NULL)
|
||||||
#endif
|
#endif
|
||||||
@ -147,9 +147,9 @@ int sched_releasetcb(FAR struct tcb_s *tcb, uint8_t ttype)
|
|||||||
up_release_stack(tcb, ttype);
|
up_release_stack(tcb, ttype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PIC
|
||||||
/* Delete the task's allocated DSpace region (external modules only) */
|
/* Delete the task's allocated DSpace region (external modules only) */
|
||||||
|
|
||||||
#ifdef CONFIG_PIC
|
|
||||||
if (tcb->dspace)
|
if (tcb->dspace)
|
||||||
{
|
{
|
||||||
if (tcb->dspace->crefs <= 1)
|
if (tcb->dspace->crefs <= 1)
|
||||||
@ -163,6 +163,12 @@ int sched_releasetcb(FAR struct tcb_s *tcb, uint8_t ttype)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_KERNEL_STACK)
|
||||||
|
/* Release the kernel stack */
|
||||||
|
|
||||||
|
(void)up_addrenv_kstackfree(tcb);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Release this thread's reference to the address environment */
|
/* Release this thread's reference to the address environment */
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_ADDRENV
|
#ifdef CONFIG_ARCH_ADDRENV
|
||||||
|
Loading…
x
Reference in New Issue
Block a user