arch/sim: Model host signal as NuttX's interrupt
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
parent
5db11a275e
commit
5107104bbe
@ -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
|
||||
|
@ -44,9 +44,7 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* No interrupts */
|
||||
|
||||
#define NR_IRQS 0
|
||||
#define NR_IRQS 64
|
||||
|
||||
/* Number of registers saved in context switch */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user