Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xtensa: some fixes in interrupt handler #5248

Merged
merged 5 commits into from Jan 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
138 changes: 138 additions & 0 deletions arch/xtensa/src/common/svcall.h
@@ -0,0 +1,138 @@
/****************************************************************************
* arch/xtensa/src/common/svcall.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

#ifndef __ARCH_XTENSA_SRC_COMMON_SVCALL_H
#define __ARCH_XTENSA_SRC_COMMON_SVCALL_H

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#ifdef CONFIG_LIB_SYSCALL
# include <syscall.h>
#endif

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/* Configuration ************************************************************/

/* This logic uses three system calls {0,1,2} for context switching and one
* for the syscall return. So a minimum of four syscall values must be
* reserved. If CONFIG_BUILD_PROTECTED is defined, then four more syscall
* values must be reserved.
*/

#ifdef CONFIG_LIB_SYSCALL
# ifdef CONFIG_BUILD_PROTECTED
# ifndef CONFIG_SYS_RESERVED
# error "CONFIG_SYS_RESERVED must be defined to have the value 9"
# elif CONFIG_SYS_RESERVED != 9
# error "CONFIG_SYS_RESERVED must have the value 9"
# endif
# else
# ifndef CONFIG_SYS_RESERVED
# error "CONFIG_SYS_RESERVED must be defined to have the value 4"
# elif CONFIG_SYS_RESERVED != 4
# error "CONFIG_SYS_RESERVED must have the value 4"
# endif
# endif
#endif

/* Xtensa system calls ******************************************************/

/* SYS call 0:
*
* int xtensa_saveusercontext(uint32_t *saveregs);
*/

#define SYS_save_context (0)

/* SYS call 1:
*
* void xtensa_fullcontextrestore(uint32_t *restoreregs) noreturn_function;
*/

#define SYS_restore_context (1)

/* SYS call 2:
*
* void xtensa_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
*/

#define SYS_switch_context (2)

#ifndef CONFIG_BUILD_FLAT
#ifdef CONFIG_LIB_SYSCALL
/* SYS call 3:
*
* void xtensa_syscall_return(void);
*/

#define SYS_syscall_return (3)

#ifdef CONFIG_BUILD_PROTECTED
/* SYS call 4:
*
* void up_task_start(main_t taskentry, int argc, char *argv[])
* noreturn_function;
*/

#define SYS_task_start (4)
/* SYS call 6:
*
* void signal_handler(_sa_sigaction_t sighand, int signo,
* siginfo_t *info, void *ucontext);
*/

#define SYS_signal_handler (6)

/* SYS call 7:
*
* void signal_handler_return(void);
*/

#define SYS_signal_handler_return (7)

#endif /* CONFIG_BUILD_PROTECTED */

/* SYS call 5:
*
* void up_pthread_start(pthread_trampoline_t startup,
* pthread_startroutine_t entrypt, pthread_addr_t arg)
* noreturn_function
*/

#define SYS_pthread_start (5)

/* SYS call 8:
*
* void up_pthread_exit(pthread_exitroutine_t exit, void *exit_value)
*/

#define SYS_pthread_exit (8)

#endif /* !CONFIG_BUILD_FLAT */
#endif /* CONFIG_LIB_SYSCALL */

#endif /* __ARCH_XTENSA_SRC_COMMON_SVCALL_H */
6 changes: 6 additions & 0 deletions arch/xtensa/src/common/xtensa.h
Expand Up @@ -341,6 +341,12 @@ void xtensa_pminitialize(void);
# define xtensa_pminitialize()
#endif

/* Interrupt handling *******************************************************/

/* Exception Handlers */

int xtensa_svcall(int irq, void *context, void *arg);

/* Debug ********************************************************************/

#ifdef CONFIG_STACK_COLORATION
Expand Down
1 change: 0 additions & 1 deletion arch/xtensa/src/common/xtensa_context.S
Expand Up @@ -115,7 +115,6 @@

_xtensa_context_save:

s32i a3, a2, (4 * REG_A3)
s32i a4, a2, (4 * REG_A4)
s32i a5, a2, (4 * REG_A5)
s32i a6, a2, (4 * REG_A6)
Expand Down
6 changes: 6 additions & 0 deletions arch/xtensa/src/common/xtensa_int_handlers.S
Expand Up @@ -312,6 +312,7 @@ _xtensa_level1_handler:

s32i a2, sp, (4 * REG_A2)
mov a2, sp /* Address of state save on stack */
s32i a3, sp, (4 * REG_A3)
Ouss4 marked this conversation as resolved.
Show resolved Hide resolved
call0 _xtensa_context_save /* Save full register state */

/* Save current SP before (possibly) overwriting it, it's the register save
Expand Down Expand Up @@ -415,6 +416,7 @@ _xtensa_level2_handler:

s32i a2, sp, (4 * REG_A2)
mov a2, sp /* Address of state save on stack */
s32i a3, sp, (4 * REG_A3)
call0 _xtensa_context_save /* Save full register state */

/* Save current SP before (possibly) overwriting it, it's the register save
Expand Down Expand Up @@ -493,6 +495,7 @@ _xtensa_level3_handler:

s32i a2, sp, (4 * REG_A2)
mov a2, sp /* Address of state save on stack */
s32i a3, sp, (4 * REG_A3)
call0 _xtensa_context_save /* Save full register state */

/* Save current SP before (possibly) overwriting it, it's the register save
Expand Down Expand Up @@ -571,6 +574,7 @@ _xtensa_level4_handler:

s32i a2, sp, (4 * REG_A2)
mov a2, sp /* Address of state save on stack */
s32i a3, sp, (4 * REG_A3)
call0 _xtensa_context_save /* Save full register state */

/* Save current SP before (possibly) overwriting it, it's the register save
Expand Down Expand Up @@ -649,6 +653,7 @@ _xtensa_level5_handler:

s32i a2, sp, (4 * REG_A2)
mov a2, sp /* Address of state save on stack */
s32i a3, sp, (4 * REG_A3)
call0 _xtensa_context_save /* Save full register state */

/* Save current SP before (possibly) overwriting it, it's the register save
Expand Down Expand Up @@ -727,6 +732,7 @@ _xtensa_level6_handler:

s32i a2, sp, (4 * REG_A2)
mov a2, sp /* Address of state save on stack */
s32i a3, sp, (4 * REG_A3)
call0 _xtensa_context_save /* Save full register state */

/* Save current SP before (possibly) overwriting it, it's the register save
Expand Down
10 changes: 8 additions & 2 deletions arch/xtensa/src/common/xtensa_panic.S
Expand Up @@ -127,8 +127,13 @@ _xtensa_panic:
*/

mov a2, sp /* Address of state save on stack */
s32i a3, sp, (4 * REG_A3)
call0 _xtensa_context_save /* Save full register state */

/* Dispatch the sycall as with other interrupts. */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* Dispatch the sycall as with other interrupts. */
/* Dispatch the syscall as with other interrupts. */


mov a12, sp /* a12 = address of register save area */

/* Switch to an interrupt stack if we have one */

#if CONFIG_ARCH_INTERRUPTSTACK > 15
Expand All @@ -151,18 +156,19 @@ _xtensa_panic:
#endif

wsr a0, PS
rsync

/* Call C panic handler: Arg1 (A2) = Exception code; Arg 2 (A3) = start
* of the register save area.
*/

#ifdef __XTENSA_CALL0_ABI__
rsr a2, EXCSAVE_1
mov a3, sp
mov a3, a12
call0 xtensa_panic /* Call xtensa_panic. Should not return */
#else
rsr a6, EXCSAVE_1
mov a7, sp
mov a7, a12
call4 xtensa_panic /* Call xtensa_panic. Should not return */
#endif

Expand Down
136 changes: 136 additions & 0 deletions arch/xtensa/src/common/xtensa_svcall.c
@@ -0,0 +1,136 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_svcall.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include <stdint.h>
#include <assert.h>
#include <debug.h>

#include <nuttx/arch.h>
#include <arch/xtensa/xtensa_specregs.h>

#include "svcall.h"
#include "xtensa.h"

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: xtensa_svcall
*
* Description:
* This is SVCall exception handler that performs context switching
*
****************************************************************************/

int xtensa_svcall(int irq, void *context, void *arg)
{
uint32_t *regs = (uint32_t *)context;
uint32_t cmd;

DEBUGASSERT(regs && regs == CURRENT_REGS);
cmd = regs[REG_A2];

/* The SVCall software interrupt is called with A2 = system call command
* and A3..A9 = variable number of arguments depending on the system call.
*/

#ifdef CONFIG_DEBUG_SYSCALL_INFO
# ifndef CONFIG_DEBUG_SVCALL
if (cmd > SYS_switch_context)
# endif
{
svcinfo("SVCALL Entry: regs: %p cmd: %d\n", regs, cmd);
svcinfo(" A0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
regs[REG_A0], regs[REG_A1], regs[REG_A2], regs[REG_A3],
regs[REG_A4], regs[REG_A5], regs[REG_A6], regs[REG_A7]);
svcinfo(" A8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
regs[REG_A8], regs[REG_A9], regs[REG_A10], regs[REG_A11],
regs[REG_A12], regs[REG_A13], regs[REG_A14], regs[REG_A15]);
svcinfo(" PC: %08x PS: %08x\n",
regs[REG_PC], regs[REG_PS]);
}
#endif

/* Handle the SVCall according to the command in A2 */

switch (cmd)
{
/* A2=SYS_save_context: This is a save context command:
*
* int xtensa_saveusercontext(uint32_t *saveregs);
*
* At this point, the following values are saved in context:
*
* A2 = SYS_save_context
* A3 = saveregs
*
* In this case, we simply need to copy the current registers to the
* save register space references in the saved A3 and return.
*/

case SYS_save_context:
{
}
break;
}

/* Report what happened. That might difficult in the case of a context
* switch.
*/

#ifdef CONFIG_DEBUG_SYSCALL_INFO
# ifndef CONFIG_DEBUG_SVCALL
if (cmd > SYS_switch_context)
# else
if (regs != CURRENT_REGS)
# endif
{
svcinfo("SVCall Return:\n");
svcinfo(" A0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
CURRENT_REGS[REG_A0], CURRENT_REGS[REG_A1],
CURRENT_REGS[REG_A2], CURRENT_REGS[REG_A3],
CURRENT_REGS[REG_A4], CURRENT_REGS[REG_A5],
CURRENT_REGS[REG_A6], CURRENT_REGS[REG_A7]);
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
CURRENT_REGS[REG_A8], CURRENT_REGS[REG_A9],
CURRENT_REGS[REG_A10], CURRENT_REGS[REG_A11],
CURRENT_REGS[REG_A12], CURRENT_REGS[REG_A13],
CURRENT_REGS[REG_A14], CURRENT_REGS[REG_A15]);
svcinfo(" PC: %08x PS: %08x\n",
regs[REG_PC], regs[REG_PS]);
}
# ifdef CONFIG_DEBUG_SVCALL
else
{
svcinfo("SVCall Return: %d\n", regs[REG_A0]);
}
# endif
#endif

return OK;
}