mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
Add support for nested system calls
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5752 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -57,8 +57,14 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
/* Configuration ************************************************************/
|
||||||
|
/* If this is a kernel build, how many nested system calls should we support? */
|
||||||
|
|
||||||
/* IRQ Stack Frame Format:
|
#ifndef CONFIG_SYS_NNEST
|
||||||
|
# define CONFIG_SYS_NNEST 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* IRQ Stack Frame Format ***************************************************
|
||||||
*
|
*
|
||||||
* The following additional registers are stored by the interrupt handling
|
* The following additional registers are stored by the interrupt handling
|
||||||
* logic.
|
* logic.
|
||||||
@@ -140,11 +146,22 @@
|
|||||||
* Public Types
|
* Public Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
/* This structure represents the return state from a system call */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
|
struct xcpt_syscall_s
|
||||||
|
{
|
||||||
|
uint32_t excreturn; /* The EXC_RETURN value */
|
||||||
|
uint32_t sysreturn; /* The return PC */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The following structure is included in the TCB and defines the complete
|
/* The following structure is included in the TCB and defines the complete
|
||||||
* state of the thread.
|
* state of the thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
|
||||||
struct xcptcontext
|
struct xcptcontext
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_DISABLE_SIGNALS
|
#ifndef CONFIG_DISABLE_SIGNALS
|
||||||
@@ -168,16 +185,17 @@ struct xcptcontext
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t sigreturn;
|
uint32_t sigreturn;
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
/* The following holds the return address and the exc_return value needed
|
/* The following array holds the return address and the exc_return value
|
||||||
* to return from a system call.
|
* needed to return from each nested system call.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t excreturn;
|
uint8_t nsyscalls;
|
||||||
uint32_t sysreturn;
|
struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Register save area */
|
/* Register save area */
|
||||||
|
|||||||
@@ -67,8 +67,14 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
/* Configuration ************************************************************/
|
||||||
|
/* If this is a kernel build, how many nested system calls should we support? */
|
||||||
|
|
||||||
/* Alternate register names */
|
#ifndef CONFIG_SYS_NNEST
|
||||||
|
# define CONFIG_SYS_NNEST 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Alternate register names *************************************************/
|
||||||
|
|
||||||
#define REG_A1 REG_R0
|
#define REG_A1 REG_R0
|
||||||
#define REG_A2 REG_R1
|
#define REG_A2 REG_R1
|
||||||
@@ -98,12 +104,22 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
/* This structure represents the return state from a system call */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
|
struct xcpt_syscall_s
|
||||||
|
{
|
||||||
|
uint32_t excreturn; /* The EXC_RETURN value */
|
||||||
|
uint32_t sysreturn; /* The return PC */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The following structure is included in the TCB and defines the complete
|
/* The following structure is included in the TCB and defines the complete
|
||||||
* state of the thread.
|
* state of the thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
|
||||||
struct xcptcontext
|
struct xcptcontext
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_DISABLE_SIGNALS
|
#ifndef CONFIG_DISABLE_SIGNALS
|
||||||
@@ -131,16 +147,18 @@ struct xcptcontext
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t sigreturn;
|
uint32_t sigreturn;
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
/* The following holds the return address and the exc_return value needed
|
/* The following array holds the return address and the exc_return value
|
||||||
* to return from a system call.
|
* needed to return from each nested system call.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t excreturn;
|
uint8_t nsyscalls;
|
||||||
uint32_t sysreturn;
|
struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Register save area */
|
/* Register save area */
|
||||||
|
|||||||
@@ -258,18 +258,19 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
case SYS_syscall_return:
|
case SYS_syscall_return:
|
||||||
{
|
{
|
||||||
struct tcb_s *rtcb = sched_self();
|
struct tcb_s *rtcb = sched_self();
|
||||||
|
int index = (int)rtcb->xcp.nsyscalls - 1;
|
||||||
|
|
||||||
/* Make sure that there is a saved syscall return address. */
|
/* Make sure that there is a saved syscall return address. */
|
||||||
|
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn != 0);
|
DEBUGASSERT(index >= 0);
|
||||||
|
|
||||||
/* Setup to return to the saved syscall return address in
|
/* Setup to return to the saved syscall return address in
|
||||||
* the original mode.
|
* the original mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
regs[REG_PC] = rtcb->xcp.sysreturn;
|
regs[REG_PC] = rtcb->xcp.syscall[index].sysreturn;
|
||||||
regs[REG_EXC_RETURN] = rtcb->xcp.excreturn;
|
regs[REG_EXC_RETURN] = rtcb->xcp.syscall[index].excreturn;
|
||||||
rtcb->xcp.sysreturn = 0;
|
rtcb->xcp.nsyscalls = index;
|
||||||
|
|
||||||
/* The return value must be in R0-R1. dispatch_syscall() temporarily
|
/* The return value must be in R0-R1. dispatch_syscall() temporarily
|
||||||
* moved the value for R0 into R2.
|
* moved the value for R0 into R2.
|
||||||
@@ -425,6 +426,7 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
{
|
{
|
||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
FAR struct tcb_s *rtcb = sched_self();
|
FAR struct tcb_s *rtcb = sched_self();
|
||||||
|
int index = rtcb->xcp.nsyscalls;
|
||||||
|
|
||||||
/* Verify that the SYS call number is within range */
|
/* Verify that the SYS call number is within range */
|
||||||
|
|
||||||
@@ -434,12 +436,13 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
* cannot yet handle nested system calls.
|
* cannot yet handle nested system calls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
|
DEBUGASSERT(index < CONFIG_SYS_NNEST);
|
||||||
|
|
||||||
/* Setup to return to dispatch_syscall in privileged mode. */
|
/* Setup to return to dispatch_syscall in privileged mode. */
|
||||||
|
|
||||||
rtcb->xcp.sysreturn = regs[REG_PC];
|
rtcb->xcp.syscall[index].sysreturn = regs[REG_PC];
|
||||||
rtcb->xcp.excreturn = regs[REG_EXC_RETURN];
|
rtcb->xcp.syscall[index].excreturn = regs[REG_EXC_RETURN];
|
||||||
|
rtcb->xcp.nsyscalls = index + 1;
|
||||||
|
|
||||||
regs[REG_PC] = (uint32_t)dispatch_syscall;
|
regs[REG_PC] = (uint32_t)dispatch_syscall;
|
||||||
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
||||||
|
|||||||
@@ -262,18 +262,19 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
case SYS_syscall_return:
|
case SYS_syscall_return:
|
||||||
{
|
{
|
||||||
struct tcb_s *rtcb = sched_self();
|
struct tcb_s *rtcb = sched_self();
|
||||||
|
int index = (int)rtcb->xcp.nsyscalls - 1;
|
||||||
|
|
||||||
/* Make sure that there is a saved syscall return address. */
|
/* Make sure that there is a saved syscall return address. */
|
||||||
|
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn != 0);
|
DEBUGASSERT(index >= 0);
|
||||||
|
|
||||||
/* Setup to return to the saved syscall return address in
|
/* Setup to return to the saved syscall return address in
|
||||||
* the original mode.
|
* the original mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
regs[REG_PC] = rtcb->xcp.sysreturn;
|
regs[REG_PC] = rtcb->xcp.syscall[index].sysreturn;
|
||||||
regs[REG_EXC_RETURN] = rtcb->xcp.excreturn;
|
regs[REG_EXC_RETURN] = rtcb->xcp.syscall[index].excreturn;
|
||||||
rtcb->xcp.sysreturn = 0;
|
rtcb->xcp.nsyscalls = index;
|
||||||
|
|
||||||
/* The return value must be in R0-R1. dispatch_syscall() temporarily
|
/* The return value must be in R0-R1. dispatch_syscall() temporarily
|
||||||
* moved the value for R0 into R2.
|
* moved the value for R0 into R2.
|
||||||
@@ -429,6 +430,7 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
{
|
{
|
||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
FAR struct tcb_s *rtcb = sched_self();
|
FAR struct tcb_s *rtcb = sched_self();
|
||||||
|
int index = rtcb->xcp.nsyscalls;
|
||||||
|
|
||||||
/* Verify that the SYS call number is within range */
|
/* Verify that the SYS call number is within range */
|
||||||
|
|
||||||
@@ -438,12 +440,13 @@ int up_svcall(int irq, FAR void *context)
|
|||||||
* cannot yet handle nested system calls.
|
* cannot yet handle nested system calls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
|
DEBUGASSERT(index < CONFIG_SYS_NNEST);
|
||||||
|
|
||||||
/* Setup to return to dispatch_syscall in privileged mode. */
|
/* Setup to return to dispatch_syscall in privileged mode. */
|
||||||
|
|
||||||
rtcb->xcp.sysreturn = regs[REG_PC];
|
rtcb->xcp.syscall[index].sysreturn = regs[REG_PC];
|
||||||
rtcb->xcp.excreturn = regs[REG_EXC_RETURN];
|
rtcb->xcp.syscall[index].excreturn = regs[REG_EXC_RETURN];
|
||||||
|
rtcb->xcp.nsyscalls = index + 1;
|
||||||
|
|
||||||
regs[REG_PC] = (uint32_t)dispatch_syscall;
|
regs[REG_PC] = (uint32_t)dispatch_syscall;
|
||||||
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
||||||
|
|||||||
@@ -61,6 +61,12 @@
|
|||||||
# define MIPS32_SAVE_GP 1
|
# define MIPS32_SAVE_GP 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If this is a kernel build, how many nested system calls should we support? */
|
||||||
|
|
||||||
|
#ifndef CONFIG_SYS_NNEST
|
||||||
|
# define CONFIG_SYS_NNEST 2
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Register save state structure ********************************************/
|
/* Register save state structure ********************************************/
|
||||||
/* Co processor registers */
|
/* Co processor registers */
|
||||||
|
|
||||||
@@ -308,6 +314,19 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
/* This structure represents the return state from a system call */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
|
struct xcpt_syscall_s
|
||||||
|
{
|
||||||
|
uint32_t sysreturn; /* The return PC */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The following structure is included in the TCB and defines the complete
|
||||||
|
* state of the thread.
|
||||||
|
*/
|
||||||
|
|
||||||
struct xcptcontext
|
struct xcptcontext
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_DISABLE_SIGNALS
|
#ifndef CONFIG_DISABLE_SIGNALS
|
||||||
@@ -323,12 +342,25 @@ struct xcptcontext
|
|||||||
|
|
||||||
uint32_t saved_epc; /* Trampoline PC */
|
uint32_t saved_epc; /* Trampoline PC */
|
||||||
uint32_t saved_status; /* Status with interrupts disabled. */
|
uint32_t saved_status; /* Status with interrupts disabled. */
|
||||||
|
|
||||||
|
# ifdef CONFIG_NUTTX_KERNEL
|
||||||
|
/* This is the saved address to use when returning from a user-space
|
||||||
|
* signal handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t sigreturn;
|
||||||
|
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
/* The following holds the return address from a system call */
|
/* The following array holds information needed to return from each nested
|
||||||
|
* system call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8_t nsyscalls;
|
||||||
|
struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST];
|
||||||
|
|
||||||
uint32_t sysreturn;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Register save area */
|
/* Register save area */
|
||||||
|
|||||||
@@ -238,18 +238,19 @@ int up_swint0(int irq, FAR void *context)
|
|||||||
case SYS_syscall_return:
|
case SYS_syscall_return:
|
||||||
{
|
{
|
||||||
struct tcb_s *rtcb = sched_self();
|
struct tcb_s *rtcb = sched_self();
|
||||||
|
int index = (int)rtcb->xcp.nsyscalls - 1;
|
||||||
|
|
||||||
/* Make sure that there is a saved syscall return address. */
|
/* Make sure that there is a saved syscall return address. */
|
||||||
|
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn != 0);
|
DEBUGASSERT(index >= 0);
|
||||||
|
|
||||||
/* Setup to return to the saved syscall return address in
|
/* Setup to return to the saved syscall return address in
|
||||||
* the original mode.
|
* the original mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
current_regs[REG_EPC] = rtcb->xcp.sysreturn;
|
current_regs[REG_EPC] = rtcb->xcp.syscall[index].sysreturn;
|
||||||
#error "Missing logic -- need to restore the original mode"
|
#error "Missing logic -- need to restore the original mode"
|
||||||
rtcb->sysreturn = 0;
|
rtcb->xcp.nsyscalls = index;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -263,6 +264,7 @@ int up_swint0(int irq, FAR void *context)
|
|||||||
{
|
{
|
||||||
#ifdef CONFIG_NUTTX_KERNEL
|
#ifdef CONFIG_NUTTX_KERNEL
|
||||||
FAR struct tcb_s *rtcb = sched_self();
|
FAR struct tcb_s *rtcb = sched_self();
|
||||||
|
int index = rtcb->xcp.nsyscalls;
|
||||||
|
|
||||||
/* Verify that the SYS call number is within range */
|
/* Verify that the SYS call number is within range */
|
||||||
|
|
||||||
@@ -272,11 +274,14 @@ int up_swint0(int irq, FAR void *context)
|
|||||||
* return address. We cannot yet handle nested system calls.
|
* return address. We cannot yet handle nested system calls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
|
DEBUGASSERT(index < CONFIG_SYS_NNEST);
|
||||||
|
|
||||||
/* Setup to return to dispatch_syscall in privileged mode. */
|
/* Setup to return to dispatch_syscall in privileged mode. */
|
||||||
|
|
||||||
rtcb->sysreturn = regs[REG_EPC];
|
rtcb->xcpsyscall[index].sysreturn = regs[REG_EPC];
|
||||||
|
#error "Missing logic -- Need to save mode"
|
||||||
|
rtcb->xcp.nsyscalls = index + 1;
|
||||||
|
|
||||||
regs[REG_EPC] = (uint32_t)dispatch_syscall;
|
regs[REG_EPC] = (uint32_t)dispatch_syscall;
|
||||||
#error "Missing logic -- Need to set privileged mode"
|
#error "Missing logic -- Need to set privileged mode"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user