diff --git a/arch/xtensa/src/common/svcall.h b/arch/xtensa/src/common/svcall.h new file mode 100644 index 0000000000..01701957d0 --- /dev/null +++ b/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 + +#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 969fa5ce15..eb53489ba3 100644 --- a/arch/xtensa/src/common/xtensa.h +++ b/arch/xtensa/src/common/xtensa.h @@ -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 diff --git a/arch/xtensa/src/common/xtensa_svcall.c b/arch/xtensa/src/common/xtensa_svcall.c new file mode 100644 index 0000000000..ab87f5cde3 --- /dev/null +++ b/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 + +#include +#include +#include + +#include +#include + +#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; +} +