Xtensa: Adapt co-processor state save/restore functions so that they are call-able from C with Windows ABI.

This commit is contained in:
Gregory Nutt 2016-10-30 08:35:09 -06:00
parent c0da94fc3e
commit 261e0edc61
12 changed files with 176 additions and 106 deletions

@ -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 */

@ -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 */

@ -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

@ -46,6 +46,8 @@
#include <arch/chip/tie.h>
#include <arch/chip/tie-asm.h>
#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 */

@ -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 <gnutt@nuttx.org>
@ -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 */

@ -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

@ -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

@ -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

@ -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

@ -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
}
}

@ -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

@ -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