arch/sim: Model host signal as NuttX's interrupt

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2020-08-29 14:06:56 +08:00 committed by liuguo09
parent 5db11a275e
commit 5107104bbe
5 changed files with 131 additions and 7 deletions

View File

@ -72,7 +72,6 @@ config ARCH_SIM
select ARCH_HAVE_TICKLESS
select ARCH_HAVE_POWEROFF
select ARCH_HAVE_TESTSET
select ARCH_NOINTC
select ALARM_ARCH
select ONESHOT
select SERIAL_CONSOLE

View File

@ -44,9 +44,7 @@
* Pre-processor Definitions
****************************************************************************/
/* No interrupts */
#define NR_IRQS 0
#define NR_IRQS 64
/* Number of registers saved in context switch */

View File

@ -25,6 +25,19 @@
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "up_internal.h"
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef CONFIG_SMP
volatile void *g_current_regs[CONFIG_SMP_NCPUS];
#else
volatile void *g_current_regs[1];
#endif
/****************************************************************************
* Private Types
@ -36,6 +49,19 @@ union sigset_u
sigset_t sigset;
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: up_handle_irq
****************************************************************************/
static void up_handle_irq(int irq, siginfo_t *info, void *context)
{
up_doirq(irq, context);
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -86,3 +112,48 @@ void up_irq_restore(uint64_t flags)
void up_irqinitialize(void)
{
}
/****************************************************************************
* Name: up_enable_irq
*
* Description:
* Enable the IRQ specified by 'irq'
*
****************************************************************************/
void up_enable_irq(int irq)
{
struct sigaction act;
sigset_t set;
/* Register signal handler */
memset(&act, 0, sizeof(act));
act.sa_sigaction = up_handle_irq;
act.sa_flags = SA_SIGINFO;
sigfillset(&act.sa_mask);
sigaction(irq, &act, NULL);
/* Unmask the signal */
sigemptyset(&set);
sigaddset(&set, irq);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
}
/****************************************************************************
* Name: up_disable_irq
*
* Description:
* Disable the IRQ specified by 'irq'
*
****************************************************************************/
void up_disable_irq(int irq)
{
/* Since it's hard to mask the signal on all threads,
* let's change the signal handler to ignore instead.
*/
signal(irq, SIG_IGN);
}

View File

@ -169,6 +169,28 @@ struct ioexpander_dev_s;
* Public Data
****************************************************************************/
/* g_current_regs[] holds a references to the current interrupt level
* register storage structure. If is non-NULL only during interrupt
* processing. Access to g_current_regs[] must be through the macro
* CURRENT_REGS for portability.
*/
#ifdef CONFIG_SMP
/* For the case of architectures with multiple CPUs, then there must be one
* such value for each processor that can receive an interrupt.
*/
int up_cpu_index(void); /* See include/nuttx/arch.h */
extern volatile void *g_current_regs[CONFIG_SMP_NCPUS];
# define CURRENT_REGS (g_current_regs[up_cpu_index()])
#else
extern volatile void *g_current_regs[1];
# define CURRENT_REGS (g_current_regs[0])
#endif
#ifdef CONFIG_SMP
/* These spinlocks are used in the SMP configuration in order to implement
* up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
@ -192,6 +214,8 @@ extern volatile uint8_t g_cpu_paused[CONFIG_SMP_NCPUS];
* Public Function Prototypes
****************************************************************************/
void *up_doirq(int irq, void *regs);
/* up_setjmp32.S ************************************************************/
int up_setjmp(void *jb);

View File

@ -41,6 +41,7 @@
#include <stdbool.h>
#include <nuttx/arch.h>
#include "up_internal.h"
/****************************************************************************
@ -58,7 +59,38 @@
bool up_interrupt_context(void)
{
/* The simulation is never in the interrupt state */
return false;
return CURRENT_REGS != NULL;
}
/****************************************************************************
* Name: up_doirq
****************************************************************************/
void *up_doirq(int irq, void *regs)
{
/* Current regs non-zero indicates that we are processing an interrupt;
* CURRENT_REGS is also used to manage interrupt level context switches.
*/
CURRENT_REGS = regs;
/* Deliver the IRQ */
irq_dispatch(irq, regs);
/* If a context switch occurred while processing the interrupt then
* CURRENT_REGS may have change value. If we return any value different
* from the input regs, then the lower level will know that a context
* switch occurred during interrupt processing.
*/
regs = (void *)CURRENT_REGS;
/* Restore the previous value of CURRENT_REGS. NULL would indicate that
* we are no longer in an interrupt handler. It will be non-NULL if we
* are returning from a nested interrupt.
*/
CURRENT_REGS = NULL;
return regs;
}