arch/xtensa: Add the optional interrupt stack.

Signed-off-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com>
This commit is contained in:
Abdelatif Guettouche 2020-10-12 12:49:58 +01:00 committed by Masayuki Ishikawa
parent 15d658403a
commit c97d11aa7b
7 changed files with 97 additions and 38 deletions

View File

@ -92,6 +92,7 @@ config ARCH_X86_64
config ARCH_XTENSA
bool "Xtensa"
select ARCH_HAVE_INTERRUPTSTACK
select ARCH_HAVE_STACKCHECK
select ARCH_HAVE_CUSTOMOPT
select ARCH_HAVE_TESTSET

View File

@ -85,18 +85,10 @@
/* Check if an interrupt stack size is configured */
#define HAVE_INTERRUPTSTACK 1
#if !defined(CONFIG_ARCH_INTERRUPTSTACK)
#ifndef CONFIG_ARCH_INTERRUPTSTACK
# define CONFIG_ARCH_INTERRUPTSTACK 0
# undef HAVE_INTERRUPTSTACK
#elif CONFIG_ARCH_INTERRUPTSTACK < 16
# warning CONFIG_ARCH_INTERRUPTSTACK is to small
# undef HAVE_INTERRUPTSTACK
#endif
#define INTERRUPTSTACK_SIZE ((CONFIG_ARCH_INTERRUPTSTACK + 15) & ~15)
#define INTERRUPT_STACKWORDS (INTERRUPTSTACK_SIZE >> 2)
/* An IDLE thread stack size for CPU0 must be defined */
@ -109,10 +101,6 @@
#define IDLETHREAD_STACKSIZE ((CONFIG_IDLETHREAD_STACKSIZE + 15) & ~15)
#define IDLETHREAD_STACKWORDS (IDLETHREAD_STACKSIZE >> 2)
/* Used for stack usage measurements */
#define STACK_COLOR 0xdeadbeef
/* In the XTENSA model, the state is copied from the stack to the TCB, but
* only a referenced is passed to get the state from the TCB.
*
@ -150,6 +138,14 @@
#define getreg32(a) (*(volatile uint32_t *)(a))
#define putreg32(v,a) (*(volatile uint32_t *)(a) = (v))
/* This is the value used to mark the stack for subsequent stack monitoring
* logic.
*/
#define STACK_COLOR 0xdeadbeef
#define INTSTACK_COLOR 0xdeadbeef
#define HEAP_COLOR 'h'
/****************************************************************************
* Public Types
****************************************************************************/
@ -181,10 +177,11 @@ extern volatile uint32_t *g_current_regs[1];
#endif
#ifdef HAVE_INTERRUPTSTACK
#if CONFIG_ARCH_INTERRUPTSTACK > 15
/* The (optional) interrupt stack */
extern uint32_t g_intstack[INTERRUPT_STACKWORDS];
extern uint32_t g_intstackalloc; /* Allocated interrupt stack */
extern uint32_t g_intstackbase; /* Initial top of interrupt stack */
#endif
/* Address of the CPU0 IDLE thread */

View File

@ -197,16 +197,16 @@ ssize_t up_check_stack_remain(void)
return up_check_tcbstack_remain(this_task());
}
#if CONFIG_ARCH_INTERRUPTSTACK > 3
#if CONFIG_ARCH_INTERRUPTSTACK > 15
size_t up_check_intstack(void)
{
return do_stackcheck((uintptr_t)&g_intstackalloc,
(CONFIG_ARCH_INTERRUPTSTACK & ~3));
(CONFIG_ARCH_INTERRUPTSTACK & ~15));
}
size_t up_check_intstack_remain(void)
{
return (CONFIG_ARCH_INTERRUPTSTACK & ~3) - up_check_intstack();
return (CONFIG_ARCH_INTERRUPTSTACK & ~15) - up_check_intstack();
}
#endif

View File

@ -163,7 +163,7 @@ void xtensa_dumpstate(void)
uint32_t sp = xtensa_getsp();
uint32_t ustackbase;
uint32_t ustacksize;
#ifdef HAVE_INTERRUPTSTACK
#if CONFIG_ARCH_INTERRUPTSTACK > 15
uint32_t istackbase;
uint32_t istacksize;
#endif
@ -185,10 +185,9 @@ void xtensa_dumpstate(void)
/* Get the limits on the interrupt stack memory */
#warning REVISIT interrupt stack
#ifdef HAVE_INTERRUPTSTACK
istackbase = (uint32_t)&g_intstack[INTERRUPT_STACKWORDS - 1];
istacksize = INTERRUPTSTACK_SIZE;
#if CONFIG_ARCH_INTERRUPTSTACK > 15
istackbase = (uint32_t)&g_intstackbase;
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~15);
/* Show interrupt stack info */
@ -214,7 +213,7 @@ void xtensa_dumpstate(void)
* at the base of the interrupt stack.
*/
sp = &g_instack[INTERRUPTSTACK_SIZE - sizeof(uint32_t)];
sp = g_intstackbase - sizeof(uint32_t);
_alert("sp: %08x\n", sp);
}
else if (CURRENT_REGS)

View File

@ -58,6 +58,36 @@
#include "xtensa.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: xtensa_color_intstack
*
* Description:
* Set the interrupt stack to a value so that later we can determine how
* much stack space was used by interrupt handling logic
*
****************************************************************************/
#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 15
static inline void xtensa_color_intstack(void)
{
ssize_t size;
uint32_t *ptr = (uint32_t *)&g_intstackalloc;
for (size = (CONFIG_ARCH_INTERRUPTSTACK & ~15);
size > 0;
size -= sizeof(uint32_t))
{
*ptr++ = INTSTACK_COLOR;
}
}
#else
# define xtensa_color_intstack()
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -81,6 +111,8 @@
void up_initialize(void)
{
xtensa_color_intstack();
#ifdef CONFIG_SMP
int i;

View File

@ -68,6 +68,19 @@
#include "chip_macros.h"
#include "xtensa_timer.h"
#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
.data
.align 16
.global g_intstackalloc
.global g_intstackbase
.type g_intstackalloc, @object
.type g_intstackbase, @object
g_intstackalloc:
.skip ((CONFIG_ARCH_INTERRUPTSTACK + 15) & ~15)
g_intstackbase:
.size g_intstackalloc, .-g_intstackalloc
#endif
/****************************************************************************
* Assembly Language Macros
****************************************************************************/
@ -91,6 +104,21 @@
addi \aout, \aout, 1 /* Return aout + 1 */
.endm
/************************************************************************************
* Name: setintstack
*
* Description:
* Set the current stack pointer to the "top" the interrupt stack. Single CPU
* case. Must be provided by MCU-specific logic in the SMP case.
*
************************************************************************************/
#if !defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15
.macro setintstack
movi a1, g_intstackbase
.endm
#endif
/****************************************************************************
* Macro dispatch_c_isr level mask
*
@ -112,6 +140,7 @@
* Entry Conditions/Side Effects:
* level - interrupt level
* mask - interrupt bitmask for this level
* a12 - register save area
*
* Exit Conditions:
* This macro will use registers a0 and a2-a5 and a12.
@ -122,12 +151,6 @@
.macro dispatch_c_isr level mask
/* Initially the register save area is in SP, but that could change as
* a consequence of context switching.
*/
mov a12, sp /* Address of save area */
#ifdef __XTENSA_CALL0_ABI__
/* Get mask of pending, enabled interrupts at this level into a2. */
@ -143,7 +166,7 @@
*/
/* Argument 1: Set of CPU interrupt to dispatch */
mov a3, sp /* Argument 2: Top of stack = register save area */
mov a3, a12 /* Argument 2: Top of stack = register save area */
call0 xtensa_int_decode /* Call xtensa_int_decode */
/* On return from xtensa_int_decode, a2 will contain the address of the new
@ -169,7 +192,7 @@
*/
/* Argument 1: Set of CPU interrupt to dispatch */
mov a7, sp /* Argument 2: Top of stack = register save area */
mov a7, a12 /* Argument 2: Top of stack = register save area */
call4 xtensa_int_decode /* Call xtensa_int_decode */
/* On return from xtensa_int_decode, a6 will contain the address of the new
@ -263,6 +286,19 @@ _xtensa_level1_handler:
mov a2, sp /* Address of state save on stack */
call0 _xtensa_context_save /* Save full register state */
/* Save current SP before (possibly) overwriting it, it's the register save
* area. This value will be used later by dispatch_c_isr to retrive the
* register save area.
*/
mov a12, sp
/* Switch to an interrupt stack if we have one */
#if CONFIG_ARCH_INTERRUPTSTACK > 15
setintstack
#endif
/* Set up PS for C, enable interrupts above this level and clear EXCM. */
ps_setup 1 a0

View File

@ -142,12 +142,6 @@ void up_irqinitialize(void)
esp32_cpuint_initialize();
#if defined(CONFIG_STACK_COLORATION) && defined(HAVE_INTERRUPTSTACK)
/* Colorize the interrupt stack for debug purposes */
#warning Missing logic
#endif
/* Attach and enable internal interrupts */
#ifdef CONFIG_SMP