summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/armv6-m/up_svcall.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/arch/arm/src/armv6-m/up_svcall.c')
-rw-r--r--nuttx/arch/arm/src/armv6-m/up_svcall.c74
1 files changed, 73 insertions, 1 deletions
diff --git a/nuttx/arch/arm/src/armv6-m/up_svcall.c b/nuttx/arch/arm/src/armv6-m/up_svcall.c
index ac99cabe0..745800532 100644
--- a/nuttx/arch/arm/src/armv6-m/up_svcall.c
+++ b/nuttx/arch/arm/src/armv6-m/up_svcall.c
@@ -344,6 +344,78 @@ int up_svcall(int irq, FAR void *context)
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
+ * ucontext (on the stack)
+ */
+
+#if defined(CONFIG_NUTTX_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
+ 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_PC];
+
+ /* Set up to return to the user-space pthread start-up function in
+ * unprivileged mode.
+ */
+
+ regs[REG_PC] = (uint32_t)USERSPACE->signal_handler;
+ regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
+
+ /* Change the parameter ordering to match the expectation of struct
+ * userpace_s signal_handler.
+ */
+
+ regs[REG_R0] = regs[REG_R1]; /* sighand */
+ regs[REG_R1] = regs[REG_R2]; /* signal */
+ regs[REG_R2] = regs[REG_R3]; /* info */
+
+ /* The last parameter, arg, is trickier. The arg parameter will
+ * reside at an offset of 4 from the stack pointer.
+ */
+
+ regs[REG_R3] = *(uint32_t*)(regs[REG_SP+4]);
+ }
+ 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
+ */
+
+#if defined(CONFIG_NUTTX_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
+ 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_PC] = rtcb->xcp.sigreturn;
+ regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
+ }
+ break;
+#endif
+
/* This is not an architecture-specific 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.
@@ -356,7 +428,7 @@ int up_svcall(int irq, FAR void *context)
/* Verify that the SYS call number is within range */
- DEBUGASSERT(cmd < SYS_maxsyscall);
+ DEBUGASSERT(cmd >= CONFIG_SYS_RESERVED && cmd < SYS_maxsyscall);
/* Make sure that there is a no saved syscall return address. We
* cannot yet handle nested system calls.