mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 01:05:54 +08:00
arch: risc-v: Add support for PROTECTED build to rv64gc
This commit is contained in:
committed by
patacongo
parent
ddc8f52202
commit
1a4ff4c4cd
@@ -285,10 +285,13 @@
|
||||
|
||||
/* This structure represents the return state from a system call */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
struct xcpt_syscall_s
|
||||
{
|
||||
uint64_t sysreturn; /* The return PC */
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
uint64_t int_ctx; /* Interrupt context (i.e. mstatus) */
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -316,7 +319,7 @@ struct xcptcontext
|
||||
uint64_t saved_epc; /* Trampoline PC */
|
||||
uint64_t saved_int_ctx; /* Interrupt context with interrupts disabled. */
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
/* This is the saved address to use when returning from a user-space
|
||||
* signal handler.
|
||||
*/
|
||||
@@ -324,7 +327,7 @@ struct xcptcontext
|
||||
uint32_t sigreturn;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
/* The following array holds information needed to return from each nested
|
||||
* system call.
|
||||
*/
|
||||
|
||||
@@ -56,11 +56,21 @@
|
||||
|
||||
#define SYS_syscall 0x00
|
||||
|
||||
/* The SYS_signal_handler_return is executed here... its value is not always
|
||||
* available in this context and so is assumed to be 7.
|
||||
*/
|
||||
|
||||
#ifndef SYS_signal_handler_return
|
||||
# define SYS_signal_handler_return (7)
|
||||
#elif SYS_signal_handler_return != 7
|
||||
# error "SYS_signal_handler_return was assumed to be 7"
|
||||
#endif
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
/* SYS call 1 and 2 are defined for internal use by the RISC-V port (see
|
||||
* arch/risc-v/include/rv64gc/syscall.h). In addition, SYS call 3 is the
|
||||
* return from a SYS call in kernel mode. The first four syscall values must,
|
||||
* arch/risc-v/include/rv64gc/syscall.h). In addition, SYS call 3 is the
|
||||
* return from a SYS call in kernel mode. The first four syscall values must,
|
||||
* therefore, be reserved (0 is not used).
|
||||
*/
|
||||
|
||||
@@ -144,7 +154,20 @@ extern "C"
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t sys_call0(unsigned int nbr);
|
||||
static inline uintptr_t sys_call0(unsigned int nbr)
|
||||
{
|
||||
register long r0 asm("a0") = (long)(nbr);
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
:: "r"(r0)
|
||||
);
|
||||
|
||||
asm volatile("nop" : "=r"(r0));
|
||||
|
||||
return r0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall1
|
||||
@@ -154,7 +177,21 @@ uintptr_t sys_call0(unsigned int nbr);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1);
|
||||
static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1)
|
||||
{
|
||||
register long r0 asm("a0") = (long)(nbr);
|
||||
register long r1 asm("a1") = (long)(parm1);
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
:: "r"(r0), "r"(r1)
|
||||
);
|
||||
|
||||
asm volatile("nop" : "=r"(r0));
|
||||
|
||||
return r0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall2
|
||||
@@ -164,7 +201,23 @@ uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2);
|
||||
static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1,
|
||||
uintptr_t parm2)
|
||||
{
|
||||
register long r0 asm("a0") = (long)(nbr);
|
||||
register long r1 asm("a1") = (long)(parm1);
|
||||
register long r2 asm("a2") = (long)(parm2);
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
:: "r"(r0), "r"(r1), "r"(r2)
|
||||
);
|
||||
|
||||
asm volatile("nop" : "=r"(r0));
|
||||
|
||||
return r0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall3
|
||||
@@ -174,8 +227,24 @@ uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, uintptr_t parm2,
|
||||
uintptr_t parm3);
|
||||
static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1,
|
||||
uintptr_t parm2, uintptr_t parm3)
|
||||
{
|
||||
register long r0 asm("a0") = (long)(nbr);
|
||||
register long r1 asm("a1") = (long)(parm1);
|
||||
register long r2 asm("a2") = (long)(parm2);
|
||||
register long r3 asm("a3") = (long)(parm3);
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3)
|
||||
);
|
||||
|
||||
asm volatile("nop" : "=r"(r0));
|
||||
|
||||
return r0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall4
|
||||
@@ -185,8 +254,26 @@ uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, uintptr_t parm2,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, uintptr_t parm2,
|
||||
uintptr_t parm3, uintptr_t parm4);
|
||||
static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1,
|
||||
uintptr_t parm2, uintptr_t parm3,
|
||||
uintptr_t parm4)
|
||||
{
|
||||
register long r0 asm("a0") = (long)(nbr);
|
||||
register long r1 asm("a1") = (long)(parm1);
|
||||
register long r2 asm("a2") = (long)(parm2);
|
||||
register long r3 asm("a3") = (long)(parm3);
|
||||
register long r4 asm("a4") = (long)(parm4);
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
|
||||
);
|
||||
|
||||
asm volatile("nop" : "=r"(r0));
|
||||
|
||||
return r0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall5
|
||||
@@ -196,8 +283,59 @@ uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, uintptr_t parm2,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, uintptr_t parm2,
|
||||
uintptr_t parm3, uintptr_t parm4, uintptr_t parm5);
|
||||
static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1,
|
||||
uintptr_t parm2, uintptr_t parm3,
|
||||
uintptr_t parm4, uintptr_t parm5)
|
||||
{
|
||||
register long r0 asm("a0") = (long)(nbr);
|
||||
register long r1 asm("a1") = (long)(parm1);
|
||||
register long r2 asm("a2") = (long)(parm2);
|
||||
register long r3 asm("a3") = (long)(parm3);
|
||||
register long r4 asm("a4") = (long)(parm4);
|
||||
register long r5 asm("a5") = (long)(parm5);
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
|
||||
);
|
||||
|
||||
asm volatile("nop" : "=r"(r0));
|
||||
|
||||
return r0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall6
|
||||
*
|
||||
* Description:
|
||||
* System call SYS_ argument and six additional parameters.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
|
||||
uintptr_t parm2, uintptr_t parm3,
|
||||
uintptr_t parm4, uintptr_t parm5,
|
||||
uintptr_t parm6)
|
||||
{
|
||||
register long r0 asm("a0") = (long)(nbr);
|
||||
register long r1 asm("a1") = (long)(parm1);
|
||||
register long r2 asm("a2") = (long)(parm2);
|
||||
register long r3 asm("a3") = (long)(parm3);
|
||||
register long r4 asm("a4") = (long)(parm4);
|
||||
register long r5 asm("a5") = (long)(parm5);
|
||||
register long r6 asm("a6") = (long)(parm6);
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"ecall"
|
||||
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6)
|
||||
);
|
||||
|
||||
asm volatile("nop" : "=r"(r0));
|
||||
|
||||
return r0;
|
||||
}
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/rv64gc/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_RISCV_SRC_RV64GC_SVCALL_H
|
||||
#define __ARCH_RISCV_SRC_RV64GC_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 8"
|
||||
# elif CONFIG_SYS_RESERVED != 8
|
||||
# error "CONFIG_SYS_RESERVED must have the value 8"
|
||||
# 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
|
||||
|
||||
/* RV64GC system calls ******************************************************/
|
||||
|
||||
/* SYS call 0:
|
||||
*
|
||||
* int up_saveusercontext(uint32_t *saveregs);
|
||||
*/
|
||||
|
||||
#define SYS_save_context (0)
|
||||
|
||||
/* SYS call 1:
|
||||
*
|
||||
* void up_fullcontextrestore(uint32_t *restoreregs) noreturn_function;
|
||||
*/
|
||||
|
||||
#define SYS_restore_context (1)
|
||||
|
||||
/* SYS call 2:
|
||||
*
|
||||
* void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
|
||||
*/
|
||||
|
||||
#define SYS_switch_context (2)
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
/* SYS call 3:
|
||||
*
|
||||
* void up_syscall_return(void);
|
||||
*/
|
||||
|
||||
#define SYS_syscall_return (3)
|
||||
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
/* SYS call 4:
|
||||
*
|
||||
* void up_task_start(main_t taskentry, int argc, FAR char *argv[])
|
||||
* noreturn_function;
|
||||
*/
|
||||
|
||||
#define SYS_task_start (4)
|
||||
|
||||
/* SYS call 5:
|
||||
*
|
||||
* void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
|
||||
* noreturn_function
|
||||
*/
|
||||
|
||||
#define SYS_pthread_start (5)
|
||||
|
||||
/* SYS call 6:
|
||||
*
|
||||
* void signal_handler(_sa_sigaction_t sighand, int signo,
|
||||
* FAR siginfo_t *info, FAR 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 */
|
||||
#endif /* CONFIG_LIB_SYSCALL */
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_RV64GC_SVCALL_H */
|
||||
@@ -88,25 +88,6 @@ void up_initial_state(struct tcb_s *tcb)
|
||||
|
||||
xcp->regs[REG_EPC] = (uintptr_t)tcb->start;
|
||||
|
||||
/* If this task is running PIC, then set the PIC base register to the
|
||||
* address of the allocated D-Space region.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PIC
|
||||
# warning "Missing logic"
|
||||
#endif
|
||||
|
||||
/* Set privileged- or unprivileged-mode, depending on how NuttX is
|
||||
* configured and what kind of thread is being started.
|
||||
*
|
||||
* If the kernel build is not selected, then all threads run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
# warning "Missing logic"
|
||||
#endif
|
||||
|
||||
/* Set the initial value of the interrupt context register.
|
||||
*
|
||||
* Since various RISC-V platforms use different interrupt
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/rv64gc/up_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 "svcall.h"
|
||||
#include "up_internal.h"
|
||||
|
||||
#if (defined(CONFIG_BUILD_PROTECTED) && defined(__KERNEL__)) || \
|
||||
defined(CONFIG_BUILD_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 a user-mode signaling handling stub will also execute
|
||||
* before the ultimate signal handler is called. See
|
||||
* arch/arm/src/armv[6\7]/up_signal_handler. 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,
|
||||
FAR siginfo_t *info, FAR 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_PROTECTED || CONFIG_BUILD_KERNEL) && !CONFIG_DISABLE_PTHREAD */
|
||||
@@ -0,0 +1,97 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/rv64gc/up_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 "up_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:
|
||||
* a0 = sighand
|
||||
* The address user-space signal handling function
|
||||
* a1-a3 = 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 svcall.h)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
.globl up_signal_handler
|
||||
.type up_signal_handler, function
|
||||
|
||||
up_signal_handler:
|
||||
|
||||
/* Save ra on the stack */
|
||||
|
||||
addi sp, sp, -8
|
||||
sd ra, (sp)
|
||||
|
||||
/* Call the signal handler */
|
||||
|
||||
mv t0, a0 /* t0=sighand */
|
||||
mv a0, a1 /* a0=signo */
|
||||
mv a1, a2 /* a1=info */
|
||||
mv a2, a3 /* a2=ucontext */
|
||||
jalr t0 /* Call the signal handler (modifies ra) */
|
||||
|
||||
/* Restore the register */
|
||||
|
||||
ld ra, (sp) /* Restore ra in sp */
|
||||
addi sp, sp, 8
|
||||
|
||||
/* Execute the SYS_signal_handler_return SVCall (will not return) */
|
||||
|
||||
li a0, SYS_signal_handler_return
|
||||
ecall
|
||||
nop
|
||||
|
||||
.size up_signal_handler, .-up_signal_handler
|
||||
.end
|
||||
|
||||
#endif /* CONFIG_BUILD_PROTECTED && !__KERNEL__ */
|
||||
@@ -41,15 +41,19 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/sched.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/userspace.h>
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
# include <syscall.h>
|
||||
#endif
|
||||
|
||||
#include "signal/signal.h"
|
||||
#include "svcall.h"
|
||||
#include "up_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -93,15 +97,38 @@ static void up_registerdump(const uint64_t *regs)
|
||||
* Name: dispatch_syscall
|
||||
*
|
||||
* Description:
|
||||
* Call the stub function corresponding to the system call.
|
||||
* Call the stub function corresponding to the system call. NOTE the non-
|
||||
* standard parameter passing:
|
||||
*
|
||||
* A0 = SYS_ call number
|
||||
* A1 = parm0
|
||||
* A2 = parm1
|
||||
* A3 = parm2
|
||||
* A4 = parm3
|
||||
* A5 = parm4
|
||||
* A6 = parm5
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
static void dispatch_syscall(void) naked_function;
|
||||
static void dispatch_syscall(void)
|
||||
{
|
||||
# error "Missing logic"
|
||||
asm volatile
|
||||
(
|
||||
" addi sp, sp, -8\n" /* Create a stack frame to hold ra */
|
||||
" sd ra, 0(sp)\n" /* Save ra in the stack frame */
|
||||
" la t0, g_stublookup\n" /* t0=The base of the stub lookup table */
|
||||
" slli a0, a0, 3\n" /* a0=Offset for the stub lookup table */
|
||||
" add t0, t0, a0\n" /* t0=The address in the table */
|
||||
" ld t0, 0(t0)\n" /* t0=The address of the stub for this syscall */
|
||||
" jalr ra, t0\n" /* Call the stub (modifies ra) */
|
||||
" ld ra, 0(sp)\n" /* Restore ra */
|
||||
" addi sp, sp, 8\n" /* Destroy the stack frame */
|
||||
" mv a2, a0\n" /* a2=Save return value in a0 */
|
||||
" li a0, 3\n" /* a0=SYS_syscall_return (3) */
|
||||
" ecall" /* Return from the syscall */
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -184,7 +211,7 @@ int up_swint(int irq, FAR void *context, FAR void *arg)
|
||||
}
|
||||
break;
|
||||
|
||||
/* A0=SYS_syscall_return: This a switch context command:
|
||||
/* A0=SYS_syscall_return: This is a SYSCALL return command:
|
||||
*
|
||||
* void up_sycall_return(void);
|
||||
*
|
||||
@@ -196,7 +223,7 @@ int up_swint(int irq, FAR void *context, FAR void *arg)
|
||||
* unprivileged thread mode.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
case SYS_syscall_return:
|
||||
{
|
||||
struct tcb_s *rtcb = sched_self();
|
||||
@@ -210,20 +237,162 @@ int up_swint(int irq, FAR void *context, FAR void *arg)
|
||||
* the original mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_EPC] = rtcb->xcp.syscall[index].sysreturn;
|
||||
#error "Missing logic -- need to restore the original mode"
|
||||
rtcb->xcp.nsyscalls = index;
|
||||
regs[REG_EPC] = rtcb->xcp.syscall[index].sysreturn;
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
regs[REG_INT_CTX] = rtcb->xcp.syscall[index].int_ctx;
|
||||
#endif
|
||||
|
||||
/* The return value must be in A0-A1.
|
||||
* dispatch_syscall() temporarily moved the value for R0 into A2.
|
||||
*/
|
||||
|
||||
regs[REG_A0] = regs[REG_A2];
|
||||
|
||||
/* 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;
|
||||
rtcb->flags &= ~TCB_FLAG_SYSCALL;
|
||||
(void)nxsig_unmask_pendingsignal();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* R0=SYS_task_start: This a user task start
|
||||
*
|
||||
* void up_task_start(main_t taskentry, int argc,
|
||||
* FAR char *argv[]) noreturn_function;
|
||||
*
|
||||
* At this point, the following values are saved in context:
|
||||
*
|
||||
* A0 = SYS_task_start
|
||||
* A1 = taskentry
|
||||
* A2 = argc
|
||||
* A3 = argv
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
case SYS_task_start:
|
||||
{
|
||||
/* Set up to return to the user-space task start-up function in
|
||||
* unprivileged mode.
|
||||
*/
|
||||
|
||||
regs[REG_EPC] = (uintptr_t)USERSPACE->task_startup & ~1;
|
||||
|
||||
regs[REG_A0] = regs[REG_A1]; /* Task entry */
|
||||
regs[REG_A1] = regs[REG_A2]; /* argc */
|
||||
regs[REG_A2] = regs[REG_A3]; /* argv */
|
||||
|
||||
regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* R0=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:
|
||||
*
|
||||
* R0 = SYS_pthread_start
|
||||
* R1 = entrypt
|
||||
* R2 = arg
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_BUILD_PROTECTED) && !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_EPC] = (uintptr_t)USERSPACE->pthread_startup & ~1;
|
||||
|
||||
/* Change the parameter ordering to match the expectation of struct
|
||||
* userpace_s pthread_startup:
|
||||
*/
|
||||
|
||||
regs[REG_A0] = regs[REG_A1]; /* pthread entry */
|
||||
regs[REG_A1] = regs[REG_A2]; /* arg */
|
||||
regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* R0=SYS_signal_handler: This a user signal handler callback
|
||||
*
|
||||
* void signal_handler(_sa_sigaction_t sighand, int signo,
|
||||
* FAR siginfo_t *info, FAR void *ucontext);
|
||||
*
|
||||
* At this point, the following values are saved in context:
|
||||
*
|
||||
* R0 = SYS_signal_handler
|
||||
* R1 = sighand
|
||||
* R2 = signo
|
||||
* R3 = info
|
||||
* R4 = ucontext
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
case SYS_signal_handler:
|
||||
{
|
||||
struct tcb_s *rtcb = sched_self();
|
||||
|
||||
/* Remember the caller's return address */
|
||||
|
||||
DEBUGASSERT(rtcb->xcp.sigreturn == 0);
|
||||
rtcb->xcp.sigreturn = regs[REG_EPC];
|
||||
|
||||
/* Set up to return to the user-space pthread start-up function in
|
||||
* unprivileged mode.
|
||||
*/
|
||||
|
||||
regs[REG_EPC] = (uintptr_t)USERSPACE->signal_handler & ~1;
|
||||
regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
|
||||
|
||||
/* Change the parameter ordering to match the expectation of struct
|
||||
* userpace_s signal_handler.
|
||||
*/
|
||||
|
||||
regs[REG_A0] = regs[REG_A1]; /* sighand */
|
||||
regs[REG_A1] = regs[REG_A2]; /* signal */
|
||||
regs[REG_A2] = regs[REG_A3]; /* info */
|
||||
regs[REG_A3] = regs[REG_A4]; /* ucontext */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* R0=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:
|
||||
*
|
||||
* R0 = SYS_signal_handler_return
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
case SYS_signal_handler_return:
|
||||
{
|
||||
struct tcb_s *rtcb = sched_self();
|
||||
|
||||
/* Set up to return to the kernel-mode signal dispatching logic. */
|
||||
|
||||
DEBUGASSERT(rtcb->xcp.sigreturn != 0);
|
||||
regs[REG_EPC] = rtcb->xcp.sigreturn & ~1;
|
||||
regs[REG_INT_CTX] |= MSTATUS_MPPM; /* Machine mode */
|
||||
|
||||
rtcb->xcp.sigreturn = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* This is not an architecture-specify 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.
|
||||
@@ -231,7 +400,7 @@ int up_swint(int irq, FAR void *context, FAR void *arg)
|
||||
|
||||
default:
|
||||
{
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
FAR struct tcb_s *rtcb = sched_self();
|
||||
int index = rtcb->xcp.nsyscalls;
|
||||
|
||||
@@ -247,20 +416,26 @@ int up_swint(int irq, FAR void *context, FAR void *arg)
|
||||
|
||||
/* Setup to return to dispatch_syscall in privileged mode. */
|
||||
|
||||
rtcb->xcpsyscall[index].sysreturn = regs[REG_EPC];
|
||||
#error "Missing logic -- Need to save mode"
|
||||
rtcb->xcp.syscall[index].sysreturn = regs[REG_EPC];
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
rtcb->xcp.syscall[index].int_ctx = regs[REG_INT_CTX];
|
||||
#endif
|
||||
|
||||
rtcb->xcp.nsyscalls = index + 1;
|
||||
|
||||
regs[REG_EPC] = (uint32_t)dispatch_syscall;
|
||||
#error "Missing logic -- Need to set privileged mode"
|
||||
regs[REG_EPC] = (uintptr_t)dispatch_syscall & ~1;
|
||||
|
||||
/* Offset R0 to account for the reserved values */
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
regs[REG_INT_CTX] |= MSTATUS_MPPM; /* Machine mode */
|
||||
#endif
|
||||
|
||||
CURRENT_REGS[REG_A0] -= CONFIG_SYS_RESERVED;
|
||||
/* Offset A0 to account for the reserved values */
|
||||
|
||||
regs[REG_A0] -= CONFIG_SYS_RESERVED;
|
||||
|
||||
/* Indicate that we are in a syscall handler. */
|
||||
|
||||
rtcb->flags |= TCB_FLAG_SYSCALL;
|
||||
rtcb->flags |= TCB_FLAG_SYSCALL;
|
||||
#else
|
||||
svcerr("ERROR: Bad SYS call: %d\n", regs[REG_A0]);
|
||||
#endif
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/****************************************************************************
|
||||
* arch/riscv/src/rv64gc/up_syscall.S
|
||||
*
|
||||
* Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Modified for RISC-V:
|
||||
*
|
||||
* Copyright (C) 2016 Ken Pettit. All rights reserved.
|
||||
* Author: Ken Pettit <pettitkd@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.file "up_syscall0.S"
|
||||
.global sys_call0
|
||||
.global sys_call1
|
||||
.global sys_call2
|
||||
.global sys_call3
|
||||
.global sys_call4
|
||||
.global sys_call5
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_syscall0, up_syscall1, up_syscall2, up_syscall3
|
||||
*
|
||||
* Description:
|
||||
* up_syscall0 - System call SYS_ argument and no additional parameters.
|
||||
* up_syscall1 - System call SYS_ argument and one additional parameter.
|
||||
* up_syscall2 - System call SYS_ argument and two additional parameters.
|
||||
* up_syscall3 - System call SYS_ argument and three additional parameters.
|
||||
* up_syscall4 - System call SYS_ argument and four additional parameters.
|
||||
* up_syscall5 - System call SYS_ argument and five additional parameters.
|
||||
*
|
||||
* Assumption:
|
||||
* All interrupts are disabled except for the software interrupts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
|
||||
sys_call0: /* a0 holds the syscall number */
|
||||
sys_call1: /* a0 holds the syscall number, argument in a1 */
|
||||
sys_call2: /* a0 holds the syscall number, arguments in a1 and a2 */
|
||||
sys_call3: /* a0 holds the syscall number, arguments in a1, a2, and a3 */
|
||||
sys_call4: /* a0 holds the syscall number, arguments in a1, a2, a3 and a4 */
|
||||
sys_call5: /* a0 holds the syscall number, arguments in a1, a2, a3, a4 and a5 */
|
||||
|
||||
/* Issue the ECALL opcode to perform a SW interrupt to the OS */
|
||||
|
||||
ecall
|
||||
|
||||
/* The actual interrupt may not a occur for a few more cycles. Let's
|
||||
* put a few nop's here in hope that the SW interrupt occurs during
|
||||
* the sequence of nops.
|
||||
*/
|
||||
|
||||
nop
|
||||
nop
|
||||
|
||||
/* Then return with the result of the software interrupt in v0 */
|
||||
|
||||
ret
|
||||
nop
|
||||
Reference in New Issue
Block a user