Xtensa: Add xtensa_coproc.h
This commit is contained in:
parent
5b1a3e6fe0
commit
be2a801e30
@ -38,17 +38,6 @@ config XTENSA_CALL0_ABI
|
||||
The Window ABI is not supported. Only the CALL0 ABI is supported in the
|
||||
current implementation.
|
||||
|
||||
config XTENSA_CP_LAZY
|
||||
bool "Lazy Co-processor Save"
|
||||
default y
|
||||
---help---
|
||||
If this option is selected, then the co-processor state will be saved
|
||||
only on context switches. As a consequency of this, co-processors
|
||||
may NOT be used within interrupt handlers. If you must use co-
|
||||
processors in interrupt handling, then disable this option. There
|
||||
will be a significant interrupt latency performance impact if this
|
||||
option is disabled.
|
||||
|
||||
config XTENSA_USE_OVLY
|
||||
bool
|
||||
default n
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include <arch/chip/core-isa.h>
|
||||
#include <arch/xtensa/xtensa_specregs.h>
|
||||
#include <arch/xtensa/xtensa_corebits.h>
|
||||
#include <arch/xtensa/xtensa_coproc.h>
|
||||
|
||||
/* Include architecture-specific IRQ definitions */
|
||||
|
||||
@ -158,6 +159,12 @@ struct xcptcontext
|
||||
|
||||
uint32_t regs[XCPTCONTEXT_REGS];
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Co-processor save area */
|
||||
|
||||
struct struct xtensa_cpstate_s cpstate;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
/* The following array holds the return address and the exc_return value
|
||||
* needed to return from each nested system call.
|
||||
|
152
arch/xtensa/include/xtensa/xtensa_coproc.h
Normal file
152
arch/xtensa/include/xtensa/xtensa_coproc.h
Normal file
@ -0,0 +1,152 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/include/xtensa/xtensa_coproc.h
|
||||
*
|
||||
* Adapted from use in NuttX by:
|
||||
*
|
||||
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Derives from logic originally provided by Cadence Design Systems Inc.
|
||||
*
|
||||
* Copyright (c) 2006-2015 Cadence Design Systems Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_XTENSA_INCLUDE_XTENSA_XTENSA_COPROC_H
|
||||
#define __ARCH_XTENSA_INCLUDE_XTENSA_XTENSA_COPROC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <arch/exp32/core-isa.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
|
||||
/* Align a value up/down to nearest n-byte boundary, where n is a power of 2. */
|
||||
|
||||
#define _CP_MASK(n) ((n) - 1)
|
||||
#define _CP_ALIGNUP(n,val) (((val) + _CP_MASK(n)) & ~_CP_MASK(n))
|
||||
#define _CP_ALIGNDOWN(n,val) ((val) & ~_CP_MASK(n))
|
||||
|
||||
/* CO-PROCESSOR STATE SAVE AREA FOR A THREAD
|
||||
*
|
||||
* NuttX provides an area per thread to save the state of co-processors when
|
||||
* that thread does not have control. Co-processors are context-switched
|
||||
* lazily (on demand) only when a new thread uses a co-processor instruction,
|
||||
* otherwise a thread retains ownership of the co-processor even when it
|
||||
* loses control of the processor. An Xtensa co-processor exception is
|
||||
* triggered when any co-processor instruction is executed by a thread that
|
||||
* is not the owner, and the context switch of that co-processor is then
|
||||
* peformed by the handler. Ownership represents which thread's state is
|
||||
* currently in the co-processor.
|
||||
*
|
||||
* Co-processors may not be used by interrupt or exception handlers. If an
|
||||
* co-processor instruction is executed by an interrupt or exception handler,
|
||||
* the co-processor exception handler will trigger a kernel panic and freeze.
|
||||
* This restriction is introduced to reduce the overhead of saving and
|
||||
* restoring co-processor state (which can be quite large) and in particular
|
||||
* remove that overhead from interrupt handlers.
|
||||
*
|
||||
* The co-processor state save area may be in any convenient per-thread
|
||||
* location such as in the thread control block or above the thread stack
|
||||
* area. It need not be in the interrupt stack frame since interrupts don't
|
||||
* use co-processors.
|
||||
*
|
||||
* Along with the save area for each co-processor, two bitmasks with flags
|
||||
* per co-processor (laid out as in the CPENABLE reg) help manage context-
|
||||
* switching co-processors as efficiently as possible:
|
||||
*
|
||||
* XTENSA_CPENABLE
|
||||
* The contents of a non-running thread's CPENABLE register.
|
||||
* It represents the co-processors owned (and whose state is still needed)
|
||||
* by the thread. When a thread is preempted, its CPENABLE is saved here.
|
||||
* When a thread solicits a context-swtich, its CPENABLE is cleared - the
|
||||
* compiler has saved the (caller-saved) co-proc state if it needs to.
|
||||
* When a non-running thread loses ownership of a CP, its bit is cleared.
|
||||
* When a thread runs, it's XTENSA_CPENABLE is loaded into the CPENABLE reg.
|
||||
* Avoids co-processor exceptions when no change of ownership is needed.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* XTENSA_CPASA
|
||||
* Pointer to the aligned save area. Allows it to be aligned more than
|
||||
* the overall save area (which might only be stack-aligned or TCB-aligned).
|
||||
* Especially relevant for Xtensa cores configured with a very large data
|
||||
* path that requires alignment greater than 16 bytes (ABI stack alignment).
|
||||
*/
|
||||
|
||||
/* Offsets of each coprocessor save area within the 'aligned save area': */
|
||||
|
||||
#define XTENSA_CP0_SA 0
|
||||
#define XTENSA_CP1_SA _CP_ALIGNUP(XCHAL_CP1_SA_ALIGN, XTENSA_CP0_SA + XCHAL_CP0_SA_SIZE)
|
||||
#define XTENSA_CP2_SA _CP_ALIGNUP(XCHAL_CP2_SA_ALIGN, XTENSA_CP1_SA + XCHAL_CP1_SA_SIZE)
|
||||
#define XTENSA_CP3_SA _CP_ALIGNUP(XCHAL_CP3_SA_ALIGN, XTENSA_CP2_SA + XCHAL_CP2_SA_SIZE)
|
||||
#define XTENSA_CP4_SA _CP_ALIGNUP(XCHAL_CP4_SA_ALIGN, XTENSA_CP3_SA + XCHAL_CP3_SA_SIZE)
|
||||
#define XTENSA_CP5_SA _CP_ALIGNUP(XCHAL_CP5_SA_ALIGN, XTENSA_CP4_SA + XCHAL_CP4_SA_SIZE)
|
||||
#define XTENSA_CP6_SA _CP_ALIGNUP(XCHAL_CP6_SA_ALIGN, XTENSA_CP5_SA + XCHAL_CP5_SA_SIZE)
|
||||
#define XTENSA_CP7_SA _CP_ALIGNUP(XCHAL_CP7_SA_ALIGN, XTENSA_CP6_SA + XCHAL_CP6_SA_SIZE)
|
||||
#define XTENSA_CP_SA_SIZE _CP_ALIGNUP(16, XTENSA_CP7_SA + XCHAL_CP7_SA_SIZE)
|
||||
|
||||
/* Offsets within the overall save area: */
|
||||
|
||||
#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 */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* #if XCHAL_CP_NUM > 0 */
|
||||
#endif /* __ARCH_XTENSA_INCLUDE_XTENSA_XTENSA_COPROC_H */
|
@ -195,13 +195,15 @@ _xtensa_coproc_savestate:
|
||||
|
||||
rsr a2, CPENABLE /* a2 = which CPs are enabled */
|
||||
beqz a2, .Ldone /* Quick exit if none */
|
||||
|
||||
mov a14, a0 /* Save return address */
|
||||
call0 XT_RTOS_CP_STATE /* Get address of CP save area */
|
||||
mov a0, a14 /* Restore return address */
|
||||
beqz a15, .Ldone /* if none then nothing to do */
|
||||
s16i a2, a15, XT_CP_CS_ST /* Save mask of CPs being stored */
|
||||
|
||||
s16i a2, a15, XTENSA_CPCSST /* Save mask of CPs being stored */
|
||||
movi a13, _xt_coproc_sa_offset /* Array of CP save offsets */
|
||||
l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */
|
||||
l32i a15, a15, XTENSA_CPASA /* a15 = base of aligned save area */
|
||||
|
||||
#if XTENSA_CP0_SA_SIZE > 0
|
||||
bbci.l a2, 0, 2f /* CP 0 not enabled */
|
||||
@ -308,11 +310,13 @@ _xtensa_coproc_restorestate:
|
||||
call0 XT_RTOS_CP_STATE /* Get address of CP save area */
|
||||
mov a0, a14 /* Restore return address */
|
||||
beqz a15, .Ldone2 /* if none then nothing to do */
|
||||
l16ui a3, a15, XT_CP_CS_ST /* a3 = which CPs have been saved */
|
||||
|
||||
l16ui a3, a15, XTENSA_CPCSST /* a3 = which CPs have been saved */
|
||||
xor a3, a3, a2 /* Clear the ones being restored */
|
||||
s32i a3, a15, XT_CP_CS_ST /* Update saved CP mask */
|
||||
s32i a3, a15, XTENSA_CPCSST /* Update saved CP mask */
|
||||
|
||||
movi a13, _xt_coproc_sa_offset /* Array of CP save offsets */
|
||||
l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */
|
||||
l32i a15, a15, XTENSA_CPASA /* a15 = base of aligned save area */
|
||||
|
||||
#if XTENSA_CP0_SA_SIZE
|
||||
bbci.l a2, 0, 2f /* CP 0 not enabled */
|
||||
|
@ -47,6 +47,8 @@
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/board.h>
|
||||
|
||||
#include <arch/xtensa/xtensa_coproc.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "xtensa.h"
|
||||
@ -57,13 +59,11 @@
|
||||
|
||||
/* XTENSA requires at least a 4-byte stack alignment. For floating point use,
|
||||
* however, the stack must be aligned to 8-byte addresses.
|
||||
*
|
||||
* REVIST: Is this true? Comes from ARM EABI
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_LIBC_FLOATINGPOINT
|
||||
# define STACK_ALIGNMENT 8
|
||||
#else
|
||||
# define STACK_ALIGNMENT 4
|
||||
#endif
|
||||
#define STACK_ALIGNMENT 8
|
||||
|
||||
/* Stack alignment macros */
|
||||
|
||||
@ -114,6 +114,12 @@
|
||||
|
||||
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
{
|
||||
#if XCHAL_CP_NUM > 0
|
||||
uintptr_t cpstart;
|
||||
uintptr_t cpend;
|
||||
size_t cpsize;
|
||||
#endif
|
||||
|
||||
/* Is there already a stack allocated of a different size? Because of
|
||||
* alignment issues, stack_size might erroneously appear to be of a
|
||||
* different size. Fortunately, this is not a critical operation.
|
||||
@ -126,6 +132,16 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
up_release_stack(tcb, ttype);
|
||||
}
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Add the size of the co-processor save area to the stack allocation.
|
||||
* REVISIT: This may waste memory. Increasing the caller's requested
|
||||
* stack size should only be necessary if the requested size could not
|
||||
* hold the co-processor save area.
|
||||
*/
|
||||
|
||||
stack_size += XTENSA_CP_SA_SIZE;
|
||||
#endif
|
||||
|
||||
/* Do we need to allocate a new stack? */
|
||||
|
||||
if (!tcb->stack_alloc_ptr)
|
||||
@ -163,15 +179,15 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
|
||||
if (tcb->stack_alloc_ptr)
|
||||
{
|
||||
size_t top_of_stack;
|
||||
uintptr_t top_of_stack;
|
||||
size_t size_of_stack;
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
/* Yes.. If stack debug is enabled, then fill the stack with a
|
||||
* recognizable value that we can use later to test for high
|
||||
* water marks.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
memset(tcb->stack_alloc_ptr, 0xaa, stack_size);
|
||||
#endif
|
||||
|
||||
@ -181,15 +197,36 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
|
||||
* the stack are referenced as positive word offsets from sp.
|
||||
*/
|
||||
|
||||
top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4;
|
||||
top_of_stack = (uintptr_t)tcb->stack_alloc_ptr + stack_size - 4;
|
||||
|
||||
/* The XTENSA stack must be aligned at word (4 byte) boundaries; for
|
||||
* floating point use, the stack must be aligned to 8-byte addresses.
|
||||
* If necessary top_of_stack must be rounded down to the next
|
||||
* boundary to meet these alignment requirements.
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Allocate the co-processor save area at the top of the (push down)
|
||||
* stack.
|
||||
*
|
||||
* REVISIT: This is not secure. In secure built configurations it
|
||||
* be more appropriate to use kmm_memalign() to allocte protected
|
||||
* memory rather than using the stack.
|
||||
*/
|
||||
|
||||
top_of_stack = STACK_ALIGN_DOWN(top_of_stack);
|
||||
cpstart = (uintptr_t)_CP_ALIGNDOWN(top_of_stack - XCHAL_CP1_SA_ALIGN);
|
||||
top_of_stack = cpstart;
|
||||
|
||||
/* Initialize the coprocessor save area (see xtensa_coproc.h) */
|
||||
|
||||
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
|
||||
|
||||
/* The XTENSA stack must be aligned. If necessary top_of_stack must be
|
||||
* rounded down to the next boundary to meet this alignment requirement.
|
||||
*
|
||||
* NOTE: Co-processor save area not included in the size of the stack.
|
||||
*/
|
||||
|
||||
top_of_stack = STACK_ALIGN_DOWN(top_of_stack);
|
||||
size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;
|
||||
|
||||
/* Save the adjusted stack values in the struct tcb_s */
|
||||
|
@ -71,11 +71,6 @@
|
||||
void up_initial_state(struct tcb_s *tcb)
|
||||
{
|
||||
struct xcptcontext *xcp = &tcb->xcp;
|
||||
#if 0 /* REVISIT */
|
||||
#if XCHAL_CP_NUM > 0
|
||||
uint32_t *ptr;
|
||||
#endif
|
||||
#endif /* REVISIT */
|
||||
|
||||
/* Initialize the initial exception register context structure */
|
||||
|
||||
@ -99,20 +94,4 @@ void up_initial_state(struct tcb_s *tcb)
|
||||
|
||||
xcp->regs[REG_PS] = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
|
||||
#endif
|
||||
|
||||
#warning REVISIT co-processor support
|
||||
#if 0 /* REVISIT */
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Init the coprocessor save area (see xtensa_context.h)
|
||||
*
|
||||
* No access to TCB here, so derive indirectly. Stack growth is top to bottom.
|
||||
* //ptr = (uint32_t *) xMPUSettings->coproc_area;
|
||||
*/
|
||||
|
||||
ptr = (uint32_t *)(((uint32_t)tcb->adj_stack_ptr - XT_CP_SIZE) & ~0xf);
|
||||
ptr[0] = 0;
|
||||
ptr[1] = 0;
|
||||
ptr[2] = (((uint32_t)ptr) + 12 + XTENSA_TOTAL_SA_ALIGN - 1) & -XTENSA_TOTAL_SA_ALIGN;
|
||||
#endif
|
||||
#endif /* REVISIT */
|
||||
}
|
||||
|
@ -81,12 +81,6 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
|
||||
#if XCHAL_CP_NUM > 0 && !defined(CONFIG_XTENSA_CP_LAZY)
|
||||
/* Save the current co processor state on entry int each interrupt. */
|
||||
|
||||
esp32_coproc_savestate(tcb->xcp.cpstate);
|
||||
#endif
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
@ -99,7 +93,6 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
|
||||
if (regs != CURRENT_REGS)
|
||||
{
|
||||
#if XCHAL_CP_NUM > 0
|
||||
#ifdef CONFIG_XTENSA_CP_LAZY
|
||||
/* If an interrupt level context switch has occurred, then save the
|
||||
* co-processor state in in the suspended thread's co-processor save
|
||||
* area.
|
||||
@ -110,9 +103,8 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
|
||||
*/
|
||||
|
||||
esp32_coproc_savestate(tcb->xcp.cpstate);
|
||||
#endif
|
||||
|
||||
/* Set up the co-processor state for the to-be-started thread.
|
||||
/* Then set up the co-processor state for the to-be-started thread.
|
||||
*
|
||||
* NOTE: The current thread for this CPU is the to-be-started
|
||||
* thread.
|
||||
|
Loading…
Reference in New Issue
Block a user