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