Misoc LM32: Add signal handling logic

This commit is contained in:
Ramtin Amin 2016-11-24 12:58:23 -06:00 committed by Gregory Nutt
parent f77dcdf323
commit 7568aaf213
8 changed files with 438 additions and 26 deletions

View File

@ -195,11 +195,44 @@
struct xcptcontext
{
#ifndef CONFIG_DISABLE_SIGNALS
/* The following function pointer is non-NULL if there are pending signals
* to be processed.
*/
void *sigdeliver; /* Actual type is sig_deliver_t */
/* These additional register save locations are used to implement the
* signal delivery trampoline.
*/
uint32_t saved_epc; /* Trampoline PC */
uint32_t saved_int_ctx; /* Interrupt context with interrupts disabled. */
# ifdef CONFIG_BUILD_KERNEL
/* This is the saved address to use when returning from a user-space
* signal handler.
*/
uint32_t sigreturn;
# endif
#endif
#ifdef CONFIG_BUILD_KERNEL
/* The following array holds information needed to return from each nested
* system call.
*/
uint8_t nsyscalls;
struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST];
#endif
/* Register save area */
uint32_t regs[XCPTCONTEXT_REGS];
};
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_MISOC_INCLUDE_LM32_IRQ_H */

View File

@ -49,4 +49,4 @@ CHIP_CSRCS += lm32_doirq.c lm32_dumpstate.c lm32_exit.c lm32_idle.c
CHIP_CSRCS += lm32_initialize.c lm32_initialstate.c lm32_interruptcontext.c
CHIP_CSRCS += lm32_irq.c lm32_releasepending.c lm32_releasestack.c
CHIP_CSRCS += lm32_stackframe.c lm32_swint.c lm32_unblocktask.c
CHIP_CSRCS += lm32_reprioritizertr.c
CHIP_CSRCS += lm32_reprioritizertr.c lm32_schedulesigaction.c lm32_sigdeliver.c

View File

@ -57,16 +57,17 @@
* logic.
*/
#define STACK_COLOR 0xdeadbeef
#define INTSTACK_COLOR 0xdeadbeef
#define HEAP_COLOR 'h'
#define STACK_COLOR 0xdeadbeef
#define INTSTACK_COLOR 0xdeadbeef
#define HEAP_COLOR 'h'
/* In the LM32 model, the state is copied from the stack to the TCB, but
* only a referenced is passed to get the state from the TCB.
*/
#define up_savestate(regs) lm32_copystate(regs, (uint32_t*)g_current_regs)
#define up_restorestate(regs) (g_current_regs = regs)
#define up_savestate(regs) lm32_copystate(regs, (uint32_t*)g_current_regs)
#define up_copystate(rega,regb) lm32_copystate(rega, regb)
#define up_restorestate(regs) (g_current_regs = regs)
/* Determine which (if any) console driver to use. If a console is enabled
* and no other console device is specified, then a serial console is

View File

@ -101,7 +101,7 @@ void up_initial_state(struct tcb_s *tcb)
/* Initial state of IE: Interrupts enabled */
xcp->regs[REG_INT_CTX] = 1;
xcp->regs[REG_INT_CTX] = 2;
/* If this task is running PIC, then set the PIC base register to the
* address of the allocated D-Space region.

View File

@ -0,0 +1,207 @@
/****************************************************************************
* arch/misoc/src/lm32/lm32_schedulesigaction.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Modified for MISOC:
*
* Copyright (C) 2016 Ramtin Amin. All rights reserved.
* Author: Ramtin Amin <keytwo@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <sched.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <arch/lm32/irq.h>
#include "sched/sched.h"
#include "lm32.h"
#ifndef CONFIG_DISABLE_SIGNALS
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_schedule_sigaction
*
* Description:
* This function is called by the OS when one or more
* signal handling actions have been queued for execution.
* The architecture specific code must configure things so
* that the 'igdeliver' callback is executed on the thread
* specified by 'tcb' as soon as possible.
*
* This function may be called from interrupt handling logic.
*
* This operation should not cause the task to be unblocked
* nor should it cause any immediate execution of sigdeliver.
* Typically, a few cases need to be considered:
*
* (1) This function may be called from an interrupt handler
* During interrupt processing, all xcptcontext structures
* should be valid for all tasks. That structure should
* be modified to invoke sigdeliver() either on return
* from (this) interrupt or on some subsequent context
* switch to the recipient task.
* (2) If not in an interrupt handler and the tcb is NOT
* the currently executing task, then again just modify
* the saved xcptcontext structure for the recipient
* task so it will invoke sigdeliver when that task is
* later resumed.
* (3) If not in an interrupt handler and the tcb IS the
* currently executing task -- just call the signal
* handler now.
*
****************************************************************************/
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
{
irqstate_t flags;
uint32_t int_ctx;
sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver);
/* Make sure that interrupts are disabled */
flags = enter_critical_section();
/* Refuse to handle nested signal actions */
if (!tcb->xcp.sigdeliver)
{
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/
sinfo("rtcb=0x%p g_current_regs=0x%p\n",
this_task(), g_current_regs);
if (tcb == this_task())
{
/* CASE 1: We are not in an interrupt handler and
* a task is signalling itself for some reason.
*/
if (!g_current_regs)
{
/* In this case just deliver the signal now. */
sigdeliver(tcb);
}
/* CASE 2: We are in an interrupt handler AND the
* interrupted task is the same as the one that
* must receive the signal, then we will have to modify
* the return state as well as the state in the TCB.
*
* Hmmm... there looks like a latent bug here: The following
* logic would fail in the strange case where we are in an
* interrupt handler, the thread is signalling itself, but
* a context switch to another task has occurred so that
* g_current_regs does not refer to the thread of this_task()!
*/
else
{
/* Save the return EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.sigdeliver = sigdeliver;
tcb->xcp.saved_epc = g_current_regs[REG_EPC];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
g_current_regs[REG_EPC] = (uint32_t)up_sigdeliver;
g_current_regs[REG_INT_CTX] = 0;
/* And make sure that the saved context in the TCB
* is the same as the interrupt return context.
*/
up_savestate(tcb->xcp.regs);
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
g_current_regs[REG_EPC], g_current_regs[REG_STATUS]);
}
}
/* Otherwise, we are (1) signaling a task is not running
* from an interrupt handler or (2) we are not in an
* interrupt handler and the running task is signalling
* some non-running task.
*/
else
{
/* Save the return EPC and STATUS registers. These will be
* restored by the signal trampoline after the signals have
* been delivered.
*/
tcb->xcp.sigdeliver = sigdeliver;
tcb->xcp.saved_epc = tcb->xcp.regs[REG_EPC];
tcb->xcp.saved_int_ctx = tcb->xcp.regs[REG_INT_CTX];
/* Then set up to vector to the trampoline with interrupts
* disabled
*/
tcb->xcp.regs[REG_EPC] = (uint32_t)up_sigdeliver;
tcb->xcp.regs[REG_INT_CTX] = 0;
sinfo("PC/STATUS Saved: %08x/%08x New: %08x/%08x\n",
tcb->xcp.saved_epc, tcb->xcp.saved_status,
tcb->xcp.regs[REG_EPC], tcb->xcp.regs[REG_STATUS]);
}
}
leave_critical_section(flags);
}
#endif /* !CONFIG_DISABLE_SIGNALS */

View File

@ -0,0 +1,136 @@
/****************************************************************************
* arch/misoc/src/lm32/lm32_sigdeliver.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <sched.h>
#include <syscall.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
#include "sched/sched.h"
#include "lm32.h"
#ifndef CONFIG_DISABLE_SIGNALS
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_sigdeliver
*
* Description:
* This is the a signal handling trampoline. When a signal action was
* posted. The task context was mucked with and forced to branch to this
* location with interrupts disabled.
*
****************************************************************************/
void up_sigdeliver(void)
{
struct tcb_s *rtcb = this_task();
uint32_t regs[XCPTCONTEXT_REGS];
sig_deliver_t sigdeliver;
/* Save the errno. This must be preserved throughout the signal handling
* so that the user code final gets the correct errno value (probably
* EINTR).
*/
int saved_errno = rtcb->pterrno;
board_autoled_on(LED_SIGNAL);
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
ASSERT(rtcb->xcp.sigdeliver != NULL);
/* Save the real return state on the stack. */
up_copystate(regs, rtcb->xcp.regs);
regs[REG_EPC] = rtcb->xcp.saved_epc;
regs[REG_INT_CTX] = rtcb->xcp.saved_int_ctx;
/* Get a local copy of the sigdeliver function pointer. We do this so that
* we can nullify the sigdeliver function pointer in the TCB and accept
* more signal deliveries while processing the current pending signals.
*/
sigdeliver = rtcb->xcp.sigdeliver;
rtcb->xcp.sigdeliver = NULL;
/* Then restore the task interrupt state */
up_irq_restore((irqstate_t)regs[REG_INT_CTX]);
/* Deliver the signals */
sigdeliver(rtcb);
/* Output any debug messages BEFORE restoring errno (because they may
* alter errno), then disable interrupts again and restore the original
* errno that is needed by the user logic (it is probably EINTR).
*/
sinfo("Resuming EPC: %08x INT_CTX: %08x\n", regs[REG_EPC], regs[REG_INT_CTX]);
(void)up_irq_save();
rtcb->pterrno = saved_errno;
/* Then restore the correct state for this thread of
* execution.
*/
board_autoled_off(LED_SIGNAL);
up_fullcontextrestore(regs);
/* up_fullcontextrestore() should not return but could if the software
* interrupts are disabled.
*/
PANIC();
}
#endif /* !CONFIG_DISABLE_SIGNALS */

View File

@ -208,7 +208,6 @@ _do_reset:
sw (sp+REG_X23), r23
sw (sp+REG_X24), r24
sw (sp+REG_X25), r25
sw (sp+REG_GP), r26
sw (sp+REG_FP), r27
@ -217,7 +216,7 @@ _do_reset:
addi r1, sp, 136
sw (sp+REG_SP), r1
/* reg RA done later */
/* Reg RA done later */
sw (sp+REG_EA), r30
sw (sp+REG_BA), r31
@ -235,6 +234,10 @@ _do_reset:
/* The 2nd argument is the regs pointer */
addi r2, sp, 0
/* Move sp away from X0 */
addi sp, sp, -4
ret
.restore_all_and_eret:

View File

@ -162,7 +162,7 @@ CONFIG_BOOT_RUNFROMFLASH=y
# Boot Memory Configuration
#
CONFIG_RAM_START=0x40000000
CONFIG_RAM_SIZE=524288
CONFIG_RAM_SIZE=67108864
# CONFIG_ARCH_HAVE_SDRAM is not set
#
@ -192,12 +192,7 @@ CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH=y
#
# RTOS Features
#
CONFIG_DISABLE_OS_API=y
CONFIG_DISABLE_POSIX_TIMERS=y
CONFIG_DISABLE_PTHREAD=y
CONFIG_DISABLE_SIGNALS=y
CONFIG_DISABLE_MQUEUE=y
CONFIG_DISABLE_ENVIRON=y
# CONFIG_DISABLE_OS_API is not set
#
# Clocks and Timers
@ -222,12 +217,18 @@ CONFIG_PREALLOC_TIMERS=0
CONFIG_INIT_ENTRYPOINT=y
# CONFIG_INIT_FILEPATH is not set
CONFIG_USER_ENTRYPOINT="nsh_main"
CONFIG_RR_INTERVAL=0
CONFIG_RR_INTERVAL=200
# CONFIG_SCHED_SPORADIC is not set
CONFIG_TASK_NAME_SIZE=0
CONFIG_MAX_TASKS=4
CONFIG_MAX_TASKS=16
# CONFIG_SCHED_HAVE_PARENT is not set
# CONFIG_SCHED_WAITPID is not set
CONFIG_SCHED_WAITPID=y
#
# Pthread Options
#
# CONFIG_MUTEX_TYPES is not set
CONFIG_NPTHREAD_KEYS=4
#
# Performance Monitoring
@ -254,19 +255,36 @@ CONFIG_NAME_MAX=32
# CONFIG_SCHED_STARTHOOK is not set
# CONFIG_SCHED_ATEXIT is not set
# CONFIG_SCHED_ONEXIT is not set
#
# Signal Numbers
#
CONFIG_SIG_SIGUSR1=1
CONFIG_SIG_SIGUSR2=2
CONFIG_SIG_SIGALARM=3
CONFIG_SIG_SIGCONDTIMEDOUT=16
#
# POSIX Message Queue Options
#
CONFIG_PREALLOC_MQ_MSGS=32
CONFIG_MQ_MAXMSGSIZE=32
# CONFIG_MODULE is not set
#
# Work queue support
#
# CONFIG_SCHED_WORKQUEUE is not set
# CONFIG_SCHED_HPWORK is not set
# CONFIG_SCHED_LPWORK is not set
#
# Stack and heap information
#
CONFIG_IDLETHREAD_STACKSIZE=1024
CONFIG_USERMAIN_STACKSIZE=1024
CONFIG_PTHREAD_STACK_MIN=512
CONFIG_PTHREAD_STACK_DEFAULT=1024
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_USERMAIN_STACKSIZE=2048
CONFIG_PTHREAD_STACK_MIN=256
CONFIG_PTHREAD_STACK_DEFAULT=2048
# CONFIG_LIB_SYSCALL is not set
#
@ -431,7 +449,9 @@ CONFIG_DISABLE_PSEUDOFS_OPERATIONS=y
# CONFIG_FS_READABLE is not set
# CONFIG_FS_WRITABLE is not set
# CONFIG_FS_NAMED_SEMAPHORES is not set
CONFIG_FS_MQUEUE_MPATH="/var/mqueue"
# CONFIG_FS_RAMMAP is not set
# CONFIG_FS_BINFS is not set
# CONFIG_FS_PROCFS is not set
# CONFIG_FS_UNIONFS is not set
@ -461,9 +481,10 @@ CONFIG_MM_REGIONS=1
# Binary Loader
#
# CONFIG_BINFMT_DISABLE is not set
# CONFIG_BINFMT_EXEPATH is not set
# CONFIG_NXFLAT is not set
# CONFIG_ELF is not set
# CONFIG_BUILTIN is not set
CONFIG_BUILTIN=y
# CONFIG_PIC is not set
# CONFIG_SYMTAB_ORDEREDBYNAME is not set
@ -477,6 +498,7 @@ CONFIG_MM_REGIONS=1
CONFIG_STDIO_BUFFER_SIZE=0
CONFIG_STDIO_LINEBUFFER=y
CONFIG_NUNGET_CHARS=0
CONFIG_LIB_HOMEDIR="/"
# CONFIG_LIBM is not set
# CONFIG_NOPRINTF_FIELDWIDTH is not set
# CONFIG_LIBC_FLOATINGPOINT is not set
@ -495,6 +517,7 @@ CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
# CONFIG_LIBC_STRERROR is not set
# CONFIG_LIBC_PERROR_STDOUT is not set
CONFIG_ARCH_LOWPUTC=y
# CONFIG_LIBC_LOCALTIME is not set
# CONFIG_TIME_EXTENDED is not set
CONFIG_LIB_SENDFILE_BUFSIZE=512
# CONFIG_ARCH_ROMGETC is not set
@ -520,6 +543,11 @@ CONFIG_LIB_SENDFILE_BUFSIZE=512
# Application Configuration
#
#
# Built-In Applications
#
CONFIG_BUILTIN_PROXY_STACKSIZE=1024
#
# CAN Utilities
#
@ -548,10 +576,10 @@ CONFIG_EXAMPLES_HELLO_STACKSIZE=2048
# CONFIG_EXAMPLES_NRF24L01TERM is not set
CONFIG_EXAMPLES_NSH=y
# CONFIG_EXAMPLES_NULL is not set
# CONFIG_EXAMPLES_NX is not set
# CONFIG_EXAMPLES_NXFFS is not set
# CONFIG_EXAMPLES_NXHELLO is not set
# CONFIG_EXAMPLES_NXIMAGE is not set
# CONFIG_EXAMPLES_NX is not set
# CONFIG_EXAMPLES_NXLINES is not set
# CONFIG_EXAMPLES_NXTERM is not set
# CONFIG_EXAMPLES_NXTEXT is not set
@ -561,6 +589,7 @@ CONFIG_EXAMPLES_OSTEST_STACKSIZE=8192
CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS=8
CONFIG_EXAMPLES_OSTEST_RR_RANGE=10000
CONFIG_EXAMPLES_OSTEST_RR_RUNS=10
CONFIG_EXAMPLES_OSTEST_WAITRESULT=y
# CONFIG_EXAMPLES_PCA9635 is not set
# CONFIG_EXAMPLES_POSIXSPAWN is not set
# CONFIG_EXAMPLES_PPPD is not set
@ -573,6 +602,7 @@ CONFIG_EXAMPLES_OSTEST_RR_RUNS=10
# CONFIG_EXAMPLES_SERLOOP is not set
# CONFIG_EXAMPLES_SLCD is not set
# CONFIG_EXAMPLES_SMART is not set
# CONFIG_EXAMPLES_SMART_TEST is not set
# CONFIG_EXAMPLES_SMP is not set
# CONFIG_EXAMPLES_TCPECHO is not set
# CONFIG_EXAMPLES_TELNETD is not set
@ -637,6 +667,7 @@ CONFIG_NSH_MAXARGUMENTS=6
CONFIG_NSH_ARGCAT=y
CONFIG_NSH_NESTDEPTH=3
# CONFIG_NSH_DISABLEBG is not set
CONFIG_NSH_BUILTIN_APPS=y
#
# Disable Individual commands
@ -741,6 +772,7 @@ CONFIG_READLINE_ECHO=y
# CONFIG_READLINE_TABCOMPLETION is not set
# CONFIG_READLINE_CMD_HISTORY is not set
# CONFIG_SYSTEM_SUDOKU is not set
# CONFIG_SYSTEM_SYSTEM is not set
# CONFIG_SYSTEM_TEE is not set
# CONFIG_SYSTEM_UBLOXMODEM is not set
# CONFIG_SYSTEM_VI is not set