diff --git a/arch/xtensa/include/syscall.h b/arch/xtensa/include/syscall.h index d43d8855a7d..be0c239ac45 100644 --- a/arch/xtensa/include/syscall.h +++ b/arch/xtensa/include/syscall.h @@ -29,21 +29,119 @@ * Included Files ****************************************************************************/ +#include +#include +#ifndef __ASSEMBLY__ +# include +# include +#endif +#ifdef CONFIG_LIB_SYSCALL +# include +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/**************************************************************************** - * Public Types - ****************************************************************************/ +/* Configuration ************************************************************/ -/**************************************************************************** - * Inline functions - ****************************************************************************/ +/* 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. + */ -/**************************************************************************** - * Public Data - ****************************************************************************/ +#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 */ /**************************************************************************** * Public Function Prototypes diff --git a/arch/xtensa/src/common/svcall.h b/arch/xtensa/src/common/svcall.h deleted file mode 100644 index 01701957d01..00000000000 --- a/arch/xtensa/src/common/svcall.h +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************************** - * 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 - -#ifdef CONFIG_LIB_SYSCALL -# include -#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 */ diff --git a/arch/xtensa/src/common/xtensa.h b/arch/xtensa/src/common/xtensa.h index b20a52c9417..fe1dadc5762 100644 --- a/arch/xtensa/src/common/xtensa.h +++ b/arch/xtensa/src/common/xtensa.h @@ -337,7 +337,7 @@ void xtensa_pminitialize(void); /* Exception Handlers */ -int xtensa_svcall(int irq, void *context, void *arg); +int xtensa_swint(int irq, void *context, void *arg); /* Debug ********************************************************************/ diff --git a/arch/xtensa/src/common/xtensa_swi.h b/arch/xtensa/src/common/xtensa_swi.h new file mode 100644 index 00000000000..be73139253d --- /dev/null +++ b/arch/xtensa/src/common/xtensa_swi.h @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/xtensa/src/common/xtensa_swi.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_XTENSA_SWI_H +#define __ARCH_XTENSA_SRC_COMMON_XTENSA_SWI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Select software interrupt number for context-switch. + * The SW interrupt level must be greater than XCHAL_SYSCALL_LEVEL + * and less than XCHAL_EXCM_LEVEL. + * So that we can generate an interrupt when up_irq_save is called. + * and not generate interrupt when up_irq_disable is called. + * Return an error if no suitable software interrupt was found. + */ + +#ifndef XTENSA_SWINT +# ifdef XCHAL_SOFTWARE2_INTERRUPT +# if XCHAL_INT_LEVEL(XCHAL_SOFTWARE2_INTERRUPT) > XCHAL_SYSCALL_LEVEL && \ + XCHAL_INT_LEVEL(XCHAL_SOFTWARE2_INTERRUPT) <= XCHAL_EXCM_LEVEL +# undef XTENSA_SWINT +# define XTENSA_SWINT XCHAL_SOFTWARE2_INTERRUPT +# endif +# endif +# ifdef XCHAL_SOFTWARE1_INTERRUPT +# if XCHAL_INT_LEVEL(XCHAL_SOFTWARE1_INTERRUPT) > XCHAL_SYSCALL_LEVEL && \ + XCHAL_INT_LEVEL(XCHAL_SOFTWARE1_INTERRUPT) <= XCHAL_EXCM_LEVEL +# undef XTENSA_SWINT +# define XTENSA_SWINT XCHAL_SOFTWARE1_INTERRUPT +# endif +# endif +# ifdef XCHAL_SOFTWARE0_INTERRUPT +# if XCHAL_INT_LEVEL(XCHAL_SOFTWARE0_INTERRUPT) > XCHAL_SYSCALL_LEVEL && \ + XCHAL_INT_LEVEL(XCHAL_SOFTWARE0_INTERRUPT) <= XCHAL_EXCM_LEVEL +# undef XTENSA_SWINT +# define XTENSA_SWINT XCHAL_SOFTWARE0_INTERRUPT +# endif +# endif +#endif +#ifndef XTENSA_SWINT +# error "There is no suitable sw interrupt in this Xtensa configuration." +#endif + +#define XCHAL_SWINT_CALL (1 << XTENSA_SWINT) + +#endif /* __ARCH_XTENSA_SRC_COMMON_XTENSA_SWI_H */ diff --git a/arch/xtensa/src/common/xtensa_svcall.c b/arch/xtensa/src/common/xtensa_swint.c similarity index 55% rename from arch/xtensa/src/common/xtensa_svcall.c rename to arch/xtensa/src/common/xtensa_swint.c index ab87f5cde32..bacdc5f7674 100644 --- a/arch/xtensa/src/common/xtensa_svcall.c +++ b/arch/xtensa/src/common/xtensa_swint.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/xtensa/src/common/xtensa_svcall.c + * arch/xtensa/src/common/xtensa_swint.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -31,7 +31,7 @@ #include #include -#include "svcall.h" +#include "syscall.h" #include "xtensa.h" /**************************************************************************** @@ -39,31 +39,39 @@ ****************************************************************************/ /**************************************************************************** - * Name: xtensa_svcall + * Name: xtensa_swint * * Description: - * This is SVCall exception handler that performs context switching + * This is software interrupt exception handler that performs context + * switching and manages system calls * ****************************************************************************/ -int xtensa_svcall(int irq, void *context, void *arg) +int xtensa_swint(int irq, void *context, void *arg) { uint32_t *regs = (uint32_t *)context; uint32_t cmd; +#if XCHAL_CP_NUM > 0 + uintptr_t cpstate; + uint32_t cpstate_off; + + cpstate_off = offsetof(struct xcptcontext, cpstate) - + offsetof(struct xcptcontext, regs); +#endif DEBUGASSERT(regs && regs == CURRENT_REGS); cmd = regs[REG_A2]; - /* The SVCall software interrupt is called with A2 = system call command + /* The SYSCall 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 +# ifndef CONFIG_DEBUG_SYSCALL if (cmd > SYS_switch_context) # endif { - svcinfo("SVCALL Entry: regs: %p cmd: %d\n", regs, cmd); + svcinfo("SYSCALL 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]); @@ -75,13 +83,13 @@ int xtensa_svcall(int irq, void *context, void *arg) } #endif - /* Handle the SVCall according to the command in A2 */ + /* Handle the SYSCall according to the command in A2 */ switch (cmd) { /* A2=SYS_save_context: This is a save context command: * - * int xtensa_saveusercontext(uint32_t *saveregs); + * int xtensa_saveusercontext(uint32_t *saveregs); * * At this point, the following values are saved in context: * @@ -94,8 +102,76 @@ int xtensa_svcall(int irq, void *context, void *arg) case SYS_save_context: { + DEBUGASSERT(regs[REG_A3] != 0); + memcpy((uint32_t *)regs[REG_A3], regs, (4 * XCPTCONTEXT_REGS)); +#if XCHAL_CP_NUM > 0 + cpstate = (uintptr_t)regs[REG_A3] + cpstate_off; + xtensa_coproc_savestate((struct xtensa_cpstate_s *)cpstate); +#endif } + break; + + /* A2=SYS_restore_context: This is a restore context command: + * + * void xtensa_fullcontextrestore(uint32_t *restoreregs) + * noreturn_function; + * + * At this point, the following values are saved in context: + * + * A2 = SYS_restore_context + * A3 = restoreregs + * + * In this case, we simply need to set CURRENT_REGS to restore + * register area referenced in the saved A3. context == CURRENT_REGS + * is the normal exception return. By setting CURRENT_REGS = + * context[A3], we force the return to the saved context referenced + * in A3. + */ + + case SYS_restore_context: + { +#if XCHAL_CP_NUM > 0 + cpstate = (uintptr_t)regs[REG_A3] + cpstate_off; + xtensa_coproc_restorestate((struct xtensa_cpstate_s *)cpstate); +#endif + DEBUGASSERT(regs[REG_A3] != 0); + CURRENT_REGS = (uint32_t *)regs[REG_A3]; + } + + break; + + /* A2=SYS_switch_context: This is a switch context command: + * + * void xtensa_switchcontext + * (uint32_t *saveregs, uint32_t *restoreregs); + * + * At this point, the following values are saved in context: + * + * A2 = SYS_switch_context + * A3 = saveregs + * A4 = restoreregs + * + * In this case, we do both: We save the context registers to the save + * register area reference by the saved contents of A3 and then set + * CURRENT_REGS to the save register area referenced by the saved + * contents of A4. + */ + + case SYS_switch_context: + { + DEBUGASSERT(regs[REG_A3] != 0 && regs[REG_A4] != 0); + + memcpy((uint32_t *)regs[REG_A3], regs, (4 * XCPTCONTEXT_REGS)); + CURRENT_REGS = (uint32_t *)regs[REG_A4]; + } + + break; + } + + if ((CURRENT_REGS[REG_PS] & PS_EXCM_MASK) != 0) + { + CURRENT_REGS[REG_PS] &= ~PS_EXCM_MASK; } /* Report what happened. That might difficult in the case of a context @@ -103,13 +179,13 @@ int xtensa_svcall(int irq, void *context, void *arg) */ #ifdef CONFIG_DEBUG_SYSCALL_INFO -# ifndef CONFIG_DEBUG_SVCALL +# ifndef CONFIG_DEBUG_SYSCALL if (cmd > SYS_switch_context) # else if (regs != CURRENT_REGS) # endif { - svcinfo("SVCall Return:\n"); + svcinfo("SYSCall 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], @@ -123,14 +199,13 @@ int xtensa_svcall(int irq, void *context, void *arg) svcinfo(" PC: %08x PS: %08x\n", regs[REG_PC], regs[REG_PS]); } -# ifdef CONFIG_DEBUG_SVCALL +# ifdef CONFIG_DEBUG_SYSCALL else { - svcinfo("SVCall Return: %d\n", regs[REG_A0]); + svcinfo("SYSCall Return: %d\n", regs[REG_A2]); } # endif #endif return OK; } -