tests: interrupt: refine the interrupt testcases

This PR include 2 changes to refine the testcases:
1. Now we using IPI to trigger interrupt in testing instead of INT
   instruction, this means we don't need to hardcode the vector
   number. That can avoid some problem.

Fixes: #40374

2. Refined the test cases. Tigger interrupt by INT instruction and
   IPI cannot be masked by irq_disabled(). Unless it's a external
   interrupt, such as a timer. Now remove those incorrect part of
   these testcases.

Signed-off-by: Enjia Mai <enjiax.mai@intel.com>
This commit is contained in:
Enjia Mai 2021-05-21 23:30:34 +08:00 committed by Anas Nashif
commit e61e63e33f
4 changed files with 54 additions and 119 deletions

View file

@ -20,25 +20,13 @@
#define TEST_DIRECT_IRQ_LINE_1 3 #define TEST_DIRECT_IRQ_LINE_1 3
#define TEST_DIRECT_IRQ_LINE_2 4 #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 #define TEST_DIRECT_IRQ_PRIO 0
#elif defined(CONFIG_ARCH_POSIX) #elif defined(CONFIG_ARCH_POSIX)
#define TEST_DIRECT_IRQ_LINE_1 5 #define TEST_DIRECT_IRQ_LINE_1 5
#define TEST_DIRECT_IRQ_LINE_2 6 #define TEST_DIRECT_IRQ_LINE_2 6
#define TRIGGER_DIRECT_IRQ_LINE_1 TEST_DIRECT_IRQ_LINE_1 #define TEST_DIRECT_IRQ_PRIO 5
#define TRIGGER_DIRECT_IRQ_LINE_2 TEST_DIRECT_IRQ_LINE_2
#define TEST_DIRECT_IRQ_PRIO 1
#endif #endif
@ -81,21 +69,12 @@ void test_direct_interrupt(void)
trig_vec1 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_DIRECT_IRQ_LINE_1); trig_vec1 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_DIRECT_IRQ_LINE_1);
trig_vec2 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_DIRECT_IRQ_LINE_2); trig_vec2 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_DIRECT_IRQ_LINE_2);
#elif defined(CONFIG_ARCH_POSIX) #elif defined(CONFIG_ARCH_POSIX)
trig_vec1 = TRIGGER_DIRECT_IRQ_LINE_1; trig_vec1 = TEST_DIRECT_IRQ_LINE_1;
trig_vec2 = TRIGGER_DIRECT_IRQ_LINE_2; trig_vec2 = TEST_DIRECT_IRQ_LINE_2;
#endif #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_1, trig_vec1);
TC_PRINT("irq(%d)=vector(%d)\n", TEST_DIRECT_IRQ_LINE_2, trig_vec2); 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_1);
irq_enable(TEST_DIRECT_IRQ_LINE_2); irq_enable(TEST_DIRECT_IRQ_LINE_2);
@ -103,33 +82,44 @@ void test_direct_interrupt(void)
direct_int_executed[1] == 0, direct_int_executed[1] == 0,
"Both ISR should not execute"); "Both ISR should not execute");
trigger_irq(TRIGGER_DIRECT_IRQ_LINE_1); trigger_irq(trig_vec1);
zassert_true(direct_int_executed[0] == 1 && zassert_true(direct_int_executed[0] == 1 &&
direct_int_executed[1] == 0, direct_int_executed[1] == 0,
"ISR1 should execute"); "ISR1 should execute");
trigger_irq(TRIGGER_DIRECT_IRQ_LINE_2); trigger_irq(trig_vec2);
zassert_true(direct_int_executed[0] == 1 && zassert_true(direct_int_executed[0] == 1 &&
direct_int_executed[1] == 1, direct_int_executed[1] == 1,
"Both ISR should execute"); "Both ISR should execute");
irq_disable(TEST_DIRECT_IRQ_LINE_1); unsigned int key = irq_lock();
irq_disable(TEST_DIRECT_IRQ_LINE_2);
trigger_irq(TRIGGER_DIRECT_IRQ_LINE_1); /* trigger under irq locked */
trigger_irq(TRIGGER_DIRECT_IRQ_LINE_2); trigger_irq(trig_vec1);
trigger_irq(trig_vec2);
/*
* irq_enable()/irq_disable() does not work here,
* see #33901.
*/
#if !defined(CONFIG_X86)
zassert_true(direct_int_executed[0] == 1 && zassert_true(direct_int_executed[0] == 1 &&
direct_int_executed[1] == 1, direct_int_executed[1] == 1,
"Both ISR should not execute again"); "Both ISR should not execute again");
#endif
irq_unlock(key);
/* interrupt serve after irq unlocked */
zassert_true(direct_int_executed[0] == 2 &&
direct_int_executed[1] == 2,
"Both ISR should execute again(%d)(%d)",
direct_int_executed[0], direct_int_executed[1]);
/* trigger after irq unlocked */
trigger_irq(trig_vec1);
trigger_irq(trig_vec2);
zassert_true(direct_int_executed[0] == 3 &&
direct_int_executed[1] == 3,
"Both ISR should execute again(%d)(%d)",
direct_int_executed[0], direct_int_executed[1]);
} }
#else #else
void test_direct_interrupt(void) void test_direct_interrupt(void)

View file

@ -18,7 +18,7 @@ static void dyn_isr(const void *arg)
{ {
ARG_UNUSED(arg); ARG_UNUSED(arg);
handler_test_result = (uintptr_t)arg; handler_test_result = (uintptr_t)arg;
handler_has_run = 1; handler_has_run++;
} }
#if defined(CONFIG_GEN_SW_ISR_TABLE) #if defined(CONFIG_GEN_SW_ISR_TABLE)
@ -70,19 +70,10 @@ void test_isr_dynamic(void)
*/ */
#if defined(CONFIG_X86) #if defined(CONFIG_X86)
#define IV_IRQS 32 /* start of vectors available for x86 IRQs */ #define IV_IRQS 32 /* start of vectors available for x86 IRQs */
/* Using APIC TSC deadline timer will conflict with our testcase */
#if defined(CONFIG_APIC_TSC_DEADLINE_TIMER)
#define TEST_IRQ_DYN_LINE 17
#else
#define TEST_IRQ_DYN_LINE 16 #define TEST_IRQ_DYN_LINE 16
#endif
#define TRIGGER_IRQ_DYN_LINE (TEST_IRQ_DYN_LINE + IV_IRQS)
#elif defined(CONFIG_ARCH_POSIX) #elif defined(CONFIG_ARCH_POSIX)
#define TEST_IRQ_DYN_LINE 5 #define TEST_IRQ_DYN_LINE 5
#define TRIGGER_IRQ_DYN_LINE 5
#endif #endif
void test_isr_dynamic(void) void test_isr_dynamic(void)
@ -98,8 +89,8 @@ void test_isr_dynamic(void)
extern void (*x86_irq_funcs[])(const void *); extern void (*x86_irq_funcs[])(const void *);
extern const void *x86_irq_args[]; extern const void *x86_irq_args[];
zassert_true(x86_irq_funcs[TEST_IRQ_DYN_LINE] == dyn_isr && zassert_true(x86_irq_funcs[vector_num - IV_IRQS] == dyn_isr &&
x86_irq_args[TEST_IRQ_DYN_LINE] == (void *)ISR_DYN_ARG, x86_irq_args[vector_num - IV_IRQS] == (void *)ISR_DYN_ARG,
"dynamic isr did not install successfully"); "dynamic isr did not install successfully");
#endif #endif
@ -107,29 +98,12 @@ extern const void *x86_irq_args[];
zassert_true(vector_num > 0, zassert_true(vector_num > 0,
"irq connect dynamic failed"); "irq connect dynamic failed");
/*
* The reason we need to hard code the trigger vector here
* is that the x86 only support immediate number for INT
* instruction. So trigger an interrupt of x86 under gcov code
* coverage report enabled, which means GCC optimization will
* be -O0. In this case, an build error happens and shows:
* "error: 'asm' operand 0 probably does not match constraints"
* and "error: impossible constraint in 'asm'"
*
* Although we hard code the trigger vecotr it here, we still
* do a check if the vector match getting from
* arch_irq_connect_dynamic().
*/
zassert_equal(vector_num, TRIGGER_IRQ_DYN_LINE,
"vector %d mismatch we specified to trigger %d",
vector_num, TRIGGER_IRQ_DYN_LINE);
zassert_equal(handler_has_run, 0, zassert_equal(handler_has_run, 0,
"handler has run before interrupt trigger"); "handler has run before interrupt trigger");
irq_enable(TEST_IRQ_DYN_LINE); irq_enable(TEST_IRQ_DYN_LINE);
trigger_irq(TRIGGER_IRQ_DYN_LINE); trigger_irq(vector_num);
zassert_equal(handler_has_run, 1, zassert_equal(handler_has_run, 1,
"interrupt triggered but handler has not run(%d)", "interrupt triggered but handler has not run(%d)",
@ -140,12 +114,13 @@ extern const void *x86_irq_args[];
"parameter(0x%lx) in handler is not correct", "parameter(0x%lx) in handler is not correct",
handler_test_result); handler_test_result);
irq_disable(TRIGGER_IRQ_DYN_LINE); trigger_irq(vector_num);
/**TESTPOINT: interrupt cannot be triggered when disable it */ /**TESTPOINT: interrupt triggered again */
zassert_equal(handler_has_run, 1, zassert_equal(handler_has_run, 2,
"interrupt handler should not be triggered again(%d)", "interrupt triggered but handler has not run(%d)",
handler_has_run); handler_has_run);
} }
#endif /* CONFIG_GEN_SW_ISR_TABLE */ #endif /* CONFIG_GEN_SW_ISR_TABLE */

View file

@ -86,17 +86,13 @@ void isr_handler(const void *param)
* Other arch will be add later. * Other arch will be add later.
*/ */
#if defined(CONFIG_X86) #if defined(CONFIG_X86)
#define IV_IRQS 32
#define TEST_IRQ_DYN_LINE 17 #define TEST_IRQ_DYN_LINE 17
#define TRIGGER_IRQ_DYN_LINE (TEST_IRQ_DYN_LINE + IV_IRQS)
#elif defined(CONFIG_ARCH_POSIX) #elif defined(CONFIG_ARCH_POSIX)
#define TEST_IRQ_DYN_LINE 5 #define TEST_IRQ_DYN_LINE 5
#define TRIGGER_IRQ_DYN_LINE 5
#else #else
#define TEST_IRQ_DYN_LINE 0 #define TEST_IRQ_DYN_LINE 0
#define TRIGGER_IRQ_DYN_LINE 0
#endif #endif
#endif #endif
@ -114,7 +110,7 @@ static void init_dyn_interrupt(void)
isr_handler, (void *)&irq_param, 0); isr_handler, (void *)&irq_param, 0);
} }
TC_PRINT("irq(%d)\n", vector_num); TC_PRINT("vector(%d)\n", vector_num);
zassert_true(vector_num > 0, "no vector can be used"); zassert_true(vector_num > 0, "no vector can be used");
irq_enable(TEST_IRQ_DYN_LINE); irq_enable(TEST_IRQ_DYN_LINE);
} }
@ -124,7 +120,7 @@ static void trigger_offload_interrupt(const bool real_irq, void *work)
irq_param.work = work; irq_param.work = work;
if (real_irq) { if (real_irq) {
trigger_irq(TRIGGER_IRQ_DYN_LINE); trigger_irq(vector_num);
} else { } else {
irq_offload((irq_offload_routine_t)&isr_handler, &irq_param); irq_offload((irq_offload_routine_t)&isr_handler, &irq_param);
} }

View file

@ -16,9 +16,6 @@
#define TEST_IRQ_LINE_1 27 #define TEST_IRQ_LINE_1 27
#define TEST_IRQ_LINE_2 28 #define TEST_IRQ_LINE_2 28
#define TRIGGER_IRQ_LINE_1 64
#define TRIGGER_IRQ_LINE_2 65
#define TEST_IRQ_PRIO 2 #define TEST_IRQ_PRIO 2
@ -61,58 +58,32 @@ void test_isr_regular(void)
IRQ_CONNECT(TEST_IRQ_LINE_1, TEST_IRQ_PRIO, isr_comm, (void *)TEST_IRQ_LINE_1, 0); IRQ_CONNECT(TEST_IRQ_LINE_1, TEST_IRQ_PRIO, isr_comm, (void *)TEST_IRQ_LINE_1, 0);
IRQ_CONNECT(TEST_IRQ_LINE_2, TEST_IRQ_PRIO, isr_comm, (void *)TEST_IRQ_LINE_2, 0); IRQ_CONNECT(TEST_IRQ_LINE_2, TEST_IRQ_PRIO, isr_comm, (void *)TEST_IRQ_LINE_2, 0);
#if defined(CONFIG_X86)
trig_vec1 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_IRQ_LINE_1); trig_vec1 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_IRQ_LINE_1);
trig_vec2 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_IRQ_LINE_2); trig_vec2 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_IRQ_LINE_2);
#elif defined(CONFIG_ARCH_POSIX)
trig_vec1 = TRIGGER_IRQ_LINE_1;
trig_vec2 = TRIGGER_IRQ_LINE_2;
#endif
/* verify the target triggering vector is correct */
zassert_equal(trig_vec1, TRIGGER_IRQ_LINE_1,
"vector %d mismatch we specified to trigger %d",
trig_vec1, TRIGGER_IRQ_LINE_1);
zassert_equal(trig_vec2, TRIGGER_IRQ_LINE_2,
"vector %d mismatch we specified to trigger %d",
trig_vec2, TRIGGER_IRQ_LINE_2);
TC_PRINT("irq(%d)=vector(%d)\n", TEST_IRQ_LINE_1, trig_vec1); TC_PRINT("irq(%d)=vector(%d)\n", TEST_IRQ_LINE_1, trig_vec1);
TC_PRINT("irq(%d)=vector(%d)\n", TEST_IRQ_LINE_2, trig_vec2); TC_PRINT("irq(%d)=vector(%d)\n", TEST_IRQ_LINE_2, trig_vec2);
irq_enable(TEST_IRQ_LINE_1);
irq_enable(TEST_IRQ_LINE_2);
trigger_irq(TRIGGER_IRQ_LINE_1); trigger_irq(trig_vec1);
zassert_true(reg_int_executed[0] == 1 && zassert_true(reg_int_executed[0] == 1 &&
reg_int_executed[1] == 0, reg_int_executed[1] == 0,
"ISR1 should execute"); "ISR1 should execute");
trigger_irq(TRIGGER_IRQ_LINE_2); trigger_irq(trig_vec2);
zassert_true(reg_int_executed[0] == 1 && zassert_true(reg_int_executed[0] == 1 &&
reg_int_executed[1] == 1, reg_int_executed[1] == 1,
"Both ISR should execute"); "Both ISR should execute");
/* Skip checking here, see #33901 */ unsigned int key = irq_lock();
#if !defined(CONFIG_X86)
irq_disable(TEST_IRQ_LINE_1);
irq_disable(TEST_IRQ_LINE_2);
/* trigger under irq disabled */
trigger_irq(TRIGGER_IRQ_LINE_1);
trigger_irq(TRIGGER_IRQ_LINE_2);
zassert_true(reg_int_executed[0] == 1 &&
reg_int_executed[1] == 1,
"Both ISR should not execute again");
int key = irq_lock();
/* trigger under irq locked */ /* trigger under irq locked */
trigger_irq(TRIGGER_IRQ_LINE_1); trigger_irq(trig_vec1);
trigger_irq(TRIGGER_IRQ_LINE_2); trigger_irq(trig_vec2);
zassert_true(reg_int_executed[0] == 1 && zassert_true(reg_int_executed[0] == 1 &&
reg_int_executed[1] == 1, reg_int_executed[1] == 1,
@ -121,17 +92,20 @@ void test_isr_regular(void)
irq_unlock(key); irq_unlock(key);
/* trigger under irq unlocked */ /* interrupt serve after irq unlocked */
trigger_irq(TRIGGER_IRQ_LINE_1);
trigger_irq(TRIGGER_IRQ_LINE_2);
zassert_true(reg_int_executed[0] == 2 && zassert_true(reg_int_executed[0] == 2 &&
reg_int_executed[1] == 2, reg_int_executed[1] == 2,
"Both ISR should execute again(%d)(%d)", "Both ISR should execute again(%d)(%d)",
reg_int_executed[0], reg_int_executed[1]); reg_int_executed[0], reg_int_executed[1]);
#else
TC_PRINT("not testing irq enable/disable\n"); /* trigger after irq unlocked */
#endif trigger_irq(trig_vec1);
trigger_irq(trig_vec2);
zassert_true(reg_int_executed[0] == 3 &&
reg_int_executed[1] == 3,
"Both ISR should execute again(%d)(%d)",
reg_int_executed[0], reg_int_executed[1]);
} }
#else #else
void test_isr_regular(void) void test_isr_regular(void)