diff --git a/arch/xtensa/src/common/xtensa.h b/arch/xtensa/src/common/xtensa.h index fb1ba85dd6a..d6af111d040 100644 --- a/arch/xtensa/src/common/xtensa.h +++ b/arch/xtensa/src/common/xtensa.h @@ -260,9 +260,8 @@ int xtensa_context_save(uint32_t *regs); void xtensa_context_restore(uint32_t *regs) noreturn_function; #if XCHAL_CP_NUM > 0 -struct tcb_s; -void xtensa_coproc_savestate(struct tcb_s *tcb); -void xtensa_coproc_restorestate(struct tcb_s *tcb); +void xtensa_coproc_savestate(struct xtensa_cpstate_s *cpstate); +void xtensa_coproc_restorestate(struct xtensa_cpstate_s *cpstate); #endif /* Signals */ diff --git a/arch/xtensa/src/common/xtensa_abi.h b/arch/xtensa/src/common/xtensa_abi.h index 6fa4456f830..63e53f26c5d 100644 --- a/arch/xtensa/src/common/xtensa_abi.h +++ b/arch/xtensa/src/common/xtensa_abi.h @@ -104,6 +104,8 @@ */ #ifdef __ASSEMBLY__ +/* Function prologues and epilogues */ + #ifdef __XTENSA_CALL0_ABI__ /* Call0 */ @@ -130,7 +132,13 @@ # define ENTRY0 entry sp, 0x10 # define RET(sz) retw # define RET0 retw + #endif + +/* Index into stack frame (skipping over saved A0) */ + +#define LOCAL_OFFSET(n) ((n) << 2) /* n = 1 .. ((size >> 2) - 1) */ + #endif /* __ASSEMBLY_ */ #endif /* __ARCH_XTENSA_SRC_COMMON_XTENSA_ABI_H */ diff --git a/arch/xtensa/src/common/xtensa_blocktask.c b/arch/xtensa/src/common/xtensa_blocktask.c index d2fb62bf486..fb1c0f910bb 100644 --- a/arch/xtensa/src/common/xtensa_blocktask.c +++ b/arch/xtensa/src/common/xtensa_blocktask.c @@ -154,7 +154,7 @@ void up_block_task(struct tcb_s *tcb, tstate_t task_state) * processor save area. */ - xtensa_coproc_savestate(rtcb); + xtensa_coproc_savestate(&rtcb->xcp.cpstate); #endif /* Restore the exception context of the rtcb at the (new) head @@ -166,7 +166,7 @@ void up_block_task(struct tcb_s *tcb, tstate_t task_state) #if XCHAL_CP_NUM > 0 /* Set up the co-processor state for the newly started thread. */ - xtensa_coproc_restorestate(rtcb); + xtensa_coproc_restorestate(&rtcb->xcp.cpstate); #endif #ifdef CONFIG_ARCH_ADDRENV diff --git a/arch/xtensa/src/common/xtensa_coproc.S b/arch/xtensa/src/common/xtensa_coproc.S index 2445eaecf32..2bcba0185f2 100644 --- a/arch/xtensa/src/common/xtensa_coproc.S +++ b/arch/xtensa/src/common/xtensa_coproc.S @@ -46,6 +46,8 @@ #include #include +#include "xtensa_abi.h" + #if XCHAL_CP_NUM > 0 /**************************************************************************** @@ -87,7 +89,7 @@ _xtensa_coproc_saoffsets: * around the assembly language call to _xtensa_coproc_savestate. * * Entry Conditions: - * - A2 holds the address of the threads state save area + * - A2 holds the address of the co-processor state save area * - The thread being switched out is still the current thread. * - CPENABLE state reflects which coprocessors are active. * - Registers have been saved/spilled already. @@ -191,6 +193,79 @@ _xtensa_coproc_savestate: .size _xtensa_coproc_savestate, . - _xtensa_coproc_savestate +/**************************************************************************** + * Name: xtensa_coproc_savestate + * + * Description: + * If there is a current thread and it has a coprocessor state save area, + * then save all callee-saved state into this area. xtensa_coproc_savestate() + * is simply a C wrapper around the assembly language call to + * _xtensa_coproc_savestate. + * + * Input Parameters: + * A2 - Address of co-processor save area + * + * Returned Value: + * None + * + * Assumptions: + * Called with interrupts disabled. + * + ****************************************************************************/ + + .global xtensa_coproc_savestate + .type xtensa_coproc_savestate, @function + + .align 4 + .literal_position + .align 4 + +xtensa_coproc_savestate: + +#ifdef __XTENSA_CALL0_ABI__ + + /* Need to preserve a8-11. _xtensa_coproc_savestate modifies a2-a7, + * a13-a15. So no registers need be saved. + */ + + ENTRY(16) + + /* Call _xtensa_coproc_savestate() with A2=address of co-processor + * save area. + */ + + call0 _xtensa_coproc_savestate + RET(16) + +#else + + /* Need to preserve a8-15. _xtensa_coproc_savestate modifies a2-a7, + * a13-a15. So only a13-a15 need be preserved. + */ + + ENTRY(16) + s32i a13, sp, LOCAL_OFFSET(1) + s32i a14, sp, LOCAL_OFFSET(2) + s32i a15, sp, LOCAL_OFFSET(3) + + /* Call _xtensa_coproc_savestate() with A2=address of co-processor + * save area. + */ + + call0 _xtensa_coproc_savestate + + /* Restore a13-15 and return */ + + 132i a13, sp, LOCAL_OFFSET(1) + 132i a14, sp, LOCAL_OFFSET(2) + 132i a15, sp, LOCAL_OFFSET(3) + + RET(16) + +#endif + + .size xtensa_coproc_savestate, . - xtensa_coproc_savestate + /**************************************************************************** * Name: _xtensa_coproc_restorestate * @@ -206,7 +281,7 @@ _xtensa_coproc_savestate: * around the assembly language call to _xtensa_coproc_restorestate. * * Entry Conditions: - * - A2 holds the address of the threads state save area + * - A2 holds the address of the co-processor state save area * - The incoming thread is set as the current thread. * - CPENABLE is set up correctly for all required coprocessors. * @@ -306,4 +381,76 @@ _xtensa_coproc_restorestate: .size _xtensa_coproc_restorestate, . - _xtensa_coproc_restorestate +/**************************************************************************** + * Name: xtensa_coproc_restorestate + * + * Description: + * Restore any callee-saved coprocessor state for the incoming thread. + * xtensa_coproc_restorestate() is simply a C wrapper around the assembly + * language call to _xtensa_coproc_restorestate. + * + * Input Parameters: + * - A2 holds the address of the threads state save area + * + * Returned Value: + * None + * + * Assumptions: + * Called with interrupts disabled. + * + ****************************************************************************/ + + .global xtensa_coproc_restorestate + .type xtensa_coproc_restorestate, @function + + .align 4 + .literal_position + .align 4 + +xtensa_coproc_restorestate: + +#ifdef __XTENSA_CALL0_ABI__ + + /* Need to preserve a8-11. _xtensa_coproc_restorestate modifies a2-a7, + * a13-a15. So no registers need be saved. + */ + + ENTRY(16) + + /* Call _xtensa_coproc_restorestate() with A2=address of co-processor + * save area. + */ + + call0 _xtensa_coproc_restorestate + RET(16) + +#else + + /* Need to preserve a8-15. _xtensa_coproc_savestate modifies a2-a7, + * a13-a15. So only a13-a15 need be preserved. + */ + + ENTRY(16) + s32i a13, sp, LOCAL_OFFSET(1) + s32i a14, sp, LOCAL_OFFSET(2) + s32i a15, sp, LOCAL_OFFSET(3) + + /* Call _xtensa_coproc_restorestate() with A2=address of co-processor + * save area. + */ + + call0 _xtensa_coproc_restorestate + + /* Restore a13-15 and return */ + + 132i a13, sp, LOCAL_OFFSET(1) + 132i a14, sp, LOCAL_OFFSET(2) + 132i a15, sp, LOCAL_OFFSET(3) + + RET(16) + +#endif + + .size xtensa_coproc_restorestate, . - xtensa_coproc_restorestate + #endif /* XCHAL_CP_NUM > 0 */ diff --git a/arch/xtensa/src/common/xtensa_cpsave.c b/arch/xtensa/src/common/xtensa_cpenable.c similarity index 66% rename from arch/xtensa/src/common/xtensa_cpsave.c rename to arch/xtensa/src/common/xtensa_cpenable.c index bd4a50ffdf9..894cb028bca 100644 --- a/arch/xtensa/src/common/xtensa_cpsave.c +++ b/arch/xtensa/src/common/xtensa_cpenable.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/xtensa/src/common/xtensa_cpsave.c + * arch/xtensa/src/common/xtensa_cpenable.c * * Copyright (C) 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -53,89 +53,6 @@ * Public Functions ****************************************************************************/ -/**************************************************************************** - * Name: xtensa_coproc_savestate - * - * Description: - * If there is a current thread and it has a coprocessor state save area, - * then save all callee-saved state into this area. xtensa_coproc_savestate() - * is simply a C wrapper around the assembly language call to - * _xtensa_coproc_savestate. - * - * Entry Conditions: - * - The thread being switched out is still the current thread. - * - CPENABLE state reflects which coprocessors are active. - * - * Exit conditions: - * - All necessary CP callee-saved state has been saved. - * - * Input Parameters: - * tcb - A pointer to the TCB of thread whose co-processor state is to - * be saved. - * - * Returned Value: - * None - * - * Assumptions: - * Called with interrupts disabled. - * - ****************************************************************************/ - -void xtensa_coproc_savestate(struct tcb_s *tcb) -{ - uint32_t cpstate = (uint32_t)((uintptr_t)&tcb->xcp.cpstate); - - __asm__ __volatile__ - ( - "mov a2, %0\n" - "call0 _xtensa_coproc_savestate\n" - : - : "r" (cpstate) - : "a0", "a2", "a3", "a4", "a5", "a6", "a7", "a13", "a14", "a15" - ); -} - -/**************************************************************************** - * Name: xtensa_coproc_restorestate - * - * Description: - * Restore any callee-saved coprocessor state for the incoming thread. - * xtensa_coproc_restorestate() is simply a C wrapper around the assembly - * language call to _xtensa_coproc_restorestate. - * - * Entry Conditions: - * - CPENABLE is set up correctly for all required coprocessors. - * - * Exit conditions: - * - All necessary CP callee-saved state has been restored. - * - CPENABLE - unchanged. - * - * Input Parameters: - * tcb - A pointer to the TCB of thread whose co-processor state is to - * be restored. - * - * Returned Value: - * None - * - * Assumptions: - * Called with interrupts disabled. - * - ****************************************************************************/ - -void xtensa_coproc_restorestate(struct tcb_s *tcb) -{ - uint32_t cpstate = (uint32_t)((uintptr_t)&tcb->xcp.cpstate); - - __asm__ __volatile__ - ( - "mov a2, %0\n" - "call0 _xtensa_coproc_restorestate\n" - : - : "r" (cpstate) - : "a0", "a2", "a3", "a4", "a5", "a6", "a7", "a13", "a14", "a15" - ); -} - /**************************************************************************** * Name: xtensa_coproc_enable * @@ -238,5 +155,4 @@ void xtensa_coproc_disable(struct xtensa_cpstate_s *cpstate, int cpset) leave_critical_section(flags); } - #endif /* XCHAL_CP_NUM */ diff --git a/arch/xtensa/src/common/xtensa_exit.c b/arch/xtensa/src/common/xtensa_exit.c index bf568f10d48..e6536901628 100644 --- a/arch/xtensa/src/common/xtensa_exit.c +++ b/arch/xtensa/src/common/xtensa_exit.c @@ -175,7 +175,7 @@ void _exit(int status) #if XCHAL_CP_NUM > 0 /* Set up the co-processor state for the newly started thread. */ - xtensa_coproc_restorestate(tcb); + xtensa_coproc_restorestate(&tcb->xcp.cpstate); #endif #ifdef CONFIG_ARCH_ADDRENV diff --git a/arch/xtensa/src/common/xtensa_irqdispatch.c b/arch/xtensa/src/common/xtensa_irqdispatch.c index 67192e0634f..9ce5bba0875 100644 --- a/arch/xtensa/src/common/xtensa_irqdispatch.c +++ b/arch/xtensa/src/common/xtensa_irqdispatch.c @@ -103,7 +103,7 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs) * NOTE 2. We saved a reference TCB of the original thread on entry. */ - xtensa_coproc_savestate(tcb); + xtensa_coproc_savestate(&tcb->xcp.cpstate); /* Then set up the co-processor state for the to-be-started thread. * @@ -112,7 +112,7 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs) */ tcb = this_task(); - xtensa_coproc_restorestate(tcb); + xtensa_coproc_restorestate(&tcb->xcp.cpstate); #endif #ifdef CONFIG_ARCH_ADDRENV diff --git a/arch/xtensa/src/common/xtensa_releasepending.c b/arch/xtensa/src/common/xtensa_releasepending.c index 4328d78a7e9..cae473243f3 100644 --- a/arch/xtensa/src/common/xtensa_releasepending.c +++ b/arch/xtensa/src/common/xtensa_releasepending.c @@ -124,7 +124,7 @@ void up_release_pending(void) * processor save area. */ - xtensa_coproc_savestate(rtcb); + xtensa_coproc_savestate(&rtcb->xcp.cpstate); #endif /* Restore the exception context of the rtcb at the (new) head * of the ready-to-run task list. @@ -135,7 +135,7 @@ void up_release_pending(void) #if XCHAL_CP_NUM > 0 /* Set up the co-processor state for the newly started thread. */ - xtensa_coproc_restorestate(rtcb); + xtensa_coproc_restorestate(&rtcb->xcp.cpstate); #endif #ifdef CONFIG_ARCH_ADDRENV diff --git a/arch/xtensa/src/common/xtensa_reprioritizertr.c b/arch/xtensa/src/common/xtensa_reprioritizertr.c index eb5255ece89..0226d18f725 100644 --- a/arch/xtensa/src/common/xtensa_reprioritizertr.c +++ b/arch/xtensa/src/common/xtensa_reprioritizertr.c @@ -177,7 +177,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) * processor save area. */ - xtensa_coproc_savestate(rtcb); + xtensa_coproc_savestate(&rtcb->xcp.cpstate); #endif /* Restore the exception context of the rtcb at the (new) head * of the ready-to-run task list. @@ -188,7 +188,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) #if XCHAL_CP_NUM > 0 /* Set up the co-processor state for the newly started thread. */ - xtensa_coproc_restorestate(rtcb); + xtensa_coproc_restorestate(&rtcb->xcp.cpstate); #endif #ifdef CONFIG_ARCH_ADDRENV diff --git a/arch/xtensa/src/common/xtensa_schedsigaction.c b/arch/xtensa/src/common/xtensa_schedsigaction.c index 438f7127684..db0f5fa9c35 100644 --- a/arch/xtensa/src/common/xtensa_schedsigaction.c +++ b/arch/xtensa/src/common/xtensa_schedsigaction.c @@ -152,9 +152,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) CURRENT_REGS[REG_PC] = (uint32_t)xtensa_sigdeliver; #ifdef __XTENSA_CALL0_ABI__ - CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(0) | PS_UM); + CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM); #else - CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(0) | PS_UM | PS_WOE); + CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE); #endif /* And make sure that the saved context in the TCB is the same @@ -187,9 +187,9 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sigdeliver; #ifdef __XTENSA_CALL0_ABI__ - tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(0) | PS_UM); + tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM); #else - tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(0) | PS_UM | PS_WOE); + tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE); #endif } } diff --git a/arch/xtensa/src/common/xtensa_unblocktask.c b/arch/xtensa/src/common/xtensa_unblocktask.c index c7788927c67..40ecf73c56b 100644 --- a/arch/xtensa/src/common/xtensa_unblocktask.c +++ b/arch/xtensa/src/common/xtensa_unblocktask.c @@ -138,7 +138,7 @@ void up_unblock_task(struct tcb_s *tcb) * processor save area. */ - xtensa_coproc_savestate(rtcb); + xtensa_coproc_savestate(&rtcb->xcp.cpstate); #endif /* Restore the exception context of the new task that is ready to @@ -151,7 +151,7 @@ void up_unblock_task(struct tcb_s *tcb) #if XCHAL_CP_NUM > 0 /* Set up the co-processor state for the newly started thread. */ - xtensa_coproc_restorestate(rtcb); + xtensa_coproc_restorestate(&rtcb->xcp.cpstate); #endif #ifdef CONFIG_ARCH_ADDRENV diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index 6e1c44113fd..b1fea99b585 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -44,7 +44,7 @@ CMN_ASRCS = xtensa_context.S xtensa_coproc.S xtensa_cpuint.S CMN_ASRCS += xtensa_int_handlers.S xtensa_nmi_handler.S xtensa_vectors.S CMN_CSRCS = xtensa_assert.c xtensa_blocktask.c xtensa_copystate.c -CMN_CSRCS += xtensa_cpsave.c xtensa_createstack.c xtensa_exit.c xtensa_idle.c +CMN_CSRCS += xtensa_cpenable.c xtensa_createstack.c xtensa_exit.c xtensa_idle.c CMN_CSRCS += xtensa_initialize.c xtensa_initialstate.c xtensa_interruptcontext.c CMN_CSRCS += xtensa_irqdispatch.c xtensa_lowputs.c xtensa_mdelay.c CMN_CSRCS += xtensa_modifyreg8.c xtensa_modifyreg16.c xtensa_modifyreg32.c