1 /*
2  * Copyright (c) 2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/interrupt_util.h>
9 
10 /*
11  * Other arch has already been tested in testcase of gen_isr_table,
12  * so we only test x86 and arch posix here.
13  * And x86_64 is also not support this kind of interrupt, we skip it.
14  */
15 #if defined(CONFIG_X86)
16 
17 #define TEST_DIRECT_IRQ_LINE_1	3
18 #define TEST_DIRECT_IRQ_LINE_2	4
19 
20 #define TEST_DIRECT_IRQ_PRIO	0
21 
22 #elif defined(CONFIG_ARCH_POSIX)
23 #define TEST_DIRECT_IRQ_LINE_1	5
24 #define TEST_DIRECT_IRQ_LINE_2	6
25 
26 #define TEST_DIRECT_IRQ_PRIO	5
27 
28 #endif
29 
30 volatile uint32_t direct_int_executed[2];
31 
ISR_DIRECT_DECLARE(direct_isr1)32 ISR_DIRECT_DECLARE(direct_isr1)
33 {
34 	direct_int_executed[0]++;
35 
36 	return 0;
37 }
38 
ISR_DIRECT_DECLARE(direct_isr2)39 ISR_DIRECT_DECLARE(direct_isr2)
40 {
41 	direct_int_executed[1]++;
42 
43 	return 1;
44 }
45 
46 /**
47  * @brief Test direct interrupt function
48  *
49  * @details validate direct interrupt works as expected.
50  * - Register two direct interrupt at build time.
51  * - Trigger interrupt and check if isr handler has executed or not.
52  * - Also check irq_enable and irq_disable works.
53  *
54  * @ingroup kernel_interrupt_tests
55  *
56  * @see IRQ_DIRECT_CONNECT(), ISR_DIRECT_DECLARE()
57  */
ZTEST(x86_direct_interrupt,test_direct_interrupt)58 ZTEST(x86_direct_interrupt, test_direct_interrupt)
59 {
60 	int trig_vec1, trig_vec2;
61 
62 	IRQ_DIRECT_CONNECT(TEST_DIRECT_IRQ_LINE_1, TEST_DIRECT_IRQ_PRIO, direct_isr1, 0);
63 	IRQ_DIRECT_CONNECT(TEST_DIRECT_IRQ_LINE_2, TEST_DIRECT_IRQ_PRIO, direct_isr2, 0);
64 
65 #if defined(CONFIG_X86)
66 	trig_vec1 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_DIRECT_IRQ_LINE_1);
67 	trig_vec2 = Z_IRQ_TO_INTERRUPT_VECTOR(TEST_DIRECT_IRQ_LINE_2);
68 #elif defined(CONFIG_ARCH_POSIX)
69 	trig_vec1 = TEST_DIRECT_IRQ_LINE_1;
70 	trig_vec2 = TEST_DIRECT_IRQ_LINE_2;
71 #endif
72 	TC_PRINT("irq(%d)=vector(%d)\n", TEST_DIRECT_IRQ_LINE_1, trig_vec1);
73 	TC_PRINT("irq(%d)=vector(%d)\n", TEST_DIRECT_IRQ_LINE_2, trig_vec2);
74 
75 	irq_enable(TEST_DIRECT_IRQ_LINE_1);
76 	irq_enable(TEST_DIRECT_IRQ_LINE_2);
77 
78 	zassert_true(direct_int_executed[0] == 0 &&
79 			direct_int_executed[1] == 0,
80 			"Both ISR should not execute");
81 
82 	trigger_irq(trig_vec1);
83 
84 	zassert_true(direct_int_executed[0] == 1 &&
85 			direct_int_executed[1] == 0,
86 			"ISR1 should execute");
87 
88 	trigger_irq(trig_vec2);
89 
90 	zassert_true(direct_int_executed[0] == 1 &&
91 			direct_int_executed[1] == 1,
92 			"Both ISR should execute");
93 
94 	unsigned int key = irq_lock();
95 
96 	/* trigger under irq locked */
97 	trigger_irq(trig_vec1);
98 	trigger_irq(trig_vec2);
99 
100 	zassert_true(direct_int_executed[0] == 1 &&
101 			direct_int_executed[1] == 1,
102 			"Both ISR should not execute again");
103 
104 	irq_unlock(key);
105 
106 	/* interrupt serve after irq unlocked */
107 	zassert_true(direct_int_executed[0] == 2 &&
108 			direct_int_executed[1] == 2,
109 			"Both ISR should execute again(%d)(%d)",
110 			direct_int_executed[0], direct_int_executed[1]);
111 
112 	/* trigger after irq unlocked */
113 	trigger_irq(trig_vec1);
114 	trigger_irq(trig_vec2);
115 
116 	zassert_true(direct_int_executed[0] == 3 &&
117 			direct_int_executed[1] == 3,
118 			"Both ISR should execute again(%d)(%d)",
119 			direct_int_executed[0], direct_int_executed[1]);
120 }
121 
122 ZTEST_SUITE(x86_direct_interrupt, NULL, NULL, NULL, NULL, NULL);
123