1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
5  */
6 
7 #include <arch.h>
8 #include <arch_helpers.h>
9 #include <buffer.h>
10 #include <esr.h>
11 #include <exit.h>
12 #include <gic.h>
13 #include <granule.h>
14 #include <inject_exp.h>
15 #include <psci.h>
16 #include <realm.h>
17 #include <rec.h>
18 #include <rsi-handler.h>
19 #include <rsi-logger.h>
20 #include <s2tt.h>
21 #include <simd.h>
22 #include <smc-rmi.h>
23 #include <smc-rsi.h>
24 #include <status.h>
25 #include <sysreg_traps.h>
26 
system_abort(void)27 __dead2 static void system_abort(void)
28 {
29 	/*
30 	 * TODO: report the abort to the EL3.
31 	 * We need to establish the exact EL3 API first.
32 	 */
33 	panic();
34 }
35 
fixup_aarch32_data_abort(struct rec * rec,unsigned long * esr)36 static bool fixup_aarch32_data_abort(struct rec *rec, unsigned long *esr)
37 {
38 	unsigned long spsr = read_spsr_el2();
39 	(void)rec;
40 
41 	if ((spsr & SPSR_EL2_nRW_AARCH32) != 0UL) {
42 		/*
43 		 * mmio emulation of AArch32 reads/writes is not supported.
44 		 */
45 		*esr &= ~ESR_EL2_ABORT_ISV_BIT;
46 		return true;
47 	}
48 	return false;
49 }
50 
get_dabt_write_value(struct rec * rec,unsigned long esr)51 static unsigned long get_dabt_write_value(struct rec *rec, unsigned long esr)
52 {
53 	unsigned int rt = esr_srt(esr);
54 
55 	/* Handle xzr */
56 	if (rt == 31U) {
57 		return 0UL;
58 	}
59 	return rec->regs[rt] & access_mask(esr);
60 }
61 
62 /*
63  * Returns 'true' if access from @rec to @addr is within the Protected IPA space.
64  */
access_in_rec_par(struct rec * rec,unsigned long addr)65 static bool access_in_rec_par(struct rec *rec, unsigned long addr)
66 {
67 	/*
68 	 * It is OK to check only the base address of the access because:
69 	 * - The Protected IPA space starts at address zero.
70 	 * - The IPA width is below 64 bits, therefore the access cannot
71 	 *   wrap around.
72 	 */
73 	return addr_in_rec_par(rec, addr);
74 }
75 
76 /*
77  * Returns 'true' if the @ipa is in PAR and its RIPAS is 'empty'.
78  *
79  * @ipa must be aligned to the granule size.
80  */
ipa_is_empty(unsigned long ipa,struct rec * rec)81 static bool ipa_is_empty(unsigned long ipa, struct rec *rec)
82 {
83 	struct s2_walk_result s2_walk;
84 	enum s2_walk_status walk_status;
85 
86 	assert(GRANULE_ALIGNED(ipa));
87 
88 	walk_status = realm_ipa_to_pa(rec, ipa, &s2_walk);
89 
90 	if (walk_status == WALK_SUCCESS) {
91 		granule_unlock(s2_walk.llt);
92 	}
93 
94 	if ((walk_status != WALK_INVALID_PARAMS) &&
95 	    (s2_walk.ripas_val == RIPAS_EMPTY)) {
96 		return true;
97 	}
98 	return false;
99 }
100 
fsc_is_external_abort(unsigned long fsc)101 static bool fsc_is_external_abort(unsigned long fsc)
102 {
103 	if (fsc == ESR_EL2_ABORT_FSC_SEA) {
104 		return true;
105 	}
106 
107 	if ((fsc >= ESR_EL2_ABORT_FSC_SEA_TTW_START) &&
108 	    (fsc <= ESR_EL2_ABORT_FSC_SEA_TTW_END)) {
109 		return true;
110 	}
111 
112 	return false;
113 }
114 
115 /*
116  * Handles Data/Instruction Aborts at a lower EL with External Abort fault
117  * status code (D/IFSC).
118  * Returns 'true' if the exception is the external abort and the `rec_exit`
119  * structure is populated, 'false' otherwise.
120  */
handle_sync_external_abort(struct rec * rec,struct rmi_rec_exit * rec_exit,unsigned long esr)121 static bool handle_sync_external_abort(struct rec *rec,
122 				       struct rmi_rec_exit *rec_exit,
123 				       unsigned long esr)
124 {
125 	unsigned long fsc = esr & MASK(ESR_EL2_ABORT_FSC);
126 	unsigned long set = esr & MASK(ESR_EL2_ABORT_SET);
127 	(void)rec;
128 
129 	if (!fsc_is_external_abort(fsc)) {
130 		return false;
131 	}
132 
133 	switch (set) {
134 	case ESR_EL2_ABORT_SET_UER:
135 		/*
136 		 * The recoverable SEA.
137 		 * Inject the sync. abort into the Realm.
138 		 * Report the exception to the host.
139 		 */
140 		inject_sync_idabort(ESR_EL2_ABORT_FSC_SEA);
141 		/*
142 		 * Fall through.
143 		 */
144 	case ESR_EL2_ABORT_SET_UEO:
145 		/*
146 		 * The restartable SEA.
147 		 * Report the exception to the host.
148 		 * The REC restarts the same instruction.
149 		 */
150 		rec_exit->esr = esr & ESR_NONEMULATED_ABORT_MASK;
151 
152 		/*
153 		 * The value of the HPFAR_EL2 is not provided to the host as
154 		 * it is undefined for external aborts.
155 		 *
156 		 * We also don't provide the content of FAR_EL2 because it
157 		 * has no practical value to the host without the HPFAR_EL2.
158 		 */
159 		break;
160 	case ESR_EL2_ABORT_SET_UC:
161 		/*
162 		 * The uncontainable SEA.
163 		 * Fatal to the system.
164 		 * Fall through.
165 		 */
166 	default:
167 		system_abort();
168 	}
169 
170 	return true;
171 }
172 
emulate_stage2_data_abort(struct rec * rec,struct rmi_rec_exit * rec_exit,unsigned long rtt_level)173 void emulate_stage2_data_abort(struct rec *rec,
174 			       struct rmi_rec_exit *rec_exit,
175 			       unsigned long rtt_level)
176 {
177 	unsigned long fipa = rec->regs[1];
178 
179 	assert(rtt_level <= (unsigned long)S2TT_PAGE_LEVEL);
180 
181 	/*
182 	 * Setup Exception Syndrom Register to emulate a real data abort
183 	 * and return to NS host to handle it.
184 	 */
185 	rec_exit->esr = (ESR_EL2_EC_DATA_ABORT |
186 			(ESR_EL2_ABORT_FSC_TRANSLATION_FAULT_L0 + rtt_level));
187 	rec_exit->far = 0UL;
188 	rec_exit->hpfar = fipa >> HPFAR_EL2_FIPA_OFFSET;
189 	rec_exit->exit_reason = RMI_EXIT_SYNC;
190 }
191 
192 /*
193  * Returns 'true' if the abort is handled and the RMM should return to the Realm,
194  * and returns 'false' if the exception should be reported to the HS host.
195  */
handle_data_abort(struct rec * rec,struct rmi_rec_exit * rec_exit,unsigned long esr)196 static bool handle_data_abort(struct rec *rec, struct rmi_rec_exit *rec_exit,
197 			      unsigned long esr)
198 {
199 	unsigned long far = 0UL;
200 	unsigned long hpfar = read_hpfar_el2();
201 	unsigned long fipa = (hpfar & MASK(HPFAR_EL2_FIPA)) << HPFAR_EL2_FIPA_OFFSET;
202 	unsigned long write_val = 0UL;
203 
204 	if (handle_sync_external_abort(rec, rec_exit, esr)) {
205 		/*
206 		 * All external aborts are immediately reported to the host.
207 		 */
208 		return false;
209 	}
210 
211 	/*
212 	 * The memory access that crosses a page boundary may cause two aborts
213 	 * with `hpfar_el2` values referring to two consecutive pages.
214 	 *
215 	 * Insert the SEA and return to the Realm if IPA is outside realm IPA space or
216 	 * the granule's RIPAS is EMPTY.
217 	 */
218 	if ((fipa >= rec_ipa_size(rec)) || ipa_is_empty(fipa, rec)) {
219 		inject_sync_idabort(ESR_EL2_ABORT_FSC_SEA);
220 		return true;
221 	}
222 
223 	if (fixup_aarch32_data_abort(rec, &esr) ||
224 	    access_in_rec_par(rec, fipa)) {
225 		esr &= ESR_NONEMULATED_ABORT_MASK;
226 		goto end;
227 	}
228 
229 	if (esr_is_write(esr)) {
230 		write_val = get_dabt_write_value(rec, esr);
231 	}
232 
233 	far = read_far_el2() & ~GRANULE_MASK;
234 	esr &= ESR_EMULATED_ABORT_MASK;
235 
236 end:
237 	rec_exit->esr = esr;
238 	rec_exit->far = far;
239 	rec_exit->hpfar = hpfar;
240 	rec_exit->gprs[0] = write_val;
241 
242 	return false;
243 }
244 
245 /*
246  * Returns 'true' if the abort is handled and the RMM should return to the Realm,
247  * and returns 'false' if the exception should be reported to the NS host.
248  */
handle_instruction_abort(struct rec * rec,struct rmi_rec_exit * rec_exit,unsigned long esr)249 static bool handle_instruction_abort(struct rec *rec, struct rmi_rec_exit *rec_exit,
250 				     unsigned long esr)
251 {
252 	unsigned long fsc = esr & MASK(ESR_EL2_ABORT_FSC);
253 	unsigned long fsc_type = fsc & ~MASK(ESR_EL2_ABORT_FSC_LEVEL);
254 	unsigned long hpfar = read_hpfar_el2();
255 	unsigned long fipa = (hpfar & MASK(HPFAR_EL2_FIPA)) << HPFAR_EL2_FIPA_OFFSET;
256 
257 	if (handle_sync_external_abort(rec, rec_exit, esr)) {
258 		/*
259 		 * All external aborts are immediately reported to the host.
260 		 */
261 		return false;
262 	}
263 
264 	/*
265 	 * Insert the SEA and return to the Realm if:
266 	 * - IPA is outside realm IPA space
267 	 * - The instruction abort is at an Unprotected IPA, or
268 	 * - The granule's RIPAS is EMPTY
269 	 */
270 	if ((fipa >= rec_ipa_size(rec)) ||
271 			!access_in_rec_par(rec, fipa) || ipa_is_empty(fipa, rec)) {
272 		inject_sync_idabort(ESR_EL2_ABORT_FSC_SEA);
273 		return true;
274 	}
275 
276 	if (fsc_type != ESR_EL2_ABORT_FSC_TRANSLATION_FAULT) {
277 		unsigned long far = read_far_el2();
278 
279 		/*
280 		 * TODO: Should this ever happen, or is it an indication of an
281 		 * internal consistency failure in the RMM which should lead
282 		 * to a panic instead?
283 		 */
284 
285 		ERROR("Unhandled instruction abort:\n");
286 		ERROR("    FSC: %12s0x%02lx\n", " ", fsc);
287 		ERROR("    FAR: %16lx\n", far);
288 		ERROR("  HPFAR: %16lx\n", hpfar);
289 		return false;
290 	}
291 
292 	rec_exit->hpfar = hpfar;
293 	rec_exit->esr = esr & ESR_NONEMULATED_ABORT_MASK;
294 
295 	return false;
296 }
297 
298 /*
299  * Handle FPU or SVE or SME exceptions.
300  * Returns: true if the exception is handled.
301  */
handle_simd_exception(struct rec * rec,unsigned long esr)302 static bool handle_simd_exception(struct rec *rec, unsigned long esr)
303 {
304 	unsigned long esr_el2_ec = esr & MASK(ESR_EL2_EC);
305 
306 	/*
307 	 * If the REC wants to use SVE and if SVE is not enabled for this REC
308 	 * then inject undefined abort. This can happen when CPU implements
309 	 * FEAT_SVE but the Realm didn't request this feature during creation.
310 	 */
311 	if ((esr_el2_ec == ESR_EL2_EC_SVE) && !rec->realm_info.simd_cfg.sve_en) {
312 		realm_inject_undef_abort();
313 		return true;
314 	}
315 
316 	/*
317 	 * This is a special case where an SVE Realm accessing certain SVE or SME
318 	 * instructions will be reported as SME exception if RMM was REC entered
319 	 * with PSTATE.SM=1. RMM needs to distinguish between lazy save-restore
320 	 * for SVE and access to SME.
321 	 * Some cases:
322 	 * 1. If SVE is disabled for the realm, then RMM needs to inject UNDEF.
323 	 * 2. If SVE is enabled for the realm, RMM will restore SVE SIMD context
324 	 *    of the REC and will resume the Realm (this will get the CPU out of
325 	 *    streaming mode). While re-trying the faulting instruction if it
326 	 *    generates a SME exception, then RMM will inject undefined abort
327 	 *    since SME is not supported for Realm.
328 	 */
329 	if ((esr_el2_ec == ESR_EL2_EC_SME) &&
330 	    (!rec->realm_info.simd_cfg.sve_en ||
331 	     (rec->active_simd_ctx == rec->aux_data.simd_ctx))) {
332 		realm_inject_undef_abort();
333 		return true;
334 	}
335 
336 	/*
337 	 * As REC uses lazy enablement, upon FPU/SVE/SME exception the active
338 	 * SIMD context must not be the REC's context
339 	 */
340 	assert(rec->active_simd_ctx != rec->aux_data.simd_ctx);
341 
342 	/* Save the NS SIMD context and restore REC's SIMD context */
343 	rec->active_simd_ctx = simd_context_switch(rec->active_simd_ctx,
344 						   rec->aux_data.simd_ctx);
345 
346 	/*
347 	 * As the REC SIMD context is now restored, enable SIMD flags in REC's
348 	 * cptr based on REC's SIMD configuration.
349 	 */
350 	SIMD_ENABLE_CPTR_FLAGS(&rec->realm_info.simd_cfg, rec->sysregs.cptr_el2);
351 
352 	/*
353 	 * Return 'true' indicating that this exception has been handled and
354 	 * execution can continue.
355 	 */
356 	return true;
357 }
358 
advance_pc(void)359 void advance_pc(void)
360 {
361 	unsigned long pc = read_elr_el2();
362 
363 	write_elr_el2(pc + 4UL);
364 }
365 
rsi_handler_needs_fpu(unsigned int id)366 static inline bool rsi_handler_needs_fpu(unsigned int id)
367 {
368 #ifdef RMM_FPU_USE_AT_REL2
369 	if ((id == SMC_RSI_ATTEST_TOKEN_CONTINUE) ||
370 	    (id == SMC_RSI_MEASUREMENT_EXTEND)) {
371 		return true;
372 	}
373 #else
374 	(void)id;
375 #endif
376 	return false;
377 }
378 
379 /*
380  * Return 'true' if execution should continue in the REC, otherwise return
381  * 'false' to go back to the NS caller of REC.Enter.
382  */
handle_realm_rsi(struct rec * rec,struct rmi_rec_exit * rec_exit)383 static bool handle_realm_rsi(struct rec *rec, struct rmi_rec_exit *rec_exit)
384 {
385 	struct rsi_result res = {UPDATE_REC_RETURN_TO_REALM, 0UL,
386 				{{[0 ... SMC_RESULT_REGS-1] = 0UL}}};
387 	unsigned int function_id = (unsigned int)rec->regs[0];
388 	bool rec_ret, restore_simd_ctx = false;
389 	unsigned int i;
390 
391 	RSI_LOG_SET(rec->regs);
392 
393 	/*
394 	 * According to SMCCCv1.1+ if SMC call doesn't return result
395 	 * in register starting from X4, it must preserve its value.
396 	 */
397 	for (i = 4U; i < SMC_RESULT_REGS; ++i) {
398 		res.smc_res.x[i] = rec->regs[i];
399 	}
400 
401 	/* Ignore SVE hint bit, until RMM supports SVE hint bit */
402 	function_id &= ~SMC_SVE_HINT;
403 
404 	if (rsi_handler_needs_fpu(function_id) == true) {
405 		simd_context_save(rec->active_simd_ctx);
406 		restore_simd_ctx = true;
407 	}
408 
409 	switch (function_id) {
410 	case SMCCC_VERSION:
411 		res.action = UPDATE_REC_RETURN_TO_REALM;
412 		res.smc_res.x[0] = SMCCC_VERSION_NUMBER;
413 		break;
414 	case SMC32_PSCI_FID_MIN ... SMC32_PSCI_FID_MAX:
415 	case SMC64_PSCI_FID_MIN ... SMC64_PSCI_FID_MAX:
416 		handle_psci(rec, rec_exit, &res);
417 		break;
418 	case SMC_RSI_VERSION:
419 		handle_rsi_version(rec, &res);
420 		break;
421 	case SMC_RSI_FEATURES:
422 		handle_rsi_features(rec, &res);
423 		break;
424 	case SMC_RSI_ATTEST_TOKEN_INIT:
425 		handle_rsi_attest_token_init(rec, &res);
426 		break;
427 	case SMC_RSI_ATTEST_TOKEN_CONTINUE:
428 		handle_rsi_attest_token_continue(rec, rec_exit, &res);
429 		break;
430 	case SMC_RSI_MEASUREMENT_READ:
431 		handle_rsi_measurement_read(rec, &res);
432 		break;
433 	case SMC_RSI_MEASUREMENT_EXTEND:
434 		handle_rsi_measurement_extend(rec, &res);
435 		break;
436 	case SMC_RSI_REALM_CONFIG:
437 		handle_rsi_realm_config(rec, &res);
438 		break;
439 	case SMC_RSI_IPA_STATE_SET:
440 		handle_rsi_ipa_state_set(rec, rec_exit, &res);
441 		break;
442 	case SMC_RSI_IPA_STATE_GET:
443 		handle_rsi_ipa_state_get(rec, &res);
444 		break;
445 	case SMC_RSI_HOST_CALL:
446 		handle_rsi_host_call(rec, rec_exit, &res);
447 		break;
448 	default:
449 		res.action = UPDATE_REC_RETURN_TO_REALM;
450 		res.smc_res.x[0] = SMC_UNKNOWN;
451 		break;
452 	}
453 
454 	if (restore_simd_ctx) {
455 		simd_context_restore(rec->active_simd_ctx);
456 	}
457 
458 	if (((unsigned int)res.action & FLAG_UPDATE_REC) != 0U) {
459 		for (i = 0U; i < SMC_RESULT_REGS; ++i) {
460 			rec->regs[i] = res.smc_res.x[i];
461 		}
462 	}
463 
464 	if (((unsigned int)res.action & FLAG_STAGE_2_ABORT) != 0U) {
465 		emulate_stage2_data_abort(rec, rec_exit, res.rtt_level);
466 	} else {
467 		advance_pc();
468 	}
469 
470 	rec_ret = (((unsigned int)res.action & FLAG_EXIT_TO_HOST) == 0U);
471 
472 	/* Log RSI call */
473 	RSI_LOG_EXIT(function_id, rec->regs, rec_ret);
474 
475 	return rec_ret;
476 }
477 
478 /*
479  * Return 'true' if the RMM handled the exception,
480  * 'false' to return to the Non-secure host.
481  */
handle_exception_sync(struct rec * rec,struct rmi_rec_exit * rec_exit)482 static bool handle_exception_sync(struct rec *rec, struct rmi_rec_exit *rec_exit)
483 {
484 	const unsigned long esr = read_esr_el2();
485 
486 	switch (esr & MASK(ESR_EL2_EC)) {
487 	case ESR_EL2_EC_WFX:
488 		rec_exit->esr = esr & (MASK(ESR_EL2_EC) | ESR_EL2_WFx_TI_BIT);
489 		advance_pc();
490 		return false;
491 	case ESR_EL2_EC_HVC:
492 		realm_inject_undef_abort();
493 		return true;
494 	case ESR_EL2_EC_SMC:
495 		return handle_realm_rsi(rec, rec_exit);
496 	case ESR_EL2_EC_SYSREG: {
497 		bool ret = handle_sysreg_access_trap(rec, rec_exit, esr);
498 		return ret;
499 	}
500 	case ESR_EL2_EC_INST_ABORT:
501 		return handle_instruction_abort(rec, rec_exit, esr);
502 	case ESR_EL2_EC_DATA_ABORT:
503 		return handle_data_abort(rec, rec_exit, esr);
504 	case ESR_EL2_EC_FPU:
505 	case ESR_EL2_EC_SVE:
506 	case ESR_EL2_EC_SME:
507 		return handle_simd_exception(rec, esr);
508 	default:
509 		/*
510 		 * TODO: Check if there are other exit reasons we could
511 		 * encounter here and handle them appropriately
512 		 */
513 		break;
514 	}
515 
516 	VERBOSE("Unhandled sync exit ESR: %08lx (EC: %lx ISS: %lx)\n",
517 		esr, EXTRACT(ESR_EL2_EC, esr), EXTRACT(ESR_EL2_ISS, esr));
518 
519 	/*
520 	 * Zero values in esr, far & hpfar of 'rec_exit' structure
521 	 * will be returned to the NS host.
522 	 * The only information that may leak is when there was
523 	 * some unhandled/unknown reason for the exception.
524 	 */
525 	return false;
526 }
527 
528 /*
529  * Return 'true' if the RMM handled the exception, 'false' to return to the
530  * Non-secure host.
531  */
handle_exception_serror_lel(struct rec * rec,struct rmi_rec_exit * rec_exit)532 static bool handle_exception_serror_lel(struct rec *rec, struct rmi_rec_exit *rec_exit)
533 {
534 	const unsigned long esr = read_esr_el2();
535 
536 	if ((esr & ESR_EL2_SERROR_IDS_BIT) != 0UL) {
537 		/*
538 		 * Implementation defined content of the esr.
539 		 */
540 		system_abort();
541 	}
542 
543 	if ((esr & MASK(ESR_EL2_SERROR_DFSC)) != ESR_EL2_SERROR_DFSC_ASYNC) {
544 		/*
545 		 * Either Uncategorized or Reserved fault status code.
546 		 */
547 		system_abort();
548 	}
549 
550 	switch (esr & MASK(ESR_EL2_SERROR_AET)) {
551 	case ESR_EL2_SERROR_AET_UEU:	/* Unrecoverable RAS Error */
552 	case ESR_EL2_SERROR_AET_UER:	/* Recoverable RAS Error */
553 		/*
554 		 * The abort is fatal to the current S/W. Inject the SError into
555 		 * the Realm so it can e.g. shut down gracefully or localize the
556 		 * problem at the specific EL0 application.
557 		 *
558 		 * Note: Consider shutting down the Realm here to avoid
559 		 * the host's attack on unstable Realms.
560 		 */
561 		inject_serror(rec, esr);
562 		/*
563 		 * Fall through.
564 		 */
565 	case ESR_EL2_SERROR_AET_CE:	/* Corrected RAS Error */
566 	case ESR_EL2_SERROR_AET_UEO:	/* Restartable RAS Error */
567 		/*
568 		 * Report the exception to the host.
569 		 */
570 		rec_exit->esr = esr & ESR_SERROR_MASK;
571 		break;
572 	case ESR_EL2_SERROR_AET_UC:	/* Uncontainable RAS Error */
573 		/*
574 		 * Fall through.
575 		 */
576 	default:
577 		/*
578 		 * Unrecognized Asynchronous Error Type
579 		 */
580 		system_abort();
581 	}
582 
583 	return false;
584 }
585 
handle_exception_irq_lel(struct rec * rec,struct rmi_rec_exit * rec_exit)586 static bool handle_exception_irq_lel(struct rec *rec, struct rmi_rec_exit *rec_exit)
587 {
588 	(void)rec;
589 
590 	rec_exit->exit_reason = RMI_EXIT_IRQ;
591 
592 	/*
593 	 * With GIC all virtual interrupt programming
594 	 * must go via the NS hypervisor.
595 	 */
596 	return false;
597 }
598 
599 /* Returns 'true' when returning to Realm (S) and false when to NS */
handle_realm_exit(struct rec * rec,struct rmi_rec_exit * rec_exit,int exception)600 bool handle_realm_exit(struct rec *rec, struct rmi_rec_exit *rec_exit, int exception)
601 {
602 	switch (exception) {
603 	case ARM_EXCEPTION_SYNC_LEL: {
604 		bool ret;
605 
606 		/*
607 		 * TODO: Sanitize ESR to ensure it doesn't leak sensitive
608 		 * information.
609 		 */
610 		rec_exit->exit_reason = RMI_EXIT_SYNC;
611 		ret = handle_exception_sync(rec, rec_exit);
612 		if (!ret) {
613 			rec->last_run_info.esr = read_esr_el2();
614 			/*
615 			 * Clear the ISV bit in last_run_info so that on next REC entry
616 			 * RMM doesn't allow MMIO emulation for invalid cases.
617 			 */
618 			if ((rec_exit->esr & ESR_EL2_ABORT_ISV_BIT) == 0UL) {
619 				rec->last_run_info.esr &= ~ESR_EL2_ABORT_ISV_BIT;
620 			}
621 			rec->last_run_info.far = read_far_el2();
622 			rec->last_run_info.hpfar = read_hpfar_el2();
623 		}
624 		return ret;
625 
626 		/*
627 		 * TODO: Much more detailed handling of exit reasons.
628 		 */
629 	}
630 	case ARM_EXCEPTION_IRQ_LEL:
631 		return handle_exception_irq_lel(rec, rec_exit);
632 	case ARM_EXCEPTION_FIQ_LEL:
633 		rec_exit->exit_reason = RMI_EXIT_FIQ;
634 		break;
635 	case ARM_EXCEPTION_SERROR_LEL: {
636 		const unsigned long esr = read_esr_el2();
637 		bool ret;
638 
639 		/*
640 		 * TODO: Sanitize ESR to ensure it doesn't leak sensitive
641 		 * information.
642 		 */
643 		rec_exit->exit_reason = RMI_EXIT_SERROR;
644 		ret = handle_exception_serror_lel(rec, rec_exit);
645 		if (!ret) {
646 			rec->last_run_info.esr = esr;
647 			rec->last_run_info.far = read_far_el2();
648 			rec->last_run_info.hpfar = read_hpfar_el2();
649 		}
650 		return ret;
651 	}
652 	default:
653 		INFO("Unrecognized exit reason: %d\n", exception);
654 		break;
655 	}
656 
657 	return false;
658 }
659