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
****************************************************************************/
/* 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
* logic.
@@ -140,11 +146,22 @@
* 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
* state of the thread.
*/
#ifndef __ASSEMBLY__
struct xcptcontext
{
#ifndef CONFIG_DISABLE_SIGNALS
@@ -168,16 +185,17 @@ struct xcptcontext
*/
uint32_t sigreturn;
# endif
#endif
#ifdef CONFIG_NUTTX_KERNEL
/* The following holds the return address and the exc_return value needed
* to return from a system call.
/* The following array holds the return address and the exc_return value
* needed to return from each nested system call.
*/
uint32_t excreturn;
uint32_t sysreturn;
uint8_t nsyscalls;
struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST];
#endif
/* Register save area */
+24 -6
View File
@@ -67,8 +67,14 @@
/****************************************************************************
* 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_A2 REG_R1
@@ -98,12 +104,22 @@
/****************************************************************************
* 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
* state of the thread.
*/
#ifndef __ASSEMBLY__
struct xcptcontext
{
#ifndef CONFIG_DISABLE_SIGNALS
@@ -131,16 +147,18 @@ struct xcptcontext
*/
uint32_t sigreturn;
# endif
#endif
#ifdef CONFIG_NUTTX_KERNEL
/* The following holds the return address and the exc_return value needed
* to return from a system call.
/* The following array holds the return address and the exc_return value
* needed to return from each nested system call.
*/
uint32_t excreturn;
uint32_t sysreturn;
uint8_t nsyscalls;
struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST];
#endif
/* Register save area */
+10 -7
View File
@@ -258,18 +258,19 @@ int up_svcall(int irq, FAR void *context)
case SYS_syscall_return:
{
struct tcb_s *rtcb = sched_self();
int index = (int)rtcb->xcp.nsyscalls - 1;
/* 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
* the original mode.
*/
regs[REG_PC] = rtcb->xcp.sysreturn;
regs[REG_EXC_RETURN] = rtcb->xcp.excreturn;
rtcb->xcp.sysreturn = 0;
regs[REG_PC] = rtcb->xcp.syscall[index].sysreturn;
regs[REG_EXC_RETURN] = rtcb->xcp.syscall[index].excreturn;
rtcb->xcp.nsyscalls = index;
/* The return value must be in R0-R1. dispatch_syscall() temporarily
* moved the value for R0 into R2.
@@ -425,6 +426,7 @@ int up_svcall(int irq, FAR void *context)
{
#ifdef CONFIG_NUTTX_KERNEL
FAR struct tcb_s *rtcb = sched_self();
int index = rtcb->xcp.nsyscalls;
/* 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.
*/
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
DEBUGASSERT(index < CONFIG_SYS_NNEST);
/* Setup to return to dispatch_syscall in privileged mode. */
rtcb->xcp.sysreturn = regs[REG_PC];
rtcb->xcp.excreturn = regs[REG_EXC_RETURN];
rtcb->xcp.syscall[index].sysreturn = regs[REG_PC];
rtcb->xcp.syscall[index].excreturn = regs[REG_EXC_RETURN];
rtcb->xcp.nsyscalls = index + 1;
regs[REG_PC] = (uint32_t)dispatch_syscall;
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:
{
struct tcb_s *rtcb = sched_self();
int index = (int)rtcb->xcp.nsyscalls - 1;
/* 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
* the original mode.
*/
regs[REG_PC] = rtcb->xcp.sysreturn;
regs[REG_EXC_RETURN] = rtcb->xcp.excreturn;
rtcb->xcp.sysreturn = 0;
regs[REG_PC] = rtcb->xcp.syscall[index].sysreturn;
regs[REG_EXC_RETURN] = rtcb->xcp.syscall[index].excreturn;
rtcb->xcp.nsyscalls = index;
/* The return value must be in R0-R1. dispatch_syscall() temporarily
* moved the value for R0 into R2.
@@ -429,6 +430,7 @@ int up_svcall(int irq, FAR void *context)
{
#ifdef CONFIG_NUTTX_KERNEL
FAR struct tcb_s *rtcb = sched_self();
int index = rtcb->xcp.nsyscalls;
/* 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.
*/
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
DEBUGASSERT(index < CONFIG_SYS_NNEST);
/* Setup to return to dispatch_syscall in privileged mode. */
rtcb->xcp.sysreturn = regs[REG_PC];
rtcb->xcp.excreturn = regs[REG_EXC_RETURN];
rtcb->xcp.syscall[index].sysreturn = regs[REG_PC];
rtcb->xcp.syscall[index].excreturn = regs[REG_EXC_RETURN];
rtcb->xcp.nsyscalls = index + 1;
regs[REG_PC] = (uint32_t)dispatch_syscall;
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
+34 -2
View File
@@ -61,6 +61,12 @@
# define MIPS32_SAVE_GP 1
#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 ********************************************/
/* Co processor registers */
@@ -308,6 +314,19 @@
#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
{
#ifndef CONFIG_DISABLE_SIGNALS
@@ -323,12 +342,25 @@ struct xcptcontext
uint32_t saved_epc; /* Trampoline PC */
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
#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
/* Register save area */
+10 -5
View File
@@ -238,18 +238,19 @@ int up_swint0(int irq, FAR void *context)
case SYS_syscall_return:
{
struct tcb_s *rtcb = sched_self();
int index = (int)rtcb->xcp.nsyscalls - 1;
/* 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
* 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"
rtcb->sysreturn = 0;
rtcb->xcp.nsyscalls = index;
}
break;
#endif
@@ -263,6 +264,7 @@ int up_swint0(int irq, FAR void *context)
{
#ifdef CONFIG_NUTTX_KERNEL
FAR struct tcb_s *rtcb = sched_self();
int index = rtcb->xcp.nsyscalls;
/* 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.
*/
DEBUGASSERT(rtcb->xcp.sysreturn == 0);
DEBUGASSERT(index < CONFIG_SYS_NNEST);
/* 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;
#error "Missing logic -- Need to set privileged mode"