From 12775801c93051e5ff46a6f156775b1855adc424 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 2 Sep 2014 15:58:14 -0600 Subject: [PATCH] Add support for delivery of use-mode signals in the kernel build. --- arch/arm/include/armv7-a/irq.h | 9 ++++ arch/arm/src/a1x/Make.defs | 2 +- arch/arm/src/armv7-a/arm_addrenv.c | 6 +-- arch/arm/src/armv7-a/arm_syscall.c | 21 ++++------ arch/arm/src/armv7-a/crt0.c | 52 ++++++++++++++++++++++++ arch/arm/src/armv7-m/up_signal_handler.S | 2 +- arch/arm/src/sama5/Make.defs | 2 +- 7 files changed, 75 insertions(+), 19 deletions(-) diff --git a/arch/arm/include/armv7-a/irq.h b/arch/arm/include/armv7-a/irq.h index 3373819dfb..00e7244ae2 100755 --- a/arch/arm/include/armv7-a/irq.h +++ b/arch/arm/include/armv7-a/irq.h @@ -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 */ diff --git a/arch/arm/src/a1x/Make.defs b/arch/arm/src/a1x/Make.defs index 17aa9bbe24..c06e3a6c8f 100644 --- a/arch/arm/src/a1x/Make.defs +++ b/arch/arm/src/a1x/Make.defs @@ -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) diff --git a/arch/arm/src/armv7-a/arm_addrenv.c b/arch/arm/src/armv7-a/arm_addrenv.c index bdb6c291d1..1c1bba0a3e 100644 --- a/arch/arm/src/armv7-a/arm_addrenv.c +++ b/arch/arm/src/armv7-a/arm_addrenv.c @@ -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; } diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c index 0295ffafef..846849b332 100644 --- a/arch/arm/src/armv7-a/arm_syscall.c +++ b/arch/arm/src/armv7-a/arm_syscall.c @@ -47,6 +47,7 @@ #include #include +#include #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 diff --git a/arch/arm/src/armv7-a/crt0.c b/arch/arm/src/armv7-a/crt0.c index cda8944339..8b661708eb 100644 --- a/arch/arm/src/armv7-a/crt0.c +++ b/arch/arm/src/armv7-a/crt0.c @@ -41,6 +41,8 @@ #include +#include + #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 */ diff --git a/arch/arm/src/armv7-m/up_signal_handler.S b/arch/arm/src/armv7-m/up_signal_handler.S index 38a0bd35d3..e220ddf107 100644 --- a/arch/arm/src/armv7-m/up_signal_handler.S +++ b/arch/arm/src/armv7-m/up_signal_handler.S @@ -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 diff --git a/arch/arm/src/sama5/Make.defs b/arch/arm/src/sama5/Make.defs index dc4544df72..241bb6a60e 100644 --- a/arch/arm/src/sama5/Make.defs +++ b/arch/arm/src/sama5/Make.defs @@ -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)