1 /*
2  * Copyright (c) 2022, ARM Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * This file just contains demonstration code, to "handle" RNG traps.
7  */
8 
9 #include <stdbool.h>
10 
11 #include <arch.h>
12 #include <arch_helpers.h>
13 #include <bl31/sync_handle.h>
14 #include <context.h>
15 
16 /*
17  * SCR_EL3.SCR_TRNDR_BIT also affects execution in EL3, so allow to disable
18  * the trap temporarily.
19  */
enable_rng_trap(bool enable)20 static void enable_rng_trap(bool enable)
21 {
22 	uint64_t scr_el3 = read_scr_el3();
23 
24 	if (enable) {
25 		scr_el3 |= SCR_TRNDR_BIT;
26 	} else {
27 		scr_el3 &= ~SCR_TRNDR_BIT;
28 	}
29 
30 	write_scr_el3(scr_el3);
31 	isb();
32 }
33 
34 /*
35  * This emulation code here is not very meaningful: enabling the RNG
36  * trap typically happens for a reason, so just calling the actual
37  * hardware instructions might not be useful or even possible.
38  */
plat_handle_rng_trap(uint64_t esr_el3,cpu_context_t * ctx)39 int plat_handle_rng_trap(uint64_t esr_el3, cpu_context_t *ctx)
40 {
41 	/* extract the target register number from the exception syndrome */
42 	unsigned int rt = get_sysreg_iss_rt(esr_el3);
43 
44 	/* ignore XZR accesses and writes to the register */
45 	if (rt == 31 || is_sysreg_iss_write(esr_el3)) {
46 		return TRAP_RET_CONTINUE;
47 	}
48 
49 	enable_rng_trap(false);
50 	if ((esr_el3 & ISS_SYSREG_OPCODE_MASK) == ISS_SYSREG_OPCODE_RNDR) {
51 		ctx->gpregs_ctx.ctx_regs[rt] = read_rndr();
52 	} else {
53 		ctx->gpregs_ctx.ctx_regs[rt] = read_rndrrs();
54 	}
55 	enable_rng_trap(true);
56 
57 	/*
58 	 * We successfully handled the trap, continue with the next
59 	 * instruction.
60 	 */
61 	return TRAP_RET_CONTINUE;
62 }
63