mirror of
https://github.com/apache/nuttx.git
synced 2026-06-05 15:58:59 +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
|
||||
****************************************************************************/
|
||||
/* 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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,19 +436,20 @@ 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;
|
||||
|
||||
/* Offset R0 to account for the reserved values */
|
||||
|
||||
regs[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||
regs[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||
#else
|
||||
slldbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]);
|
||||
#endif
|
||||
|
||||
@@ -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,19 +440,20 @@ 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;
|
||||
|
||||
/* Offset R0 to account for the reserved values */
|
||||
|
||||
regs[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||
regs[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||
#else
|
||||
slldbg("ERROR: Bad SYS call: %d\n", regs[REG_R0]);
|
||||
#endif
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,17 +274,20 @@ 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];
|
||||
regs[REG_EPC] = (uint32_t)dispatch_syscall;
|
||||
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"
|
||||
|
||||
/* Offset R0 to account for the reserved values */
|
||||
|
||||
current_regs[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||
current_regs[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||
#else
|
||||
slldbg("ERROR: Bad SYS call: %d\n", regs[REG_A0]);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user