This macro is slated for complete removal, as it's not possible on arches with an MPU stack guard to know the true buffer bounds without also knowing the runtime state of its associated thread. As removing this completely would be invasive to where we are in the 1.14 release, demote to a private kernel Z_ API instead. The current way that the macro is being used internally will not cause any undue harm, we just don't want any external code depending on it. The final work to remove this (and overhaul stack specification in general) will take place in 1.15 in the context of #14269 Fixes: #14766 Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
127 lines
3.7 KiB
C
127 lines
3.7 KiB
C
/*
|
|
* Copyright (c) 2016 Cadence Design Systems, Inc.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifdef CONFIG_INIT_STACKS
|
|
#include <string.h>
|
|
#endif /* CONFIG_INIT_STACKS */
|
|
#ifdef CONFIG_DEBUG
|
|
#include <misc/printk.h>
|
|
#endif
|
|
#include <kernel_structs.h>
|
|
#include <wait_q.h>
|
|
#include <xtensa_config.h>
|
|
#include <kernel_internal.h>
|
|
|
|
extern void z_xt_user_exit(void);
|
|
|
|
/*
|
|
* @brief Initialize a new thread
|
|
*
|
|
* Any coprocessor context data is put at the lower address of the stack. An
|
|
* initial context, to be "restored" by __return_from_coop(), is put at
|
|
* the other end of the stack, and thus reusable by the stack when not
|
|
* needed anymore.
|
|
*
|
|
* The initial context is a basic stack frame that contains arguments for
|
|
* z_thread_entry() return address, that points at z_thread_entry()
|
|
* and status register.
|
|
*
|
|
* <options> is currently unused.
|
|
*
|
|
* @param thread pointer to k_thread memory
|
|
* @param pStackmem the pointer to aligned stack memory
|
|
* @param stackSize the stack size in bytes
|
|
* @param pEntry thread entry point routine
|
|
* @param p1 first param to entry point
|
|
* @param p2 second param to entry point
|
|
* @param p3 third param to entry point
|
|
* @param priority thread priority
|
|
* @param options is unused (saved for future expansion)
|
|
*
|
|
* @return N/A
|
|
*/
|
|
|
|
void z_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
|
size_t stackSize, k_thread_entry_t pEntry,
|
|
void *p1, void *p2, void *p3,
|
|
int priority, unsigned int options)
|
|
{
|
|
char *pStack = Z_THREAD_STACK_BUFFER(stack);
|
|
|
|
/* Align stack end to maximum alignment requirement. */
|
|
char *stackEnd = (char *)ROUND_DOWN(pStack + stackSize, 16);
|
|
#if XCHAL_CP_NUM > 0
|
|
u32_t *cpSA;
|
|
char *cpStack;
|
|
#endif
|
|
|
|
z_new_thread_init(thread, pStack, stackSize, priority, options);
|
|
|
|
#ifdef CONFIG_DEBUG
|
|
printk("\nstackPtr = %p, stackSize = %d\n", pStack, stackSize);
|
|
printk("stackEnd = %p\n", stackEnd);
|
|
#endif
|
|
#if XCHAL_CP_NUM > 0
|
|
/* Ensure CP state descriptor is correctly initialized */
|
|
cpStack = thread->arch.preempCoprocReg.cpStack; /* short hand alias */
|
|
/* Set to zero to avoid bad surprises */
|
|
(void)memset(cpStack, 0, XT_CP_ASA);
|
|
/* Coprocessor's stack is allocated just after the k_thread */
|
|
cpSA = (u32_t *)(thread->arch.preempCoprocReg.cpStack + XT_CP_ASA);
|
|
/* Coprocessor's save area alignment is at leat 16 bytes */
|
|
*cpSA = ROUND_UP(cpSA + 1,
|
|
(XCHAL_TOTAL_SA_ALIGN < 16 ? 16 : XCHAL_TOTAL_SA_ALIGN));
|
|
#ifdef CONFIG_DEBUG
|
|
printk("cpStack = %p\n", thread->arch.preempCoprocReg.cpStack);
|
|
printk("cpAsa = %p\n",
|
|
*(void **)(thread->arch.preempCoprocReg.cpStack + XT_CP_ASA));
|
|
#endif
|
|
#endif
|
|
/* Thread's first frame alignment is granted as both operands are
|
|
* aligned
|
|
*/
|
|
XtExcFrame *pInitCtx =
|
|
(XtExcFrame *)(stackEnd - (XT_XTRA_SIZE - XT_CP_SIZE));
|
|
#ifdef CONFIG_DEBUG
|
|
printk("pInitCtx = %p\n", pInitCtx);
|
|
#endif
|
|
/* Explicitly initialize certain saved registers */
|
|
|
|
/* task entrypoint */
|
|
pInitCtx->pc = (u32_t)z_thread_entry;
|
|
|
|
/* physical top of stack frame */
|
|
pInitCtx->a1 = (u32_t)pInitCtx + XT_STK_FRMSZ;
|
|
|
|
/* user exception exit dispatcher */
|
|
pInitCtx->exit = (u32_t)z_xt_user_exit;
|
|
|
|
/* Set initial PS to int level 0, EXCM disabled, user mode.
|
|
* Also set entry point argument arg.
|
|
*/
|
|
#ifdef __XTENSA_CALL0_ABI__
|
|
pInitCtx->a2 = (u32_t)pEntry;
|
|
pInitCtx->a3 = (u32_t)p1;
|
|
pInitCtx->a4 = (u32_t)p2;
|
|
pInitCtx->a5 = (u32_t)p3;
|
|
pInitCtx->ps = PS_UM | PS_EXCM;
|
|
#else
|
|
/* For windowed ABI set also WOE and CALLINC
|
|
* (pretend task is 'call4')
|
|
*/
|
|
pInitCtx->a6 = (u32_t)pEntry;
|
|
pInitCtx->a7 = (u32_t)p1;
|
|
pInitCtx->a8 = (u32_t)p2;
|
|
pInitCtx->a9 = (u32_t)p3;
|
|
pInitCtx->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
|
|
#endif
|
|
thread->callee_saved.topOfStack = pInitCtx;
|
|
thread->arch.flags = 0;
|
|
/* initial values in all other registers/k_thread entries are
|
|
* irrelevant
|
|
*/
|
|
}
|
|
|