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:
patacongo
2013-03-17 16:13:28 +00:00
parent 21df6b97b2
commit 990c1febf8
6 changed files with 116 additions and 37 deletions
+24 -6
View File
@@ -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 */
+24 -6
View File
@@ -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 */
+10 -7
View File
@@ -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;
+10 -7
View File
@@ -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;
+34 -2
View File
@@ -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 */
+10 -5
View File
@@ -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"