xtensa: Implement syscalls required for Protected Mode

Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
Gustavo Henrique Nihei 2022-05-11 18:53:07 -03:00 committed by Xiang Xiao
parent 9072eecc30
commit be9fc59b07
10 changed files with 745 additions and 38 deletions

View File

@ -144,6 +144,15 @@
#ifndef __ASSEMBLY__
#ifdef CONFIG_LIB_SYSCALL
/* This structure represents the return state from a system call */
struct xcpt_syscall_s
{
uintptr_t sysreturn; /* The return PC */
};
#endif
/* This struct defines the way the registers are stored. */
struct xcptcontext
@ -168,6 +177,14 @@ struct xcptcontext
uint32_t *regs;
#ifndef CONFIG_BUILD_FLAT
/* This is the saved address to use when returning from a user-space
* signal handler.
*/
uintptr_t sigreturn;
#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.

View File

@ -34,9 +34,6 @@
#ifndef __ASSEMBLY__
# include <stdint.h>
#endif
#ifdef CONFIG_LIB_SYSCALL
# include <syscall.h>
#endif
#include <arch/xtensa/core.h>
#include <arch/xtensa/xtensa_corebits.h>

View File

@ -53,6 +53,8 @@ HEAD_AOBJ = $(HEAD_ASRC:.S=$(OBJEXT))
HEAD_COBJ = $(HEAD_CSRC:.c=$(OBJEXT))
STARTUP_OBJS ?= $(HEAD_AOBJ) $(HEAD_COBJ)
# Flat build or kernel-mode objects
ASRCS = $(CHIP_ASRCS) $(CMN_ASRCS)
AOBJS = $(ASRCS:.S=$(OBJEXT))
@ -62,12 +64,34 @@ COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
OBJS = $(AOBJS) $(COBJS)
# User-mode objects
UASRCS = $(CHIP_UASRCS) $(CMN_UASRCS)
UAOBJS = $(UASRCS:.S=$(OBJEXT))
UCSRCS = $(CHIP_UCSRCS) $(CMN_UCSRCS)
UCOBJS = $(UCSRCS:.c=$(OBJEXT))
USRCS = $(UASRCS) $(UCSRCS)
UOBJS = $(UAOBJS) $(UCOBJS)
KBIN = libkarch$(LIBEXT)
BIN = libarch$(LIBEXT)
# Override in Make.defs if linker is not 'ld'
LDSTARTGROUP ?= --start-group
LDENDGROUP ?= --end-group
LDFLAGS += $(addprefix -T,$(call CONVERT_PATH,$(ARCHSCRIPT))) $(EXTRALINKCMDS)
ifeq ($(LD),$(CC))
LDSTARTGROUP ?= -Wl,--start-group
LDENDGROUP ?= -Wl,--end-group
LDFLAGS := $(addprefix -Xlinker ,$(LDFLAGS))
LDFLAGS += $(CFLAGS)
else
LDSTARTGROUP ?= --start-group
LDENDGROUP ?= --end-group
endif
BOARDMAKE = $(if $(wildcard board$(DELIM)Makefile),y,)
LIBPATHS += -L $(call CONVERT_PATH,$(TOPDIR)$(DELIM)staging)
@ -80,19 +104,30 @@ ifeq ($(BOARDMAKE),y)
LDLIBS += -lboard
endif
VPATH = chip:common:$(ARCH_SUBDIR)
VPATH += chip
VPATH += common
VPATH += $(ARCH_SUBDIR)
VPATH += $(CHIP_DIR)
all: $(STARTUP_OBJS) libarch$(LIBEXT)
.PHONY: board/libboard$(LIBEXT)
$(AOBJS) $(HEAD_AOBJ): %$(OBJEXT): %.S
$(AOBJS) $(UAOBJS) $(HEAD_AOBJ): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
$(COBJS) $(HEAD_COBJ): %$(OBJEXT): %.c
$(COBJS) $(UCOBJS) $(HEAD_COBJ): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)
libarch$(LIBEXT): $(OBJS)
ifeq ($(CONFIG_BUILD_FLAT),y)
$(BIN): $(OBJS)
$(call ARCHIVE, $@, $(OBJS))
else
$(BIN): $(UOBJS)
$(call ARCHIVE, $@, $(UOBJS))
endif
$(KBIN): $(OBJS)
$(call ARCHIVE, $@, $(OBJS))
board/libboard$(LIBEXT):
@ -147,7 +182,7 @@ makedepfile: $(CSRCS:.c=.ddc) $(ASRCS:.S=.dds) $(HEAD_CSRC:.c=.ddc) $(HEAD_ASRC:
ifeq ($(BOARDMAKE),y)
$(Q) $(MAKE) -C board depend
endif
$(Q) $(MAKE) makedepfile DEPPATH="--dep-path chip --dep-path common --dep-path $(ARCH_SUBDIR)"
$(Q) $(MAKE) makedepfile DEPPATH="$(patsubst %,--dep-path %,$(subst :, ,$(VPATH)))"
$(Q) touch $@
depend: .depend
@ -158,7 +193,8 @@ clean:
ifeq ($(BOARDMAKE),y)
$(Q) $(MAKE) -C board clean
endif
$(call DELFILE, libarch$(LIBEXT))
$(call DELFILE, $(KBIN))
$(call DELFILE, $(BIN))
$(call CLEAN)
distclean:: clean

View File

@ -289,6 +289,12 @@ void xtensa_pause_handler(void);
void _xtensa_sig_trampoline(void);
void xtensa_sig_deliver(void);
#ifdef CONFIG_LIB_SYSCALL
void xtensa_dispatch_syscall(unsigned int nbr, uintptr_t parm1,
uintptr_t parm2, uintptr_t parm3,
uintptr_t parm4, uintptr_t parm5);
#endif
/* Chip-specific functions **************************************************/
/* Chip specific functions defined in arch/xtensa/src/<chip> */

View File

@ -0,0 +1,104 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_dispatch_syscall.S
*
* 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 <arch/syscall.h>
#include <arch/xtensa/xtensa_abi.h>
#ifdef CONFIG_LIB_SYSCALL
/****************************************************************************
* File info
****************************************************************************/
.file "xtensa_dispatch_syscall.S"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: xtensa_dispatch_syscall
*
* Description:
* Call the stub function corresponding to the system call. NOTE the non-
* standard parameter passing:
*
* A2 = SYS_ call number
* A3 = parm0
* A4 = parm1
* A5 = parm2
* A6 = parm3
* A7 = parm4
* A8 = parm5
*
****************************************************************************/
.text
.global xtensa_dispatch_syscall
.type xtensa_dispatch_syscall, @function
.align 4
xtensa_dispatch_syscall:
/* Allocate parm5 in stack */
s32i a8, sp, LOCAL_OFFSET(0)
mov a11, a7 /* Move parm4 into callee's a7 */
mov a10, a6 /* Move parm3 into callee's a6 */
mov a9, a5 /* Move parm2 into callee's a5 */
mov a8, a4 /* Move parm1 into callee's a4 */
mov a7, a3 /* Move parm0 into callee's a3 */
mov a6, a2 /* Move SYS_ call number into callee's a2 */
/* Load the stub address into A3 */
movi a3, g_stublookup
slli a2, a2, 2
add a3, a3, a2
l32i a3, a3, 0
/* Call the stub */
callx4 a3
/* Move into A3 the return value from the stub */
mov a3, a6
/* Execute the SYS_signal_handler_return syscall (will not return) */
movi a2, SYS_syscall_return
movi a4, XCHAL_SWINT_CALL
wsr a4, INTSET
rsync
.size xtensa_dispatch_syscall, .-xtensa_dispatch_syscall
#endif /* CONFIG_LIB_SYSCALL */

View File

@ -0,0 +1,76 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_pthread_start.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 <assert.h>
#include <pthread.h>
#include <nuttx/arch.h>
#include <arch/syscall.h>
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) && \
!defined(CONFIG_DISABLE_PTHREAD)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_pthread_start
*
* Description:
* In this kernel mode build, this function will be called to execute a
* pthread in user-space. When the pthread is first started, a kernel-mode
* stub will first run to perform some housekeeping functions. This
* kernel-mode stub will then be called transfer control to the user-mode
* pthread.
*
* Normally the a user-mode start-up stub will also execute before the
* pthread actually starts. See libc/pthread/pthread_create.c
*
* Input Parameters:
* startup - The user-space pthread startup function
* entrypt - The user-space address of the pthread entry point
* arg - Standard argument for the pthread entry point
*
* Returned Value:
* This function should not return. It should call the user-mode start-up
* stub and that stub should call pthread_exit if/when the user pthread
* terminates.
*
****************************************************************************/
void up_pthread_start(pthread_trampoline_t startup,
pthread_startroutine_t entrypt, pthread_addr_t arg)
{
/* Let sys_call3() do all of the work */
sys_call3(SYS_pthread_start, (uintptr_t)startup, (uintptr_t)entrypt,
(uintptr_t)arg);
PANIC();
}
#endif /* !CONFIG_BUILD_FLAT && __KERNEL__ && !CONFIG_DISABLE_PTHREAD */

View File

@ -0,0 +1,75 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_signal_dispatch.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 <nuttx/arch.h>
#include <arch/syscall.h>
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_signal_dispatch
*
* Description:
* In the kernel mode build, this function will be called to execute a
* a signal handler in user-space. When the signal is delivered, a
* kernel-mode stub will first run to perform some housekeeping functions.
* This kernel-mode stub will then be called transfer control to the user
* mode signal handler by calling this function.
*
* Normally the user-mode signaling handling stub will also execute
* before the ultimate signal handler is called. See
* arch/xtensa/src/common/xtensa_signal_handler.c. This function is the
* user-space, signal handler trampoline function. It is called from
* up_signal_dispatch() in user-mode.
*
* Input Parameters:
* sighand - The address user-space signal handling function
* signo, info, and ucontext - Standard arguments to be passed to the
* signal handling function.
*
* Returned Value:
* None. This function does not return in the normal sense. It returns
* via an architecture specific system call made by up_signal_handler().
* However, this will look like a normal return by the caller of
* up_signal_dispatch.
*
****************************************************************************/
void up_signal_dispatch(_sa_sigaction_t sighand, int signo,
siginfo_t *info, void *ucontext)
{
/* Let sys_call4() do all of the work */
sys_call4(SYS_signal_handler, (uintptr_t)sighand, (uintptr_t)signo,
(uintptr_t)info, (uintptr_t)ucontext);
}
#endif /* !CONFIG_BUILD_FLAT && __KERNEL__ */

View File

@ -0,0 +1,86 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_signal_handler.S
*
* 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 <arch/syscall.h>
#if defined(CONFIG_BUILD_PROTECTED) && !defined(__KERNEL__)
/****************************************************************************
* File info
****************************************************************************/
.file "xtensa_signal_handler.S"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_signal_handler
*
* Description:
* This function is the user-space, signal handler trampoline function. It
* is called from up_signal_dispatch() in user-mode.
*
* Input Parameters:
* a2 = sighand
* The address user-space signal handling function
* a3-a5 = signo, info, and ucontext
* Standard arguments to be passed to the signal handling function.
*
* Returned Value:
* None. This function does not return in the normal sense. It returns
* via the SYS_signal_handler_return (see syscall.h)
*
****************************************************************************/
.text
.global up_signal_handler
.type up_signal_handler, @function
.align 4
up_signal_handler:
/* Call the signal handler */
mov a6, a3 /* Move signo into callee's a2 */
mov a7, a4 /* Move info into callee's a3 */
mov a8, a5 /* Move ucontext into callee's a4 */
callx4 a2 /* Call the signal handler */
/* Execute the SYS_signal_handler_return syscall (will not return) */
movi a2, SYS_signal_handler_return
movi a3, XCHAL_SWINT_CALL
wsr a3, INTSET
rsync
.size up_signal_handler, .-up_signal_handler
#endif /* CONFIG_BUILD_PROTECTED && !__KERNEL__ */

View File

@ -30,10 +30,33 @@
#include <nuttx/arch.h>
#include <arch/xtensa/xtensa_specregs.h>
#include <sys/syscall.h>
#include "signal/signal.h"
#include "syscall.h"
#include "xtensa.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: xtensa_registerdump
****************************************************************************/
#ifdef CONFIG_DEBUG_SYSCALL_INFO
static void xtensa_registerdump(const uintptr_t *regs)
{
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
/****************************************************************************
* Public Functions
****************************************************************************/
@ -52,10 +75,11 @@ int xtensa_swint(int irq, void *context, void *arg)
uint32_t *regs = (uint32_t *)context;
uint32_t cmd;
DEBUGASSERT(regs && regs == CURRENT_REGS);
DEBUGASSERT(regs != NULL && regs == CURRENT_REGS);
cmd = regs[REG_A2];
/* The SYSCall 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.
*/
@ -65,18 +89,11 @@ int xtensa_swint(int irq, void *context, void *arg)
# endif
{
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]);
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]);
xtensa_registerdump(regs);
}
#endif
/* Handle the SYSCall according to the command in A2 */
/* Handle the syscall according to the command in A2 */
switch (cmd)
{
@ -98,7 +115,6 @@ int xtensa_swint(int irq, void *context, void *arg)
DEBUGASSERT(regs[REG_A3] != 0);
memcpy((uint32_t *)regs[REG_A3], regs, XCPTCONTEXT_SIZE);
}
break;
/* A2=SYS_restore_context: This is a restore context command:
@ -123,7 +139,6 @@ int xtensa_swint(int irq, void *context, void *arg)
DEBUGASSERT(regs[REG_A3] != 0);
CURRENT_REGS = (uint32_t *)regs[REG_A3];
}
break;
/* A2=SYS_switch_context: This is a switch context command:
@ -149,7 +164,240 @@ int xtensa_swint(int irq, void *context, void *arg)
*(uint32_t **)regs[REG_A3] = regs;
CURRENT_REGS = (uint32_t *)regs[REG_A4];
}
break;
/* A2=SYS_syscall_return: This is a syscall return command:
*
* void up_syscall_return(void);
*
* At this point, the following values are saved in context:
*
* A2 = SYS_syscall_return
*
* We need to restore the saved return address and return in
* unprivileged thread mode.
*/
#ifdef CONFIG_LIB_SYSCALL
case SYS_syscall_return:
{
struct tcb_s *rtcb = nxsched_self();
int index = (int)rtcb->xcp.nsyscalls - 1;
/* Make sure that there is a saved syscall return address. */
DEBUGASSERT(index >= 0);
/* Setup to return to the saved syscall return address in
* the original mode.
*/
regs[REG_PC] = rtcb->xcp.syscall[index].sysreturn;
/* The return value must be in A2-A5.
* xtensa_dispatch_syscall() temporarily moved the value into A3.
*/
regs[REG_A2] = regs[REG_A3];
/* Save the new syscall nesting level */
rtcb->xcp.nsyscalls = index;
/* Handle any signal actions that were deferred while processing
* the system call.
*/
rtcb->flags &= ~TCB_FLAG_SYSCALL;
nxsig_unmask_pendingsignal();
}
break;
#endif
/* A2=SYS_task_start: This a user task start
*
* void up_task_start(main_t taskentry, int argc,
* char *argv[]) noreturn_function;
*
* At this point, the following values are saved in context:
*
* A2 = SYS_task_start
* A3 = taskentry
* A4 = argc
* A5 = argv
*/
#ifndef CONFIG_BUILD_FLAT
case SYS_task_start:
{
/* Set up to return to the user-space task start-up function in
* unprivileged mode.
*/
#ifdef CONFIG_BUILD_PROTECTED
/* Use the nxtask_startup trampoline function */
regs[REG_PC] = (uintptr_t)USERSPACE->task_startup;
regs[REG_A6] = regs[REG_A3]; /* Task entry */
regs[REG_A7] = regs[REG_A4]; /* argc */
regs[REG_A8] = regs[REG_A5]; /* argv */
#else
/* Start the user task directly */
regs[REG_PC] = (uintptr_t)regs[REG_A3];
regs[REG_A6] = regs[REG_A4]; /* argc */
regs[REG_A7] = regs[REG_A5]; /* argv */
#endif
/* User task rotates window, so pretend task was 'call4'd */
regs[REG_PS] = PS_UM | PS_WOE | PS_CALLINC(1);
}
break;
#endif
/* A2=SYS_pthread_start: This a user pthread start
*
* void up_pthread_start(pthread_startroutine_t entrypt,
* pthread_addr_t arg) noreturn_function;
*
* At this point, the following values are saved in context:
*
* A2 = SYS_pthread_start
* A3 = startup
* A4 = entrypt
* A5 = arg
*/
#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
case SYS_pthread_start:
{
/* Set up to return to the user-space pthread start-up function in
* unprivileged mode.
*/
regs[REG_PC] = (uintptr_t)regs[REG_A3]; /* startup */
/* Change the parameter ordering to match the expectation of the
* user space pthread_startup:
*/
regs[REG_A6] = regs[REG_A4]; /* pthread entry */
regs[REG_A7] = regs[REG_A5]; /* arg */
/* Startup task rotates window, so pretend task was 'call4'd */
regs[REG_PS] = PS_UM | PS_WOE | PS_CALLINC(1);
}
break;
#endif
/* A2=SYS_signal_handler: This a user signal handler callback
*
* void signal_handler(_sa_sigaction_t sighand, int signo,
* siginfo_t *info, void *ucontext);
*
* At this point, the following values are saved in context:
*
* A2 = SYS_signal_handler
* A3 = sighand
* A4 = signo
* A5 = info
* A6 = ucontext
*/
#ifndef CONFIG_BUILD_FLAT
case SYS_signal_handler:
{
struct tcb_s *rtcb = nxsched_self();
/* Remember the caller's return address */
DEBUGASSERT(rtcb->xcp.sigreturn == 0);
rtcb->xcp.sigreturn = regs[REG_PC];
/* Set up to return to the user-space trampoline function in
* unprivileged mode.
*/
regs[REG_PC] = (uintptr_t)USERSPACE->signal_handler;
/* Change the parameter ordering to match the expectation of struct
* userpace_s signal_handler.
*/
regs[REG_A2] = regs[REG_A3]; /* sighand */
regs[REG_A3] = regs[REG_A4]; /* signal */
regs[REG_A4] = regs[REG_A5]; /* info */
regs[REG_A5] = regs[REG_A6]; /* ucontext */
}
break;
#endif
/* A2=SYS_signal_handler_return: This a user signal handler callback
*
* void signal_handler_return(void);
*
* At this point, the following values are saved in context:
*
* A2 = SYS_signal_handler_return
*/
#ifndef CONFIG_BUILD_FLAT
case SYS_signal_handler_return:
{
struct tcb_s *rtcb = nxsched_self();
/* Set up to return to the kernel-mode signal dispatching logic. */
DEBUGASSERT(rtcb->xcp.sigreturn != 0);
regs[REG_PC] = rtcb->xcp.sigreturn;
rtcb->xcp.sigreturn = 0;
}
break;
#endif
/* This is not an architecture-specific system call. If NuttX is built
* as a standalone kernel with a system call interface, then all of the
* additional system calls must be handled as in the default case.
*/
default:
{
#ifdef CONFIG_LIB_SYSCALL
struct tcb_s *rtcb = nxsched_self();
int index = rtcb->xcp.nsyscalls;
/* Verify that the syscall number is within range */
DEBUGASSERT(cmd < SYS_maxsyscall);
/* Make sure that we got here that there is a no saved syscall
* return address. We cannot yet handle nested system calls.
*/
DEBUGASSERT(index < CONFIG_SYS_NNEST);
/* Setup to return to xtensa_dispatch_syscall in privileged mode. */
rtcb->xcp.syscall[index].sysreturn = regs[REG_PC];
rtcb->xcp.nsyscalls = index + 1;
regs[REG_PC] = (uintptr_t)xtensa_dispatch_syscall;
/* Offset A2 to account for the reserved values */
regs[REG_A2] -= CONFIG_SYS_RESERVED;
/* Indicate that we are in a syscall handler. */
rtcb->flags |= TCB_FLAG_SYSCALL;
#else
svcerr("ERROR: Bad SYSCALL: %" PRIu32 "\n", cmd);
#endif
}
break;
/* A2=SYS_flush_context: This flush windows to the stack:
@ -186,24 +434,13 @@ int xtensa_swint(int irq, void *context, void *arg)
if (regs != CURRENT_REGS)
# endif
{
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],
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]);
svcinfo("SYSCALL Return: Context switch!\n");
xtensa_registerdump((const uintptr_t *)CURRENT_REGS);
}
# ifdef CONFIG_DEBUG_SYSCALL
else
{
svcinfo("SYSCall Return: %d\n", regs[REG_A2]);
svcinfo("SYSCALL Return: %" PRIu32 "\n", cmd);
}
# endif
#endif

View File

@ -0,0 +1,73 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_task_start.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 <assert.h>
#include <nuttx/arch.h>
#include <arch/syscall.h>
#ifndef CONFIG_BUILD_FLAT
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_task_start
*
* Description:
* In this kernel mode build, this function will be called to execute a
* task in user-space. When the task is first started, a kernel-mode
* stub will first run to perform some housekeeping functions. This
* kernel-mode stub will then be called transfer control to the user-mode
* task.
*
* Normally the a user-mode start-up stub will also execute before the
* task actually starts. See libc/sched/task_startup.c
*
* Input Parameters:
* taskentry - The user-space entry point of the task.
* argc - The number of parameters being passed.
* argv - The parameters being passed. These lie in kernel-space memory
* and will have to be reallocated in user-space memory.
*
* Returned Value:
* This function should not return. It should call the user-mode start-up
* stub and that stub should call exit if/when the user task terminates.
*
****************************************************************************/
void up_task_start(main_t taskentry, int argc, char *argv[])
{
/* Let sys_call3() do all of the work */
sys_call3(SYS_task_start, (uintptr_t)taskentry, (uintptr_t)argc,
(uintptr_t)argv);
PANIC();
}
#endif /* !CONFIG_BUILD_FLAT */