1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include <irq/irq.h>
13 #include <common/types.h>
14 #include <common/kprint.h>
15 #include <common/util.h>
16 #include <sched/sched.h>
17 #include <sched/fpu.h>
18 #include <arch/machine/smp.h>
19 #include <arch/machine/esr.h>
20 #include <arch/trustzone/smc.h>
21 #include "irq_entry.h"
22
23 u8 irq_handle_type[MAX_IRQ_NUM];
24
arch_enable_irqno(int irq)25 void arch_enable_irqno(int irq)
26 {
27 plat_enable_irqno(irq);
28 }
29
arch_disable_irqno(int irq)30 void arch_disable_irqno(int irq)
31 {
32 plat_disable_irqno(irq);
33 }
34
arch_interrupt_init_per_cpu(void)35 void arch_interrupt_init_per_cpu(void)
36 {
37 disable_irq();
38
39 /* platform dependent init */
40 set_exception_vector();
41 plat_interrupt_init();
42 }
43
arch_interrupt_init(void)44 void arch_interrupt_init(void)
45 {
46 arch_interrupt_init_per_cpu();
47 memset(irq_handle_type, HANDLE_KERNEL, MAX_IRQ_NUM);
48 }
49
handle_entry_c(int type,u64 esr,u64 address)50 u64 handle_entry_c(int type, u64 esr, u64 address)
51 {
52 /* ec: exception class */
53 u32 esr_ec = GET_ESR_EL1_EC(esr);
54
55 kdebug("Exception type: %d, ESR: 0x%lx, Fault address: 0x%lx, "
56 "EC 0b%b\n",
57 type,
58 esr,
59 address,
60 esr_ec);
61
62 /* Currently, ChCore only handles a part of IRQs */
63 if (type < SYNC_EL0_64) {
64 if (esr_ec != ESR_EL1_EC_DABT_CEL) {
65 kinfo("%s: irq type is %d\n", __func__, type);
66 BUG_ON(1);
67 }
68 }
69
70 u64 fix_addr = 0;
71 /* Dispatch exception according to EC */
72 switch (esr_ec) {
73 case ESR_EL1_EC_UNKNOWN:
74 kdebug("Unknown\n");
75 break;
76 case ESR_EL1_EC_WFI_WFE:
77 kdebug("Trapped WFI or WFE instruction execution\n");
78 return address;
79 case ESR_EL1_EC_ENFP:
80 #if FPU_SAVING_MODE == LAZY_FPU_MODE
81 /*
82 * Disable FPU in EL1: IRQ type is SYNC_EL1h (4).
83 * Disable FPU in EL0: IRQ type is SYNC_EL0_64 (8).
84 */
85 change_fpu_owner();
86 return address;
87 #else
88 kdebug(
89 "Access to SVE, Advanced SIMD, or floating-point functionality\n");
90 break;
91 #endif
92 case ESR_EL1_EC_ILLEGAL_EXEC:
93 kdebug("Illegal Execution state\n");
94 break;
95 case ESR_EL1_EC_SVC_32:
96 kdebug("SVC instruction execution in AArch32 state\n");
97 break;
98 case ESR_EL1_EC_SVC_64:
99 kdebug("SVC instruction execution in AArch64 state\n");
100 break;
101 case ESR_EL1_EC_MRS_MSR_64:
102 kdebug("Using MSR or MRS from a lower Exception level\n");
103 break;
104 case ESR_EL1_EC_IABT_LEL:
105 kdebug("Instruction Abort from a lower Exception level\n");
106 /* Page fault handler here:
107 * dynamic loading can trigger faults here.
108 */
109 do_page_fault(esr, address, type, &fix_addr);
110 return address;
111 case ESR_EL1_EC_IABT_CEL:
112 kinfo("Instruction Abort from current Exception level\n");
113 break;
114 case ESR_EL1_EC_PC_ALIGN:
115 kdebug("PC alignment fault exception\n");
116 break;
117 case ESR_EL1_EC_DABT_LEL:
118 kdebug("Data Abort from a lower Exception level\n");
119 /* Handle faults caused by data access.
120 * We only consider page faults for now.
121 */
122 do_page_fault(esr, address, type, &fix_addr);
123 return address;
124 case ESR_EL1_EC_DABT_CEL:
125 kdebug("Data Abort from a current Exception level\n");
126 do_page_fault(esr, address, type, &fix_addr);
127
128 if (fix_addr)
129 return fix_addr;
130 else
131 return address;
132 case ESR_EL1_EC_SP_ALIGN:
133 kdebug("SP alignment fault exception\n");
134 break;
135 case ESR_EL1_EC_FP_32:
136 kdebug("Trapped floating-point exception taken from AArch32 state\n");
137 break;
138 case ESR_EL1_EC_FP_64:
139 kdebug("Trapped floating-point exception taken from AArch64 state\n");
140 break;
141 case ESR_EL1_EC_SError:
142 kdebug("SERROR\n");
143 break;
144 default:
145 kdebug("Unsupported Exception ESR %lx\n", esr);
146 break;
147 }
148
149 kinfo("Exception type: %d, ESR: 0x%lx, Fault address: 0x%lx, "
150 "EC 0b%b\n",
151 type,
152 esr,
153 address,
154 esr_ec);
155
156 BUG_ON(1);
157 }
158
159 /* Interrupt handler for interrupts happening when in EL0. */
handle_irq(void)160 void handle_irq(void)
161 {
162 plat_handle_irq();
163 sched();
164 eret_to_thread(switch_context());
165 }
166
167 /* Interrupt handler for interrupts happening when in EL1 (idle thread). */
handle_irq_el1(u64 elr_el1)168 void handle_irq_el1(u64 elr_el1)
169 {
170 /* Just reuse the same interrupt handler for EL0. */
171 handle_irq();
172 }
173
unexpected_handler(void)174 void unexpected_handler(void)
175 {
176 kinfo("[fatal error] %s is invoked\n", __func__);
177 BUG_ON(1);
178 }
179
handle_fiq(void)180 void handle_fiq(void)
181 {
182 save_and_release_fpu_owner();
183 smc_call(SMC_STD_RESPONSE, SMC_EXIT_PREEMPTED);
184 }
185