From 73453a39d1de5ba865b94f6c0c89408fae782c17 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Mon, 14 Feb 2022 14:30:34 -0800 Subject: [PATCH] arch: Add IRQ_OFFSET_NESTED feature The x86 and xtensa implementations of irq_offload() invoke synchronous interrupts on the local CPU, and are therefore safe to use from within an interrupt context. This is a cheap and portable way to exercise nested interrupts, which are otherwise highly platform-dependent to test. Add a kconfig to signal the capability. Signed-off-by: Andy Ross --- arch/Kconfig | 10 ++++++++++ include/irq_offload.h | 7 +++++++ kernel/thread.c | 4 ++++ 3 files changed, 21 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index 937382c1b62..a619ee6ccc5 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -84,6 +84,7 @@ config X86 select ARCH_HAS_TIMING_FUNCTIONS select ARCH_HAS_THREAD_LOCAL_STORAGE select ARCH_HAS_DEMAND_PAGING + select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD select NEED_LIBC_MEM_PARTITION if USERSPACE && TIMING_FUNCTIONS \ && !BOARD_HAS_TIMING_FUNCTIONS \ && !SOC_HAS_TIMING_FUNCTIONS @@ -116,6 +117,7 @@ config XTENSA select HAS_DTS select USE_SWITCH select USE_SWITCH_SUPPORTED + select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD imply ATOMIC_OPERATIONS_ARCH help Xtensa architecture @@ -438,6 +440,14 @@ config IRQ_OFFLOAD run in interrupt context. Only useful for test cases that need to validate the correctness of kernel objects in IRQ context. +config IRQ_OFFLOAD_NESTED + bool "irq_offload() supports nested IRQs" + depends on IRQ_OFFLOAD + help + When set by the arch layer, indicates that irq_offload() may + legally be called in interrupt context to cause a + synchronous nested interrupt on the current CPU. Not all + hardware is capable. config EXTRA_EXCEPTION_INFO bool "Collect extra exception info" diff --git a/include/irq_offload.h b/include/irq_offload.h index 1a651b2dcfd..9651a757ced 100644 --- a/include/irq_offload.h +++ b/include/irq_offload.h @@ -25,6 +25,13 @@ typedef void (*irq_offload_routine_t)(const void *parameter); * which needs to show that kernel objects work correctly in interrupt * context. * + * Additionally, when CONFIG_IRQ_OFFLOAD_NESTED is set by the + * architecture, this routine works to synchronously invoke a nested + * interrupt when called from an ISR context (i.e. when k_is_in_isr() + * is true). Note that not all platforms will have hardware support + * for this capability, and even on those some interrupts may be + * running at unpreemptible priorities. + * * @param routine The function to run * @param parameter Argument to pass to the function when it is run as an * interrupt diff --git a/kernel/thread.c b/kernel/thread.c index 275f2fdea4a..9109b60f143 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -890,9 +890,13 @@ K_SEM_DEFINE(offload_sem, 1, 1); void irq_offload(irq_offload_routine_t routine, const void *parameter) { +#ifdef CONFIG_IRQ_OFFLOAD_NESTED + arch_irq_offload(routine, parameter); +#else k_sem_take(&offload_sem, K_FOREVER); arch_irq_offload(routine, parameter); k_sem_give(&offload_sem); +#endif } #endif