xtensa: Implement syscalls required for Protected Mode
Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
parent
9072eecc30
commit
be9fc59b07
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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> */
|
||||
|
104
arch/xtensa/src/common/xtensa_dispatch_syscall.S
Normal file
104
arch/xtensa/src/common/xtensa_dispatch_syscall.S
Normal 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 */
|
76
arch/xtensa/src/common/xtensa_pthread_start.c
Normal file
76
arch/xtensa/src/common/xtensa_pthread_start.c
Normal 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 */
|
75
arch/xtensa/src/common/xtensa_signal_dispatch.c
Normal file
75
arch/xtensa/src/common/xtensa_signal_dispatch.c
Normal 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__ */
|
86
arch/xtensa/src/common/xtensa_signal_handler.S
Normal file
86
arch/xtensa/src/common/xtensa_signal_handler.S
Normal 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__ */
|
@ -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
|
||||
|
73
arch/xtensa/src/common/xtensa_task_start.c
Normal file
73
arch/xtensa/src/common/xtensa_task_start.c
Normal 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 */
|
Loading…
Reference in New Issue
Block a user