master
c 382 lines 12.2 KB
Raw
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /*
4 * QEMU ARM CPU - interrupt_request handling
5 *
6 * Copyright (c) 2003-2025 QEMU contributors
7 */
8
9 #include "qemu/osdep.h"
10 #include "cpu.h"
11 #include "internals.h"
12
13 #ifdef CONFIG_TCG
14 #include "accel/tcg/cpu-ops.h"
15
16 static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
17 unsigned int target_el,
18 unsigned int cur_el, bool secure,
19 uint64_t hcr_el2)
20 {
21 CPUARMState *env = cpu_env(cs);
22 bool pstate_unmasked;
23 bool unmasked = false;
24 bool allIntMask = false;
25
26 /*
27 * Don't take exceptions if they target a lower EL.
28 * This check should catch any exceptions that would not be taken
29 * but left pending.
30 */
31 if (cur_el > target_el) {
32 return false;
33 }
34
35 if (cpu_isar_feature(aa64_nmi, env_archcpu(env)) &&
36 env->cp15.sctlr_el[target_el] & SCTLR_NMI && cur_el == target_el) {
37 allIntMask = env->pstate & PSTATE_ALLINT ||
38 ((env->cp15.sctlr_el[target_el] & SCTLR_SPINTMASK) &&
39 (env->pstate & PSTATE_SP));
40 }
41
42 switch (excp_idx) {
43 case EXCP_NMI:
44 pstate_unmasked = !allIntMask;
45 break;
46
47 case EXCP_VINMI:
48 if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
49 /* VINMIs are only taken when hypervized. */
50 return false;
51 }
52 return !allIntMask;
53 case EXCP_VFNMI:
54 if (!(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
55 /* VFNMIs are only taken when hypervized. */
56 return false;
57 }
58 return !allIntMask;
59 case EXCP_FIQ:
60 pstate_unmasked = (!(env->daif & PSTATE_F)) && (!allIntMask);
61 break;
62
63 case EXCP_IRQ:
64 pstate_unmasked = (!(env->daif & PSTATE_I)) && (!allIntMask);
65 break;
66
67 case EXCP_VFIQ:
68 if (!(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
69 /* VFIQs are only taken when hypervized. */
70 return false;
71 }
72 return !(env->daif & PSTATE_F) && (!allIntMask);
73 case EXCP_VIRQ:
74 if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
75 /* VIRQs are only taken when hypervized. */
76 return false;
77 }
78 return !(env->daif & PSTATE_I) && (!allIntMask);
79 case EXCP_VSERR:
80 if (!(hcr_el2 & HCR_AMO) || (hcr_el2 & HCR_TGE)) {
81 /* VIRQs are only taken when hypervized. */
82 return false;
83 }
84 return !(env->daif & PSTATE_A);
85 default:
86 g_assert_not_reached();
87 }
88
89 /*
90 * Use the target EL, current execution state and SCR/HCR settings to
91 * determine whether the corresponding CPSR bit is used to mask the
92 * interrupt.
93 */
94 if ((target_el > cur_el) && (target_el != 1)) {
95 /* Exceptions targeting a higher EL may not be maskable */
96 if (arm_feature(env, ARM_FEATURE_AARCH64)) {
97 switch (target_el) {
98 case 2:
99 /*
100 * According to ARM DDI 0487H.a, an interrupt can be masked
101 * when HCR_E2H and HCR_TGE are both set regardless of the
102 * current Security state. Note that we need to revisit this
103 * part again once we need to support NMI.
104 */
105 if ((hcr_el2 & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
106 unmasked = true;
107 }
108 break;
109 case 3:
110 /* Interrupt cannot be masked when the target EL is 3 */
111 unmasked = true;
112 break;
113 default:
114 g_assert_not_reached();
115 }
116 } else {
117 /*
118 * The old 32-bit-only environment has a more complicated
119 * masking setup. HCR and SCR bits not only affect interrupt
120 * routing but also change the behaviour of masking.
121 */
122 bool hcr, scr;
123
124 switch (excp_idx) {
125 case EXCP_FIQ:
126 /*
127 * If FIQs are routed to EL3 or EL2 then there are cases where
128 * we override the CPSR.F in determining if the exception is
129 * masked or not. If neither of these are set then we fall back
130 * to the CPSR.F setting otherwise we further assess the state
131 * below.
132 */
133 hcr = hcr_el2 & HCR_FMO;
134 scr = (env->cp15.scr_el3 & SCR_FIQ);
135
136 /*
137 * When EL3 is 32-bit, the SCR.FW bit controls whether the
138 * CPSR.F bit masks FIQ interrupts when taken in non-secure
139 * state. If SCR.FW is set then FIQs can be masked by CPSR.F
140 * when non-secure but only when FIQs are only routed to EL3.
141 */
142 scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr);
143 break;
144 case EXCP_IRQ:
145 /*
146 * When EL3 execution state is 32-bit, if HCR.IMO is set then
147 * we may override the CPSR.I masking when in non-secure state.
148 * The SCR.IRQ setting has already been taken into consideration
149 * when setting the target EL, so it does not have a further
150 * affect here.
151 */
152 hcr = hcr_el2 & HCR_IMO;
153 scr = false;
154 break;
155 default:
156 g_assert_not_reached();
157 }
158
159 if ((scr || hcr) && !secure) {
160 unmasked = true;
161 }
162 }
163 }
164
165 /*
166 * The PSTATE bits only mask the interrupt if we have not overridden the
167 * ability above.
168 */
169 return unmasked || pstate_unmasked;
170 }
171
172 bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
173 {
174 CPUARMState *env = cpu_env(cs);
175 uint32_t cur_el = arm_current_el(env);
176 bool secure = arm_is_secure(env);
177 uint64_t hcr_el2 = arm_hcr_el2_eff(env);
178 uint32_t target_el;
179 uint32_t excp_idx;
180
181 /* The prioritization of interrupts is IMPLEMENTATION DEFINED. */
182
183 if (cpu_isar_feature(aa64_nmi, env_archcpu(env)) &&
184 (arm_sctlr(env, cur_el) & SCTLR_NMI)) {
185 if (interrupt_request & CPU_INTERRUPT_NMI) {
186 excp_idx = EXCP_NMI;
187 target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
188 if (arm_excp_unmasked(cs, excp_idx, target_el,
189 cur_el, secure, hcr_el2)) {
190 goto found;
191 }
192 }
193 if (interrupt_request & CPU_INTERRUPT_VINMI) {
194 excp_idx = EXCP_VINMI;
195 target_el = 1;
196 if (arm_excp_unmasked(cs, excp_idx, target_el,
197 cur_el, secure, hcr_el2)) {
198 goto found;
199 }
200 }
201 if (interrupt_request & CPU_INTERRUPT_VFNMI) {
202 excp_idx = EXCP_VFNMI;
203 target_el = 1;
204 if (arm_excp_unmasked(cs, excp_idx, target_el,
205 cur_el, secure, hcr_el2)) {
206 goto found;
207 }
208 }
209 } else {
210 /*
211 * NMI disabled: interrupts with superpriority are handled
212 * as if they didn't have it
213 */
214 if (interrupt_request & CPU_INTERRUPT_NMI) {
215 interrupt_request |= CPU_INTERRUPT_HARD;
216 }
217 if (interrupt_request & CPU_INTERRUPT_VINMI) {
218 interrupt_request |= CPU_INTERRUPT_VIRQ;
219 }
220 if (interrupt_request & CPU_INTERRUPT_VFNMI) {
221 interrupt_request |= CPU_INTERRUPT_VFIQ;
222 }
223 }
224
225 if (interrupt_request & CPU_INTERRUPT_FIQ) {
226 excp_idx = EXCP_FIQ;
227 target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
228 if (arm_excp_unmasked(cs, excp_idx, target_el,
229 cur_el, secure, hcr_el2)) {
230 goto found;
231 }
232 }
233 if (interrupt_request & CPU_INTERRUPT_HARD) {
234 excp_idx = EXCP_IRQ;
235 target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
236 if (arm_excp_unmasked(cs, excp_idx, target_el,
237 cur_el, secure, hcr_el2)) {
238 goto found;
239 }
240 }
241 if (interrupt_request & CPU_INTERRUPT_VIRQ) {
242 excp_idx = EXCP_VIRQ;
243 target_el = 1;
244 if (arm_excp_unmasked(cs, excp_idx, target_el,
245 cur_el, secure, hcr_el2)) {
246 goto found;
247 }
248 }
249 if (interrupt_request & CPU_INTERRUPT_VFIQ) {
250 excp_idx = EXCP_VFIQ;
251 target_el = 1;
252 if (arm_excp_unmasked(cs, excp_idx, target_el,
253 cur_el, secure, hcr_el2)) {
254 goto found;
255 }
256 }
257 if (interrupt_request & CPU_INTERRUPT_VSERR) {
258 excp_idx = EXCP_VSERR;
259 target_el = 1;
260 if (arm_excp_unmasked(cs, excp_idx, target_el,
261 cur_el, secure, hcr_el2)) {
262 /* Taking a virtual abort clears HCR_EL2.VSE */
263 env->cp15.hcr_el2 &= ~HCR_VSE;
264 cpu_reset_interrupt(cs, CPU_INTERRUPT_VSERR);
265 goto found;
266 }
267 }
268 return false;
269
270 found:
271 cs->exception_index = excp_idx;
272 env->exception.target_el = target_el;
273 cs->cc->tcg_ops->do_interrupt(cs);
274 return true;
275 }
276 #endif /* CONFIG_TCG */
277
278 void arm_cpu_update_virq(ARMCPU *cpu)
279 {
280 /*
281 * Update the interrupt level for VIRQ, which is the logical OR of
282 * the HCR_EL2.VI bit and the input line level from the GIC.
283 */
284 CPUARMState *env = &cpu->env;
285 CPUState *cs = CPU(cpu);
286
287 bool new_state = ((arm_hcr_el2_eff(env) & HCR_VI) &&
288 !(arm_hcrx_el2_eff(env) & HCRX_VINMI)) ||
289 (env->irq_line_state & CPU_INTERRUPT_VIRQ);
290
291 if (new_state != cpu_test_interrupt(cs, CPU_INTERRUPT_VIRQ)) {
292 if (new_state) {
293 cpu_interrupt(cs, CPU_INTERRUPT_VIRQ);
294 } else {
295 cpu_reset_interrupt(cs, CPU_INTERRUPT_VIRQ);
296 }
297 }
298 }
299
300 void arm_cpu_update_vfiq(ARMCPU *cpu)
301 {
302 /*
303 * Update the interrupt level for VFIQ, which is the logical OR of
304 * the HCR_EL2.VF bit and the input line level from the GIC.
305 */
306 CPUARMState *env = &cpu->env;
307 CPUState *cs = CPU(cpu);
308
309 bool new_state = ((arm_hcr_el2_eff(env) & HCR_VF) &&
310 !(arm_hcrx_el2_eff(env) & HCRX_VFNMI)) ||
311 (env->irq_line_state & CPU_INTERRUPT_VFIQ);
312
313 if (new_state != cpu_test_interrupt(cs, CPU_INTERRUPT_VFIQ)) {
314 if (new_state) {
315 cpu_interrupt(cs, CPU_INTERRUPT_VFIQ);
316 } else {
317 cpu_reset_interrupt(cs, CPU_INTERRUPT_VFIQ);
318 }
319 }
320 }
321
322 void arm_cpu_update_vinmi(ARMCPU *cpu)
323 {
324 /*
325 * Update the interrupt level for VINMI, which is the logical OR of
326 * the HCRX_EL2.VINMI bit and the input line level from the GIC.
327 */
328 CPUARMState *env = &cpu->env;
329 CPUState *cs = CPU(cpu);
330
331 bool new_state = ((arm_hcr_el2_eff(env) & HCR_VI) &&
332 (arm_hcrx_el2_eff(env) & HCRX_VINMI)) ||
333 (env->irq_line_state & CPU_INTERRUPT_VINMI);
334
335 if (new_state != cpu_test_interrupt(cs, CPU_INTERRUPT_VINMI)) {
336 if (new_state) {
337 cpu_interrupt(cs, CPU_INTERRUPT_VINMI);
338 } else {
339 cpu_reset_interrupt(cs, CPU_INTERRUPT_VINMI);
340 }
341 }
342 }
343
344 void arm_cpu_update_vfnmi(ARMCPU *cpu)
345 {
346 /*
347 * Update the interrupt level for VFNMI, which is the HCRX_EL2.VFNMI bit.
348 */
349 CPUARMState *env = &cpu->env;
350 CPUState *cs = CPU(cpu);
351
352 bool new_state = (arm_hcr_el2_eff(env) & HCR_VF) &&
353 (arm_hcrx_el2_eff(env) & HCRX_VFNMI);
354
355 if (new_state != cpu_test_interrupt(cs, CPU_INTERRUPT_VFNMI)) {
356 if (new_state) {
357 cpu_interrupt(cs, CPU_INTERRUPT_VFNMI);
358 } else {
359 cpu_reset_interrupt(cs, CPU_INTERRUPT_VFNMI);
360 }
361 }
362 }
363
364 void arm_cpu_update_vserr(ARMCPU *cpu)
365 {
366 /*
367 * Update the interrupt level for VSERR, which is the HCR_EL2.VSE bit.
368 */
369 CPUARMState *env = &cpu->env;
370 CPUState *cs = CPU(cpu);
371
372 bool new_state = env->cp15.hcr_el2 & HCR_VSE;
373
374 if (new_state != cpu_test_interrupt(cs, CPU_INTERRUPT_VSERR)) {
375 if (new_state) {
376 cpu_interrupt(cs, CPU_INTERRUPT_VSERR);
377 } else {
378 cpu_reset_interrupt(cs, CPU_INTERRUPT_VSERR);
379 }
380 }
381 }
382