Add support for delivery of use-mode signals in the kernel build.
This commit is contained in:
parent
aa7efbb52e
commit
12775801c9
@ -240,6 +240,15 @@ struct xcptcontext
|
|||||||
|
|
||||||
uint32_t saved_pc;
|
uint32_t saved_pc;
|
||||||
uint32_t saved_cpsr;
|
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
|
#endif
|
||||||
|
|
||||||
/* Register save area */
|
/* Register save area */
|
||||||
|
@ -83,7 +83,7 @@ CMN_CSRCS += arm_va2pte.c
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_BUILD_KERNEL),y)
|
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
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ARCH_ADDRENV),y)
|
ifeq ($(CONFIG_ARCH_ADDRENV),y)
|
||||||
|
@ -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
|
* 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
|
* actual size of the data region that is allocated will include a
|
||||||
* OS private reserved region at the beginning. The size of the
|
* 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
|
* addrenv - The location to return the representation of the task address
|
||||||
* environment.
|
* 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,
|
ret = up_addrenv_create_region(addrenv->data, ARCH_DATA_NSECTS,
|
||||||
CONFIG_ARCH_DATA_VBASE,
|
CONFIG_ARCH_DATA_VBASE,
|
||||||
datasize + ARCH_DATA_RESERVE,
|
datasize + ARCH_DATA_RESERVE_SIZE,
|
||||||
MMU_L2_UDATAFLAGS);
|
MMU_L2_UDATAFLAGS);
|
||||||
if (ret < 0)
|
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 */
|
/* Not much to do in this case */
|
||||||
|
|
||||||
DEBUGASSERT(addrenv && vdata);
|
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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
#include <arch/irq.h>
|
#include <arch/irq.h>
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
|
#include <nuttx/addrenv.h>
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
#include "svcall.h"
|
#include "svcall.h"
|
||||||
@ -128,7 +129,7 @@ static void dispatch_syscall(void)
|
|||||||
" add sp, sp, #16\n" /* Destroy the stack frame */
|
" add sp, sp, #16\n" /* Destroy the stack frame */
|
||||||
" mov r2, r0\n" /* R2=Save return value in R2 */
|
" mov r2, r0\n" /* R2=Save return value in R2 */
|
||||||
" mov r0, #0\n" /* R0=SYS_syscall_return */
|
" mov r0, #0\n" /* R0=SYS_syscall_return */
|
||||||
" svc #0x900001" /* Return from the SYSCALL */
|
" svc #0x900001\n" /* Return from the SYSCALL */
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -202,7 +203,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||||||
|
|
||||||
case SYS_syscall_return:
|
case SYS_syscall_return:
|
||||||
{
|
{
|
||||||
struct tcb_s *rtcb = sched_self();
|
FAR struct tcb_s *rtcb = sched_self();
|
||||||
int index = (int)rtcb->xcp.nsyscalls - 1;
|
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. */
|
||||||
@ -293,6 +294,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
|
||||||
/* R0=SYS_signal_handler: This a user signal handler callback
|
/* R0=SYS_signal_handler: This a user signal handler callback
|
||||||
*
|
*
|
||||||
* void signal_handler(_sa_sigaction_t sighand, int signo,
|
* void signal_handler(_sa_sigaction_t sighand, int signo,
|
||||||
@ -307,12 +309,9 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||||||
* ucontext (on the stack)
|
* ucontext (on the stack)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
|
|
||||||
case SYS_signal_handler:
|
case SYS_signal_handler:
|
||||||
{
|
{
|
||||||
#warning Missing logic
|
FAR struct tcb_s *rtcb = sched_self();
|
||||||
#if 0
|
|
||||||
struct tcb_s *rtcb = sched_self();
|
|
||||||
|
|
||||||
/* Remember the caller's return address */
|
/* Remember the caller's return address */
|
||||||
|
|
||||||
@ -323,7 +322,7 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||||||
* unprivileged mode.
|
* 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;
|
cpsr = regs[REG_CPSR] & ~PSR_MODE_MASK;
|
||||||
regs[REG_CPSR] = cpsr | PSR_MODE_USR;
|
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]);
|
regs[REG_R3] = *(uint32_t*)(regs[REG_SP+4]);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
|
||||||
/* R0=SYS_signal_handler_return: This a user signal handler callback
|
/* R0=SYS_signal_handler_return: This a user signal handler callback
|
||||||
*
|
*
|
||||||
* void signal_handler_return(void);
|
* void signal_handler_return(void);
|
||||||
@ -354,12 +353,9 @@ uint32_t *arm_syscall(uint32_t *regs)
|
|||||||
* R0 = SYS_signal_handler_return
|
* R0 = SYS_signal_handler_return
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_SIGNALS)
|
|
||||||
case SYS_signal_handler_return:
|
case SYS_signal_handler_return:
|
||||||
{
|
{
|
||||||
#warning Missing logic
|
FAR struct tcb_s *rtcb = sched_self();
|
||||||
#if 0
|
|
||||||
struct tcb_s *rtcb = sched_self();
|
|
||||||
|
|
||||||
/* Set up to return to the kernel-mode signal dispatching logic. */
|
/* 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;
|
cpsr = regs[REG_CPSR] & ~PSR_MODE_MASK;
|
||||||
regs[REG_CPSR] = cpsr | PSR_MODE_SVC;
|
regs[REG_CPSR] = cpsr | PSR_MODE_SVC;
|
||||||
rtcb->xcp.sigreturn = 0;
|
rtcb->xcp.sigreturn = 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <nuttx/addrenv.h>
|
||||||
|
|
||||||
#ifdef CONFIG_BUILD_KERNEL
|
#ifdef CONFIG_BUILD_KERNEL
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -61,6 +63,48 @@ extern main_t main;
|
|||||||
* Private Functions
|
* 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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -89,6 +133,14 @@ void _start(int argc, FAR char *argv[])
|
|||||||
{
|
{
|
||||||
int ret;
|
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 */
|
/* Call C++ constructors */
|
||||||
/* Setup so that C++ destructors called on task exit */
|
/* Setup so that C++ destructors called on task exit */
|
||||||
/* REVISIT: Missing logic */
|
/* REVISIT: Missing logic */
|
||||||
|
@ -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.
|
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
@ -85,7 +85,7 @@ CMN_CSRCS += arm_va2pte.c
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_BUILD_KERNEL),y)
|
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
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ARCH_ADDRENV),y)
|
ifeq ($(CONFIG_ARCH_ADDRENV),y)
|
||||||
|
Loading…
Reference in New Issue
Block a user