mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 01:05:54 +08:00
Xtensa: Cleanup of co-processor logic; remove some unnecessary things.
This commit is contained in:
@@ -44,6 +44,17 @@ config XTENSA_USE_OVLY
|
||||
---help---
|
||||
Enable code overlay support. This option is currently unsupported.
|
||||
|
||||
config XTENSA_CP_INITSET
|
||||
bool "Default co-processor enables"
|
||||
default 1
|
||||
range 0 65535
|
||||
---help---
|
||||
Co-processors may be enabled on a thread by calling xtensa_coproc_enable()
|
||||
and disabled by calling xtensa_coproc_disable(). Some co-processors
|
||||
should be enabled on all threads by default. That set of co-processors
|
||||
is provided by CONFIG_XTENSA_CP_INITSET. Each bit corresponds to one
|
||||
coprocessor with the same bit layout as for the CPENABLE register.
|
||||
|
||||
config ARCH_CHIP
|
||||
string
|
||||
default "esp32" if ARCH_CHIP_ESP32
|
||||
|
||||
@@ -162,7 +162,7 @@ struct xcptcontext
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Co-processor save area */
|
||||
|
||||
struct struct xtensa_cpstate_s cpstate;
|
||||
struct xtensa_cpstate_s cpstate;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
#define _CP_ALIGNUP(n,val) (((val) + _CP_MASK(n)) & ~_CP_MASK(n))
|
||||
#define _CP_ALIGNDOWN(n,val) ((val) & ~_CP_MASK(n))
|
||||
|
||||
/* A set of all co-processors */
|
||||
|
||||
#define XTENSA_CP_ALLSET ((1 << XCHAL_CP_NUM) - 1)
|
||||
|
||||
/* CO-PROCESSOR STATE SAVE AREA FOR A THREAD
|
||||
*
|
||||
* NuttX provides an area per thread to save the state of co-processors when
|
||||
@@ -93,18 +97,11 @@
|
||||
* XTENSA_CPSTORED
|
||||
* A bitmask with the same layout as CPENABLE, a bit per co-processor.
|
||||
* Indicates whether the state of each co-processor is saved in the state
|
||||
* save area. When a thread enters the kernel, only the state of co-procs
|
||||
* still enabled in CPENABLE is saved. When the co-processor exception
|
||||
* handler assigns ownership of a co-processor to a thread, it restores
|
||||
* the saved state only if this bit is set, and clears this bit.
|
||||
*
|
||||
* XTENSA_CPCSST
|
||||
* A bitmask with the same layout as CPENABLE, a bit per co-processor.
|
||||
* Indicates whether callee-saved state is saved in the state save area.
|
||||
* Callee-saved state is saved by itself on a solicited context switch,
|
||||
* and restored when needed by the coprocessor exception handler.
|
||||
* Unsolicited switches will cause the entire coprocessor to be saved
|
||||
* when necessary.
|
||||
* save area. When the state of a thread is saved, only the state of co-procs
|
||||
* still enabled in CPENABLE is saved. When the co-processor state is
|
||||
* is restored, the state is only resotred for a co-processor if this bit
|
||||
* is set. This bist set is cleared after after co-processor state has
|
||||
* been restored.
|
||||
*
|
||||
* XTENSA_CPASA
|
||||
* Pointer to the aligned save area. Allows it to be aligned more than
|
||||
@@ -129,8 +126,7 @@
|
||||
|
||||
#define XTENSA_CPENABLE 0 /* (2 bytes) coprocessors active for this thread */
|
||||
#define XTENSA_CPSTORED 2 /* (2 bytes) coprocessors saved for this thread */
|
||||
#define XTENSA_CPCSST 4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */
|
||||
#define XTENSA_CPASA 8 /* (4 bytes) ptr to aligned save area */
|
||||
#define XTENSA_CPASA 4 /* (4 bytes) ptr to aligned save area */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
@@ -140,11 +136,33 @@
|
||||
|
||||
struct xtensa_cpstate_s
|
||||
{
|
||||
uint16_t cpenable; /* (2 bytes) coprocessors active for this thread */
|
||||
uint16_t cpstored; /* (2 bytes) coprocessors saved for this thread */
|
||||
uint16_t cpcsst /* (2 bytes) coprocessor callee-saved regs stored for this thread */
|
||||
uint16_t unused; /* (2 bytes) unused */
|
||||
uint32_t *cpasa; /* (4 bytes) ptr to aligned save area */
|
||||
uint16_t cpenable; /* (2 bytes) Co-processors active for this thread */
|
||||
uint16_t cpstored; /* (2 bytes) Co-processors saved for this thread */
|
||||
uint32_t *cpasa; /* (4 bytes) Pointer to aligned save area */
|
||||
}
|
||||
|
||||
/* Return the current value of the CPENABLE register */
|
||||
|
||||
static inline uint32_t xtensa_get_cpenable(void)
|
||||
{
|
||||
uint32_t cpenable;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"rsr %0, CPENABLE" : "=r"(cpenable)
|
||||
);
|
||||
|
||||
return cpenable;
|
||||
}
|
||||
|
||||
/* Set the value of the CPENABLE register */
|
||||
|
||||
static inline void xtensa_set_cpenable(uint32_t cpenable)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"wsr %0, PS" : : "r"(cpenable)
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@@ -241,6 +241,8 @@ void xtensa_coproc_init(void);
|
||||
|
||||
struct xtensa_cpstate_s;
|
||||
void xtensa_coproc_release(struct xtensa_cpstate_s *cpstate);
|
||||
void xtensa_coproc_enable(struct xtensa_cpstate_s *cpstate, int cpset);
|
||||
void xtensa_coproc_disable(struct xtensa_cpstate_s *cpstate, int cpset);
|
||||
#endif
|
||||
|
||||
/* IRQs */
|
||||
|
||||
@@ -113,6 +113,7 @@ xtensa_coproc_init:
|
||||
movi a2, _xt_coproc_owner_sa /* a2 = base of owner array */
|
||||
addi a3, a2, (XTENSA_CP_MAX*portNUM_PROCESSORS) << 2 /* a3 = top+1 of owner array */
|
||||
movi a4, 0 /* a4 = 0 (unowned) */
|
||||
|
||||
1: s32i a4, a2, 0
|
||||
addi a2, a2, 4
|
||||
bltu a2, a3, 1b
|
||||
@@ -223,7 +224,7 @@ _xtensa_coproc_savestate:
|
||||
rsr a2, CPENABLE /* a2 = which CPs are enabled */
|
||||
beqz a2, .Ldone1 /* Quick exit if none */
|
||||
|
||||
s16i a2, a15, XTENSA_CPCSST /* Save mask of CPs being stored */
|
||||
s16i a2, a15, XTENSA_CPSTORED /* Save mask of CPs being stored */
|
||||
movi a13, _xtensa_coproc_saoffsets /* Array of CP save offsets */
|
||||
l32i a15, a15, XTENSA_CPASA /* a15 = base of aligned save area */
|
||||
|
||||
@@ -336,9 +337,9 @@ _xtensa_coproc_restorestate:
|
||||
/* Move the address of the thread state save area to R15 */
|
||||
|
||||
mov a15, a2 /* A15 is now the address of the save area */
|
||||
l16ui a2, a15, XTENSA_CPCSST /* a3 = which CPs have been saved */
|
||||
l16ui a2, a15, XTENSA_CPSTORED /* a2 = which CPs have been saved */
|
||||
movi a3, 0 /* Clear the ones being restored (all of them) */
|
||||
s32i a3, a15, XTENSA_CPCSST /* Update saved CP mask */
|
||||
s16i a3, a15, XTENSA_CPSTORED /* Clear saved CP mask */
|
||||
|
||||
movi a13, _xtensa_coproc_saoffsets /* Array of CP save offsets */
|
||||
l32i a15, a15, XTENSA_CPASA /* a15 = base of aligned save area */
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <arch/xtensa/xtensa_coproc.h>
|
||||
#include <arch/chip/core-isa.h>
|
||||
|
||||
#include "xtensa.h"
|
||||
@@ -58,12 +60,22 @@
|
||||
* 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.
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@@ -89,12 +101,22 @@ void xtensa_coproc_savestate(struct tcb_s *tcb)
|
||||
* 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.
|
||||
* Entry Conditions:
|
||||
* - CPENABLE is set up correctly for all required coprocessors.
|
||||
*
|
||||
* Exit conditions:
|
||||
* - All necessary CP callee-saved state has been restored.
|
||||
* - CPENABLE - unchanged.
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@@ -113,4 +135,107 @@ void xtensa_coproc_restorestate(struct tcb_s *tcb)
|
||||
)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_coproc_enable
|
||||
*
|
||||
* Description:
|
||||
* Enable a set of co-processors.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpstate - A pointer to the Co-processor state save structure.
|
||||
* cpset - A bit set of co-processors to be enabled. Matches bit layout
|
||||
* of the CPENABLE register. Bit 0-XCHAL_CP_NUM: 0 = no change
|
||||
* 1 = enable
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void xtensa_coproc_enable(struct xtensa_cpstate_s *cpstate, int cpset)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint32_t cpenable;
|
||||
|
||||
/* These operations must be atomic */
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Don't enable co-processors that may already be enabled
|
||||
*
|
||||
* cpenable
|
||||
* 0 1
|
||||
* --- ---
|
||||
* cpset 0 | 0 0
|
||||
* 1 | 1 0
|
||||
*/
|
||||
|
||||
cpset ^= (cpset & cpstate->cpenable);
|
||||
if (cpset != 0)
|
||||
{
|
||||
/* Enable the co-processors */
|
||||
|
||||
cpenable = xtensa_get_cpenable();
|
||||
cpenable |= cpset;
|
||||
xtensa_put_cpenable(cpenable);
|
||||
|
||||
cpstate->cpenable = cpenable;
|
||||
cpsates->cpstored &= ~cpset;
|
||||
}
|
||||
|
||||
leave_critical_section();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_coproc_disable
|
||||
*
|
||||
* Description:
|
||||
* Enable a set of co-processors.
|
||||
*
|
||||
* Input Parameters:
|
||||
* cpstate - A pointer to the Co-processor state save structure.
|
||||
* cpset - A bit set of co-processors to be enabled. Matches bit layout
|
||||
* of the CPENABLE register. Bit 0-XCHAL_CP_NUM: 0 = no change
|
||||
* 1 = disable
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void xtensa_coproc_disable(struct xtensa_cpstate_s *cpstate, int cpset)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint32_t cpenable;
|
||||
|
||||
/* These operations must be atomic */
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Don't disable co-processors that are already be disabled.
|
||||
*
|
||||
* cpenable
|
||||
* 0 1
|
||||
* --- ---
|
||||
* cpset 0 | 0 0
|
||||
* 1 | 0 1
|
||||
*/
|
||||
|
||||
cpset &= cpstate->cpenable;
|
||||
if (cpset != 0)
|
||||
{
|
||||
/* Disable the co-processors */
|
||||
|
||||
cpenable = xtensa_get_cpenable();
|
||||
cpenable &= ~cpset;
|
||||
xtensa_put_cpenable(cpenable);
|
||||
|
||||
cpstate->cpenable = cpenable;
|
||||
cpsates->cpstored &= ~cpset;
|
||||
}
|
||||
|
||||
leave_critical_section();
|
||||
}
|
||||
|
||||
|
||||
#endif /* XCHAL_CP_NUM */
|
||||
|
||||
@@ -215,8 +215,6 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
|
||||
xcp->cpstate.cpenable = 0; /* No coprocessors active for this thread */
|
||||
xcp->cpstate.cpstored = 0; /* No coprocessors saved for this thread */
|
||||
xcp->cpstate.cpcsst = 0; /* No oprocessor callee-saved regs stored for this thread */
|
||||
xcp->cpstate.unused = 0; /* unused */
|
||||
xcp->cpstate.cpasa = (uint32_t *)cpstart; /* Start of aligned save area */
|
||||
#endif
|
||||
|
||||
|
||||
@@ -156,10 +156,11 @@ void _exit(int status)
|
||||
#endif
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Disable preprocessor support fo the task that is exit-ing. */
|
||||
/* Disable co-processor support for the task that is exit-ing. */
|
||||
|
||||
tcb = this_task();
|
||||
xtensa_coproc_release(&tcb->xcp.cpstate);
|
||||
xtensa_coproc_disable(&tcb->xcp.cpstate, XTENSA_CP_ALLSET);
|
||||
#endif
|
||||
|
||||
/* Destroy the task at the head of the ready to run list. */
|
||||
|
||||
@@ -94,4 +94,13 @@ void up_initial_state(struct tcb_s *tcb)
|
||||
|
||||
xcp->regs[REG_PS] = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
|
||||
#endif
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Set up the co-processors that will be enabled initially when the thread
|
||||
* starts (see xtensa_coproc.h)
|
||||
*/
|
||||
|
||||
xcp->cpstate.cpenable = CONFIG_XTENSA_CP_INITSET;
|
||||
xcp->cpstate.cpstored = 0; /* No coprocessors haved statee saved for this thread */
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -174,6 +174,7 @@ _xtensa_level6_vector:
|
||||
.align 4
|
||||
|
||||
_xtensa_nmi_vector:
|
||||
|
||||
wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */
|
||||
call0 _xt_nmi /* load interrupt handler */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user