From c9c8cec3b6792165208493c5519d07b599458ed1 Mon Sep 17 00:00:00 2001 From: Enjia Mai Date: Mon, 29 Mar 2021 22:27:13 +0800 Subject: [PATCH] tests: interrupt: add test cases of direct interrupt for arch x86 and posix Add test cases of direct interrupt for arch x86 and posix. We register two direct interrupt at build time, then triggering interrupt and check if ISR handler has executed or not. We also check irq_enable and irq_disable works. Why we add an extra compiler option "-mgeneral-regs-only" to make it works in arch x86. because there might be some existing x87 instructions executing inside interrupt context. Signed-off-by: Enjia Mai --- tests/kernel/interrupt/src/direct_isr.c | 139 ++++++++++++++++++++++++ tests/kernel/interrupt/src/main.c | 4 +- tests/kernel/interrupt/testcase.yaml | 14 ++- 3 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 tests/kernel/interrupt/src/direct_isr.c diff --git a/tests/kernel/interrupt/src/direct_isr.c b/tests/kernel/interrupt/src/direct_isr.c new file mode 100644 index 00000000000..d2e4133ceac --- /dev/null +++ b/tests/kernel/interrupt/src/direct_isr.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2021 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "interrupt_util.h" + +/* + * Other arch has already been tested in testcase of gen_isr_table, + * so we only test x86 and arch posix here. + * And x86_64 is also not support this kind of interrupt, we skip it. + */ +#if (defined(CONFIG_X86) && !defined(CONFIG_X86_64)) ||\ + defined(CONFIG_ARCH_POSIX) + +#if defined(CONFIG_X86) + +#define TEST_DIRECT_IRQ_LINE_1 3 +#define TEST_DIRECT_IRQ_LINE_2 4 + +/* the vector got would be different when enable code coverage */ +#if defined(CONFIG_COVERAGE) +#define TRIGGER_DIRECT_IRQ_LINE_1 34 +#define TRIGGER_DIRECT_IRQ_LINE_2 35 +#else +#define TRIGGER_DIRECT_IRQ_LINE_1 35 +#define TRIGGER_DIRECT_IRQ_LINE_2 34 +#endif + +#define TEST_DIRECT_IRQ_PRIO 0 + +#elif defined(CONFIG_ARCH_POSIX) +#define TEST_DIRECT_IRQ_LINE_1 5 +#define TEST_DIRECT_IRQ_LINE_2 6 + +#define TRIGGER_DIRECT_IRQ_LINE_1 TEST_DIRECT_IRQ_LINE_1 +#define TRIGGER_DIRECT_IRQ_LINE_2 TEST_DIRECT_IRQ_LINE_2 + +#define TEST_DIRECT_IRQ_PRIO 1 + +#endif + +volatile uint32_t direct_int_executed[2]; + +ISR_DIRECT_DECLARE(direct_isr1) +{ + direct_int_executed[0]++; + + return 0; +} + +ISR_DIRECT_DECLARE(direct_isr2) +{ + direct_int_executed[1]++; + + return 1; +} + +/** + * @brief Test direct interrupt function + * + * @details validate direct interrupt works as expected. + * - Register two direct interrupt at build time. + * - Trigger interrupt and check if isr handler has executed or not. + * - Also check irq_enable and irq_disable works. + * + * @ingroup kernel_interrupt_tests + * + * @see IRQ_DIRECT_CONNECT(), ISR_DIRECT_DECLARE() + */ +void test_direct_interrupt(void) +{ + int trig_vec1, trig_vec2; + + IRQ_DIRECT_CONNECT(TEST_DIRECT_IRQ_LINE_1, TEST_DIRECT_IRQ_PRIO, direct_isr1, 0); + IRQ_DIRECT_CONNECT(TEST_DIRECT_IRQ_LINE_2, TEST_DIRECT_IRQ_PRIO, direct_isr2, 0); + +#if defined(CONFIG_X86) + trig_vec1 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_DIRECT_IRQ_LINE_1); + trig_vec2 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_DIRECT_IRQ_LINE_2); +#elif defined(CONFIG_ARCH_POSIX) + trig_vec1 = TRIGGER_DIRECT_IRQ_LINE_1; + trig_vec2 = TRIGGER_DIRECT_IRQ_LINE_2; +#endif + TC_PRINT("irq(%d)=vector(%d)\n", TEST_DIRECT_IRQ_LINE_1, trig_vec1); + TC_PRINT("irq(%d)=vector(%d)\n", TEST_DIRECT_IRQ_LINE_2, trig_vec2); + + /* verify the target triggering vector is correct */ + zassert_equal(trig_vec1, TRIGGER_DIRECT_IRQ_LINE_1, + "vector %d mismatch we specified to trigger %d", + trig_vec1, TRIGGER_DIRECT_IRQ_LINE_1); + + zassert_equal(trig_vec2, TRIGGER_DIRECT_IRQ_LINE_2, + "vector %d mismatch we specified to trigger %d", + trig_vec2, TRIGGER_DIRECT_IRQ_LINE_2); + + irq_enable(TEST_DIRECT_IRQ_LINE_1); + irq_enable(TEST_DIRECT_IRQ_LINE_2); + + zassert_true(direct_int_executed[0] == 0 && + direct_int_executed[1] == 0, + "Both ISR should not execute"); + + trigger_irq(TRIGGER_DIRECT_IRQ_LINE_1); + + zassert_true(direct_int_executed[0] == 1 && + direct_int_executed[1] == 0, + "ISR1 should execute"); + + trigger_irq(TRIGGER_DIRECT_IRQ_LINE_2); + + zassert_true(direct_int_executed[0] == 1 && + direct_int_executed[1] == 1, + "Both ISR should execute"); + + irq_disable(TEST_DIRECT_IRQ_LINE_1); + irq_disable(TEST_DIRECT_IRQ_LINE_2); + + trigger_irq(TRIGGER_DIRECT_IRQ_LINE_1); + trigger_irq(TRIGGER_DIRECT_IRQ_LINE_2); + + /* + * irq_enable()/irq_disable() does not work here, + * see #33901. + */ +#if !defined(CONFIG_X86) + zassert_true(direct_int_executed[0] == 1 && + direct_int_executed[1] == 1, + "Both ISR should not execute again"); +#endif +} +#else +void test_direct_interrupt(void) +{ + ztest_test_skip(); +} +#endif /* end defined(CONFIG_X86) || defined(CONFIG_ARCH_POSIX) */ diff --git a/tests/kernel/interrupt/src/main.c b/tests/kernel/interrupt/src/main.c index 82f20ba745b..37e6f25b014 100644 --- a/tests/kernel/interrupt/src/main.c +++ b/tests/kernel/interrupt/src/main.c @@ -13,6 +13,7 @@ extern void test_isr_regular(void); extern void test_isr_offload_job_multiple(void); extern void test_isr_offload_job_identi(void); extern void test_isr_offload_job(void); +extern void test_direct_interrupt(void); void test_main(void) { @@ -23,7 +24,8 @@ void test_main(void) ztest_unit_test(test_isr_regular), ztest_unit_test(test_isr_offload_job_multiple), ztest_unit_test(test_isr_offload_job_identi), - ztest_unit_test(test_isr_offload_job) + ztest_unit_test(test_isr_offload_job), + ztest_unit_test(test_direct_interrupt) ); ztest_run_test_suite(interrupt_feature); } diff --git a/tests/kernel/interrupt/testcase.yaml b/tests/kernel/interrupt/testcase.yaml index cb59a77637e..1dcf177af43 100644 --- a/tests/kernel/interrupt/testcase.yaml +++ b/tests/kernel/interrupt/testcase.yaml @@ -1,6 +1,18 @@ tests: arch.interrupt: # nios2 excluded, see #22956 - arch_exclude: nios2 + arch_exclude: nios2 x86 tags: kernel interrupt filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE + + arch.interrupt.x86_64: + arch_allow: x86 + tags: kernel interrupt + filter: CONFIG_X86_64 + + arch.interrupt.x86: + arch_allow: x86 + tags: kernel interrupt + filter: not CONFIG_X86_64 + extra_configs: + - CONFIG_COMPILER_OPT="-mgeneral-regs-only"