1 /*
2  * Copyright (c) 2017 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/toolchain.h>
8 #include <zephyr/linker/sections.h>
9 #include <zephyr/sw_isr_table.h>
10 #include <zephyr/arch/cpu.h>
11 
12 /* There is an additional member at the end populated by the linker script
13  * which indicates the number of interrupts specified
14  */
15 struct int_list_header {
16 	uint32_t table_size;
17 	uint32_t offset;
18 #if defined(CONFIG_ISR_TABLES_LOCAL_DECLARATION)
19 	uint32_t swi_table_entry_size;
20 	uint32_t shared_isr_table_entry_size;
21 	uint32_t shared_isr_client_num_offset;
22 #endif /* defined(CONFIG_ISR_TABLES_LOCAL_DECLARATION) */
23 };
24 
25 /* These values are not included in the resulting binary, but instead form the
26  * header of the initList section, which is used by gen_isr_tables.py to create
27  * the vector and sw isr tables,
28  */
29 Z_GENERIC_SECTION(.irq_info) __used struct int_list_header _iheader = {
30 	.table_size = IRQ_TABLE_SIZE,
31 	.offset = CONFIG_GEN_IRQ_START_VECTOR,
32 #if defined(CONFIG_ISR_TABLES_LOCAL_DECLARATION)
33 	.swi_table_entry_size = sizeof(struct _isr_table_entry),
34 #if defined(CONFIG_SHARED_INTERRUPTS)
35 	.shared_isr_table_entry_size = sizeof(struct z_shared_isr_table_entry),
36 	.shared_isr_client_num_offset = offsetof(struct z_shared_isr_table_entry, client_num),
37 #endif /* defined(CONFIG_SHARED_INTERRUPTS) */
38 #endif /* defined(CONFIG_ISR_TABLES_LOCAL_DECLARATION) */
39 };
40 
41 /* These are placeholder tables. They will be replaced by the real tables
42  * generated by gen_isr_tables.py.
43  *
44  * z_irq_spurious is used as a placeholder value to ensure that it is not
45  * optimized out in the first linker pass. The first linker pass must contain
46  * the same symbols as the second linker pass for the code generation to work.
47  */
48 
49 /* Some arches don't use a vector table, they have a common exception entry
50  * point for all interrupts. Don't generate a table in this case.
51  */
52 #ifdef CONFIG_GEN_IRQ_VECTOR_TABLE
53 /* When both the IRQ vector table and the software ISR table are used, populate
54  * the IRQ vector table with the common software ISR by default, such that all
55  * indirect interrupt vectors are handled using the software ISR table;
56  * otherwise, populate the IRQ vector table with z_irq_spurious so that all
57  * un-connected IRQ vectors end up in the spurious IRQ handler.
58  */
59 #ifdef CONFIG_GEN_SW_ISR_TABLE
60 #define IRQ_VECTOR_TABLE_DEFAULT_ISR	_isr_wrapper
61 #else
62 #define IRQ_VECTOR_TABLE_DEFAULT_ISR	z_irq_spurious
63 #endif /* CONFIG_GEN_SW_ISR_TABLE */
64 
65 #ifdef CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_CODE
66 
67 /* Assembly code for a jump instruction. Must be set by the architecture. */
68 #ifndef ARCH_IRQ_VECTOR_JUMP_CODE
69 #error "ARCH_IRQ_VECTOR_JUMP_CODE not defined"
70 #endif
71 
72 #define BUILD_VECTOR(n, _) __asm(ARCH_IRQ_VECTOR_JUMP_CODE(IRQ_VECTOR_TABLE_DEFAULT_ISR))
73 
74 /* The IRQ vector table contains the jump opcodes towards the vector routine */
_irq_vector_table(void)75 void __irq_vector_table __attribute__((naked)) _irq_vector_table(void) {
76 	 LISTIFY(CONFIG_NUM_IRQS, BUILD_VECTOR, (;));
77 };
78 #else
79 
80 /* The IRQ vector table is an array of vector addresses */
81 uintptr_t __irq_vector_table _irq_vector_table[IRQ_TABLE_SIZE] = {
82 	[0 ...(IRQ_TABLE_SIZE - 1)] = (uintptr_t)&IRQ_VECTOR_TABLE_DEFAULT_ISR,
83 };
84 #endif /* CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_CODE */
85 #endif /* CONFIG_GEN_IRQ_VECTOR_TABLE */
86 
87 /* If there are no interrupts at all, or all interrupts are of the 'direct'
88  * type and bypass the _sw_isr_table, then do not generate one.
89  */
90 #ifdef CONFIG_GEN_SW_ISR_TABLE
91 struct _isr_table_entry __sw_isr_table _sw_isr_table[IRQ_TABLE_SIZE] = {
92 	[0 ...(IRQ_TABLE_SIZE - 1)] = {(const void *)0x42,
93 				       &z_irq_spurious},
94 };
95 #endif
96 
97 #ifdef CONFIG_SHARED_INTERRUPTS
98 struct z_shared_isr_table_entry __shared_sw_isr_table z_shared_sw_isr_table[IRQ_TABLE_SIZE] = {
99 };
100 #endif
101