Add support for delivery of use-mode signals in the kernel build.

This commit is contained in:
Gregory Nutt 2014-09-02 15:58:14 -06:00
parent aa7efbb52e
commit 12775801c9
7 changed files with 75 additions and 19 deletions

View File

@ -240,6 +240,15 @@ struct xcptcontext
uint32_t saved_pc;
uint32_t saved_cpsr;
# ifdef CONFIG_BUILD_KERNEL
/* This is the saved address to use when returning from a user-space
* signal handler.
*/
uint32_t sigreturn;
# endif
#endif
/* Register save area */

View File

@ -83,7 +83,7 @@ CMN_CSRCS += arm_va2pte.c
endif
ifeq ($(CONFIG_BUILD_KERNEL),y)
CMN_CSRCS += up_task_start.c up_pthread_start.c
CMN_CSRCS += up_task_start.c up_pthread_start.c up_signal_dispatch.c
endif
ifeq ($(CONFIG_ARCH_ADDRENV),y)

View File

@ -332,7 +332,7 @@ static void up_addrenv_destroy_region(FAR uintptr_t **list,
* needed by the task. This region may be read/write only. NOTE: The
* actual size of the data region that is allocated will include a
* OS private reserved region at the beginning. The size of the
* private, reserved region is give by ARCH_DATA_RESERVE.
* private, reserved region is give by ARCH_DATA_RESERVE_SIZE.
* addrenv - The location to return the representation of the task address
* environment.
*
@ -378,7 +378,7 @@ int up_addrenv_create(size_t textsize, size_t datasize,
ret = up_addrenv_create_region(addrenv->data, ARCH_DATA_NSECTS,
CONFIG_ARCH_DATA_VBASE,
datasize + ARCH_DATA_RESERVE,
datasize + ARCH_DATA_RESERVE_SIZE,
MMU_L2_UDATAFLAGS);
if (ret < 0)
{
@ -495,7 +495,7 @@ int up_addrenv_vdata(FAR group_addrenv_t *addrenv, uintptr_t textsize,
/* Not much to do in this case */
DEBUGASSERT(addrenv && vdata);
*vdata = (FAR void *)(CONFIG_ARCH_DATA_VBASE + ARCH_DATA_RESERVE);
*vdata = (FAR void *)(CONFIG_ARCH_DATA_VBASE + ARCH_DATA_RESERVE_SIZE);
return OK;
}

View File

@ -47,6 +47,7 @@
#include <arch/irq.h>
#include <nuttx/sched.h>
#include <nuttx/addrenv.h>
#include "arm.h"
#include "svcall.h"
@ -128,7 +129,7 @@ static void dispatch_syscall(void)
" add sp, sp, #16\n" /* Destroy the stack frame */
" mov r2, r0\n" /* R2=Save return value in R2 */
" mov r0, #0\n" /* R0=SYS_syscall_return */
" svc #0x900001" /* Return from the SYSCALL */
" svc #0x900001\n" /* Return from the SYSCALL */
);
}
#endif
@ -202,7 +203,7 @@ uint32_t *arm_syscall(uint32_t *regs)
case SYS_syscall_return:
{
struct tcb_s *rtcb = sched_self();
FAR struct tcb_s *rtcb = sched_self();
int index = (int)rtcb->xcp.nsyscalls - 1;
/* Make sure that there is a saved SYSCALL return address. */
@ -293,6 +294,7 @@ uint32_t *arm_syscall(uint32_t *regs)
break;
#endif
#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
/* R0=SYS_signal_handler: This a user signal handler callback
*
* void signal_handler(_sa_sigaction_t sighand, int signo,
@ -307,12 +309,9 @@ uint32_t *arm_syscall(uint32_t *regs)
* ucontext (on the stack)
*/
#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
case SYS_signal_handler:
{
#warning Missing logic
#if 0
struct tcb_s *rtcb = sched_self();
FAR struct tcb_s *rtcb = sched_self();
/* Remember the caller's return address */
@ -323,7 +322,7 @@ uint32_t *arm_syscall(uint32_t *regs)
* unprivileged mode.
*/
regs[REG_PC] = (uint32_t)USERSPACE->signal_handler;
regs[REG_PC] = (uint32_t)ARCH_DATA_RESERVE->ar_sigtramp;
cpsr = regs[REG_CPSR] & ~PSR_MODE_MASK;
regs[REG_CPSR] = cpsr | PSR_MODE_USR;
@ -340,11 +339,11 @@ uint32_t *arm_syscall(uint32_t *regs)
*/
regs[REG_R3] = *(uint32_t*)(regs[REG_SP+4]);
#endif
}
break;
#endif
#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
/* R0=SYS_signal_handler_return: This a user signal handler callback
*
* void signal_handler_return(void);
@ -354,12 +353,9 @@ uint32_t *arm_syscall(uint32_t *regs)
* R0 = SYS_signal_handler_return
*/
#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
case SYS_signal_handler_return:
{
#warning Missing logic
#if 0
struct tcb_s *rtcb = sched_self();
FAR struct tcb_s *rtcb = sched_self();
/* Set up to return to the kernel-mode signal dispatching logic. */
@ -369,7 +365,6 @@ uint32_t *arm_syscall(uint32_t *regs)
cpsr = regs[REG_CPSR] & ~PSR_MODE_MASK;
regs[REG_CPSR] = cpsr | PSR_MODE_SVC;
rtcb->xcp.sigreturn = 0;
#endif
}
break;
#endif

View File

@ -41,6 +41,8 @@
#include <sys/types.h>
#include <nuttx/addrenv.h>
#ifdef CONFIG_BUILD_KERNEL
/****************************************************************************
@ -61,6 +63,48 @@ extern main_t main;
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: up_signal_handler
*
* Description:
* This function is the user-space, signal handler trampoline function. It
* is called from up_signal_dispatch() in user-mode.
*
* R0-R3, R11 - volatile registers need not be preserved.
* R4-R10 - static registers must be preserved
* R12-R14 - LR and SP must be preserved
*
* Inputs:
* R0 = sighand
* The address user-space signal handling function
* R1-R3 = signo, info, and ucontext
* Standard arguments to be passed to the signal handling function.
*
* Return:
* None. This function does not return in the normal sense. It returns
* via the SYS_signal_handler_return (see svcall.h)
*
****************************************************************************/
#ifndef CONFIG_DISABLE_SIGNALS
static void sig_trampoline(void) naked_function;
static void sig_trampoline(void)
{
__asm__ __volatile__
(
" push {lr}\n" /* Save LR on the stack */
" mov ip, r0\n" /* IP=sighand */
" mov r0, r1\n" /* R0=signo */
" mov r1, r2\n" /* R1=info */
" mov r2, r3\n" /* R2=ucontext */
" blx ip\n" /* Call the signal handler */
" pop {r2}\n" /* Recover LR in R2 */
" mov lr, r2\n" /* Restore LR */
" mov r0, #4\n" /* SYS_signal_handler_return
" svc #0x900001\n" /* Return from the signal handler */
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -89,6 +133,14 @@ void _start(int argc, FAR char *argv[])
{
int ret;
#ifndef CONFIG_DISABLE_SIGNALS
/* Initialize the reserved area at the beginning of the .bss/.data region
* that is visible to the RTOS.
*/
ADDRENV_DATA_RESERVE->ar_sigtramp = (addrenv_sigtramp_t)sig_trampoline;
#endif
/* Call C++ constructors */
/* Setup so that C++ destructors called on task exit */
/* REVISIT: Missing logic */

View File

@ -1,5 +1,5 @@
/****************************************************************************
* arch/arm/srcm/armv7-m/up_signal_handler.S
* arch/arm/src/armv7-m/up_signal_handler.S
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>

View File

@ -85,7 +85,7 @@ CMN_CSRCS += arm_va2pte.c
endif
ifeq ($(CONFIG_BUILD_KERNEL),y)
CMN_CSRCS += up_task_start.c up_pthread_start.c
CMN_CSRCS += up_task_start.c up_pthread_start.c up_signal_dispatch.c
endif
ifeq ($(CONFIG_ARCH_ADDRENV),y)