1 /*
2  * Copyright (c) 2018 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 #define ISR_DYN_ARG	0xab249cfd
11 
12 static unsigned int handler_has_run;
13 static uintptr_t handler_test_result;
14 
dyn_isr(const void * arg)15 static void dyn_isr(const void *arg)
16 {
17 	ARG_UNUSED(arg);
18 	handler_test_result = (uintptr_t)arg;
19 	handler_has_run++;
20 }
21 
22 #if defined(CONFIG_GEN_SW_ISR_TABLE)
23 extern
24 #ifndef CONFIG_DYNAMIC_INTERRUPTS
25 const
26 #endif
27 struct _isr_table_entry _sw_isr_table[];
28 
29 #if defined(CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET)
30 #define IRQ_OFFSET CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET
31 #else
32 #define IRQ_OFFSET 0
33 #endif
34 
35 /**
36  * @brief Test dynamic ISR installation
37  *
38  * @ingroup kernel_interrupt_tests
39  *
40  * @details This routine locates an unused entry in the software ISR table,
41  * installs a dynamic ISR to the unused entry by calling the dynamic
42  * configured function, and verifies that the ISR is successfully installed
43  * by checking the software ISR table entry.
44  *
45  * @see arch_irq_connect_dynamic()
46  */
ZTEST(interrupt_feature,test_isr_dynamic)47 ZTEST(interrupt_feature, test_isr_dynamic)
48 {
49 	int i;
50 	const void *argval;
51 
52 	for (i = 0; i < (CONFIG_NUM_IRQS - CONFIG_GEN_IRQ_START_VECTOR); i++) {
53 		if (_sw_isr_table[i].isr == z_irq_spurious) {
54 			break;
55 		}
56 	}
57 
58 	zassert_true(_sw_isr_table[i].isr == z_irq_spurious,
59 		     "could not find slot for dynamic isr");
60 
61 	printk("installing dynamic ISR for IRQ %d\n",
62 	       CONFIG_GEN_IRQ_START_VECTOR + i);
63 
64 	argval = (const void *)&i;
65 	arch_irq_connect_dynamic(i + CONFIG_GEN_IRQ_START_VECTOR, 0, dyn_isr,
66 				 argval, 0);
67 
68 	zassert_true(_sw_isr_table[i + IRQ_OFFSET].isr == dyn_isr &&
69 		     _sw_isr_table[i + IRQ_OFFSET].arg == argval,
70 		     "dynamic isr did not install successfully");
71 }
72 #else
73 /*
74  * For testing arch such as x86, x86_64 and posix which support dynamic
75  * interrupt but without SW ISR table, we test it by applying for a
76  * dynamic interrupt and then trigger it to check if happened correctly.
77  */
78 #if defined(CONFIG_X86)
79 #define IV_IRQS 32	/* start of vectors available for x86 IRQs */
80 #define TEST_IRQ_DYN_LINE 25
81 
82 #elif defined(CONFIG_ARCH_POSIX)
83 #define TEST_IRQ_DYN_LINE 5
84 #endif
85 
ZTEST(interrupt_feature,test_isr_dynamic)86 ZTEST(interrupt_feature, test_isr_dynamic)
87 {
88 	int vector_num;
89 
90 	/**TESTPOINT: configuration of interrupts dynamically at runtime */
91 	vector_num = arch_irq_connect_dynamic(TEST_IRQ_DYN_LINE, 1, dyn_isr,
92 				 (void *)ISR_DYN_ARG, 0);
93 
94 #if defined(CONFIG_X86_64)
95 /* The isr table for x86_64 is visiable, so check it up here */
96 extern void (*x86_irq_funcs[])(const void *);
97 extern const void *x86_irq_args[];
98 
99 	zassert_true(x86_irq_funcs[vector_num - IV_IRQS] == dyn_isr &&
100 		     x86_irq_args[vector_num - IV_IRQS] == (void *)ISR_DYN_ARG,
101 		     "dynamic isr did not install successfully");
102 #endif
103 
104 	TC_PRINT("vector(%d)\n", vector_num);
105 	zassert_true(vector_num > 0,
106 			"irq connect dynamic failed");
107 
108 	zassert_equal(handler_has_run, 0,
109 			"handler has run before interrupt trigger");
110 
111 	irq_enable(TEST_IRQ_DYN_LINE);
112 
113 	trigger_irq(vector_num);
114 
115 	zassert_equal(handler_has_run, 1,
116 			"interrupt triggered but handler has not run(%d)",
117 			handler_has_run);
118 
119 	/**TESTPOINT: pass word-sized parameter to interrupt */
120 	zassert_equal(handler_test_result, ISR_DYN_ARG,
121 			"parameter(0x%" PRIxPTR ") in handler is not correct",
122 			handler_test_result);
123 
124 	trigger_irq(vector_num);
125 
126 	/**TESTPOINT: interrupt triggered again */
127 	zassert_equal(handler_has_run, 2,
128 			"interrupt triggered but handler has not run(%d)",
129 			handler_has_run);
130 
131 	irq_disable(TEST_IRQ_DYN_LINE);
132 }
133 #endif /* CONFIG_GEN_SW_ISR_TABLE */
134