From b488b396bbc3e6e7b7845d1656ec9bcc10c6eeb4 Mon Sep 17 00:00:00 2001 From: Enjia Mai Date: Sun, 28 Feb 2021 22:34:06 +0800 Subject: [PATCH] tests: improve test cases for interrupt testing Improve dynamic interrupt test cases of interrupt for platform such as x86, x86_64, native_posix, this improve code coverage of it. Signed-off-by: Enjia Mai --- tests/kernel/interrupt/CMakeLists.txt | 5 ++ tests/kernel/interrupt/prj.conf | 1 + tests/kernel/interrupt/src/dynamic_isr.c | 94 +++++++++++++++++++-- tests/kernel/interrupt/src/interrupt_util.h | 63 ++++++++++++++ 4 files changed, 155 insertions(+), 8 deletions(-) diff --git a/tests/kernel/interrupt/CMakeLists.txt b/tests/kernel/interrupt/CMakeLists.txt index d27692962aa..a7c3f862911 100644 --- a/tests/kernel/interrupt/CMakeLists.txt +++ b/tests/kernel/interrupt/CMakeLists.txt @@ -6,3 +6,8 @@ project(interrupt) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) + +target_include_directories(app PRIVATE + ${ZEPHYR_BASE}/kernel/include + ${ZEPHYR_BASE}/arch/${ARCH}/include + ) diff --git a/tests/kernel/interrupt/prj.conf b/tests/kernel/interrupt/prj.conf index 673e4724372..e4ba089e3bd 100644 --- a/tests/kernel/interrupt/prj.conf +++ b/tests/kernel/interrupt/prj.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y CONFIG_DYNAMIC_INTERRUPTS=y CONFIG_MP_NUM_CPUS=1 +CONFIG_THREAD_STACK_INFO=y diff --git a/tests/kernel/interrupt/src/dynamic_isr.c b/tests/kernel/interrupt/src/dynamic_isr.c index 0fc440cc0c6..e3a5c5965a6 100644 --- a/tests/kernel/interrupt/src/dynamic_isr.c +++ b/tests/kernel/interrupt/src/dynamic_isr.c @@ -5,25 +5,37 @@ */ #include +#include "interrupt_util.h" -#if defined(CONFIG_DYNAMIC_INTERRUPTS) && defined(CONFIG_GEN_SW_ISR_TABLE) -extern struct _isr_table_entry __sw_isr_table _sw_isr_table[]; -extern void z_irq_spurious(const void *unused); +#if defined(CONFIG_DYNAMIC_INTERRUPTS) + +#define ISR_DYN_ARG 0xab249cfd + +static unsigned int handler_has_run; +static uintptr_t handler_test_result; static void dyn_isr(const void *arg) { ARG_UNUSED(arg); + handler_test_result = (uintptr_t)arg; + handler_has_run = 1; } +#if defined(CONFIG_GEN_SW_ISR_TABLE) +extern struct _isr_table_entry __sw_isr_table _sw_isr_table[]; +extern void z_irq_spurious(const void *unused); + /** * @brief Test dynamic ISR installation * * @ingroup kernel_interrupt_tests * - * This routine locates an unused entry in the software ISR table, installs a - * dynamic ISR to the unused entry by calling the `arch_irq_connect_dynamic` - * function, and verifies that the ISR is successfully installed by checking - * the software ISR table entry. + * @details This routine locates an unused entry in the software ISR table, + * installs a dynamic ISR to the unused entry by calling the dynamic + * configured function, and verifies that the ISR is successfully installed + * by checking the software ISR table entry. + * + * @see arch_irq_connect_dynamic() */ void test_isr_dynamic(void) { @@ -50,10 +62,76 @@ void test_isr_dynamic(void) _sw_isr_table[i].arg == argval, "dynamic isr did not install successfully"); } +#else +/* + * For testing arch such as x86, x86_64 and posix which support dynamic + * interrupt but without SW ISR table, we test it by applying for a dynamic + * interrupt and then trigger it to check if happened correctly. + */ +static int get_dynamic_interrupt_line(void) +{ +#ifdef TEST_IRQ_DYN_LINE + return TEST_IRQ_DYN_LINE; +#else + return -1; +#endif +} + +void test_isr_dynamic(void) +{ + int irq_dyn_line; + int vector_num; + + /* Get a irq line for dynamic interrupt */ + irq_dyn_line = get_dynamic_interrupt_line(); + + /**TESTPOINT: configuration of interrupts dynamically at runtime */ + vector_num = arch_irq_connect_dynamic(irq_dyn_line, 1, dyn_isr, + (void *)ISR_DYN_ARG, 0); + +#if defined(CONFIG_X86_64) +/* The isr table for x86_64 is visiable, so check it up here */ +extern void (*x86_irq_funcs[])(const void *); +extern const void *x86_irq_args[]; + + zassert_true(x86_irq_funcs[irq_dyn_line] == dyn_isr && + x86_irq_args[irq_dyn_line] == (void *)ISR_DYN_ARG, + "dynamic isr did not install successfully"); +#endif + + TC_PRINT("vector(%d)\n", vector_num); + zassert_true(vector_num > 0, + "irq connect dynamic failed"); + + zassert_equal(handler_has_run, 0, + "handler has run before interrupt trigger"); + + irq_enable(irq_dyn_line); + + trigger_irq(irq_dyn_line); + + zassert_equal(handler_has_run, 1, + "interrupt triggered but handler has not run(%d)", + handler_has_run); + + /**TESTPOINT: pass word-sized parameter to interrupt */ + zassert_equal(handler_test_result, ISR_DYN_ARG, + "parameter(0x%lx) in handler is not correct", + handler_test_result); + + irq_disable(irq_dyn_line); + + /**TESTPOINT: interrupt cannot be triggered when disable it */ + zassert_equal(handler_has_run, 1, + "interrupt handler should not be triggered again(%d)", + handler_has_run); +} +#endif /* CONFIG_GEN_SW_ISR_TABLE */ + #else /* Skip the dynamic interrupt test for the platforms that do not support it */ void test_isr_dynamic(void) { ztest_test_skip(); } -#endif /* CONFIG_DYNAMIC_INTERRUPTS && CONFIG_GEN_SW_ISR_TABLE */ +#endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/tests/kernel/interrupt/src/interrupt_util.h b/tests/kernel/interrupt/src/interrupt_util.h index b8fb43aa211..cc3cd1e2862 100644 --- a/tests/kernel/interrupt/src/interrupt_util.h +++ b/tests/kernel/interrupt/src/interrupt_util.h @@ -99,6 +99,69 @@ static inline void trigger_irq(int irq) printk("Triggering irq : %d\n", irq); z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_HINT, irq); } + +#elif defined(CONFIG_X86) + +#define TEST_IRQ_DYN_LINE 16 +#define TEST_DYNAMIC_VECTOR TEST_IRQ_DYN_LINE+32 + +static inline void trigger_irq(int irq) +{ + int vector = irq + 32; + +/* + * Trigger an interrupt of x86 under gcov code coverage report enabled, + * which means GCC optimization will be -O0, so need to hard code the + * immediate number for INT instruction. Otherwise, an build error + * happends and shows: + * "error: 'asm' operand 0 probably does not match constraints" and + * "error: impossible constraint in 'asm'" + */ +#if defined(CONFIG_COVERAGE) + if (vector == TEST_DYNAMIC_VECTOR) { + __asm__ volatile("int %0" :: "i"(TEST_DYNAMIC_VECTOR)); + } else { + printk("not interrupt"); + } +#else + __asm__ volatile("int %0" :: "i"(vector)); +#endif +} + +#elif defined(CONFIG_ARCH_POSIX) +#include "irq_ctrl.h" + +#define TEST_IRQ_DYN_LINE 5 + +static inline void trigger_irq(int irq) +{ + hw_irq_ctrl_raise_im_from_sw(irq); +} + +#elif defined(CONFIG_RISCV) +static inline void trigger_irq(int irq) +{ + uint32_t mip; + + __asm__ volatile ("csrrs %0, mip, %1\n" + : "=r" (mip) + : "r" (1 << irq)); +} + +#elif defined(CONFIG_XTENSA) +static inline void trigger_irq(int irq) +{ + z_xt_set_intset(BIT((unsigned int)irq)); +} + +#elif defined(CONFIG_SPARC) +extern void z_sparc_enter_irq(int); + +static inline void trigger_irq(int irq) +{ + z_sparc_enter_irq(irq); +} + #else /* for not supported architecture */ #define NO_TRIGGER_FROM_SW