int handle_sysreg_trap(uint64_t esr_el3, cpu_context_t *ctx)
{
switch (esr_el3 & ISS_SYSREG_OPCODE_MASK) {
+#if ENABLE_FEAT_RNG_TRAP
+ case ISS_SYSREG_OPCODE_RNDR:
+ case ISS_SYSREG_OPCODE_RNDRRS:
+ return plat_handle_rng_trap(esr_el3, ctx);
+#endif
default:
return TRAP_RET_UNHANDLED;
}
The default implementation of this function calls
``report_unhandled_exception``.
+Function : plat_handle_rng_trap
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : uint64_t
+ Argument : cpu_context_t *
+ Return : int
+
+This function is invoked by BL31's exception handler when there is a synchronous
+system register trap caused by access to the RNDR or RNDRRS registers. It allows
+platforms implementing ``FEAT_RNG_TRAP`` and enabling ``ENABLE_FEAT_RNG_TRAP`` to
+emulate those system registers by returing back some entropy to the lower EL.
+
+The first parameter (``uint64_t esr_el3``) contains the content of the ESR_EL3
+syndrome register, which encodes the instruction that was trapped. The interesting
+information in there is the target register (``get_sysreg_iss_rt()``).
+
+The second parameter (``cpu_context_t *ctx``) represents the CPU state in the
+lower exception level, at the time when the execution of the ``mrs`` instruction
+was trapped. Its content can be changed, to put the entropy into the target
+register.
+
+The return value indicates how to proceed:
+
+- When returning ``TRAP_RET_UNHANDLED`` (-1), the machine will panic.
+- When returning ``TRAP_RET_REPEAT`` (0), the exception handler will return
+ to the same instruction, so its execution will be repeated.
+- When returning ``TRAP_RET_CONTINUE`` (1), the exception handler will return
+ to the next instruction.
+
+This function needs to be implemented by a platform if it enables FEAT_RNG_TRAP.
+
Build flags
-----------
#define RGSR_EL1 S3_0_C1_C0_5
#define GCR_EL1 S3_0_C1_C0_6
+/*******************************************************************************
+ * Armv8.5 - Random Number Generator Registers
+ ******************************************************************************/
+#define RNDR S3_3_C2_C4_0
+#define RNDRRS S3_3_C2_C4_1
+
/*******************************************************************************
* FEAT_HCX - Extended Hypervisor Configuration Register
******************************************************************************/
DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1)
/* Armv8.5 FEAT_RNG Registers */
-DEFINE_SYSREG_READ_FUNC(rndr)
-DEFINE_SYSREG_READ_FUNC(rndrrs)
+DEFINE_RENAME_SYSREG_READ_FUNC(rndr, RNDR)
+DEFINE_RENAME_SYSREG_READ_FUNC(rndrrs, RNDRRS)
/* FEAT_HCX Register */
DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2)
#define ISS_SYSREG_REG_SHIFT 5U
#define ISS_SYSREG_DIRECTION_MASK 0x000001UL
+#define ISS_SYSREG_OPCODE_RNDR 0x30c808U
+#define ISS_SYSREG_OPCODE_RNDRRS 0x32c808U
+
#define TRAP_RET_UNHANDLED -1
#define TRAP_RET_REPEAT 0
#define TRAP_RET_CONTINUE 1
*/
int handle_sysreg_trap(uint64_t esr_el3, cpu_context_t *ctx);
+/* Prototypes for system register emulation handlers provided by platforms. */
+int plat_handle_rng_trap(uint64_t esr_el3, cpu_context_t *ctx);
+
#endif /* __ASSEMBLER__ */
#endif
--- /dev/null
+/*
+ * Copyright (c) 2022, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file just contains demonstration code, to "handle" RNG traps.
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <bl31/sync_handle.h>
+#include <context.h>
+
+/*
+ * SCR_EL3.SCR_TRNDR_BIT also affects execution in EL3, so allow to disable
+ * the trap temporarily.
+ */
+static void enable_rng_trap(bool enable)
+{
+ uint64_t scr_el3 = read_scr_el3();
+
+ if (enable) {
+ scr_el3 |= SCR_TRNDR_BIT;
+ } else {
+ scr_el3 &= ~SCR_TRNDR_BIT;
+ }
+
+ write_scr_el3(scr_el3);
+ isb();
+}
+
+/*
+ * This emulation code here is not very meaningful: enabling the RNG
+ * trap typically happens for a reason, so just calling the actual
+ * hardware instructions might not be useful or even possible.
+ */
+int plat_handle_rng_trap(uint64_t esr_el3, cpu_context_t *ctx)
+{
+ /* extract the target register number from the exception syndrome */
+ unsigned int rt = get_sysreg_iss_rt(esr_el3);
+
+ /* ignore XZR accesses and writes to the register */
+ if (rt == 31 || is_sysreg_iss_write(esr_el3)) {
+ return TRAP_RET_CONTINUE;
+ }
+
+ enable_rng_trap(false);
+ if ((esr_el3 & ISS_SYSREG_OPCODE_MASK) == ISS_SYSREG_OPCODE_RNDR) {
+ ctx->gpregs_ctx.ctx_regs[rt] = read_rndr();
+ } else {
+ ctx->gpregs_ctx.ctx_regs[rt] = read_rndrrs();
+ }
+ enable_rng_trap(true);
+
+ /*
+ * We successfully handled the trap, continue with the next
+ * instruction.
+ */
+ return TRAP_RET_CONTINUE;
+}
plat/arm/board/fvp/fvp_realm_attest_key.c
endif
+ifeq (${ENABLE_FEAT_RNG_TRAP},1)
+BL31_SOURCES += plat/arm/board/fvp/fvp_sync_traps.c
+endif
+
ifeq (${BL2_AT_EL3},1)
BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
plat/arm/board/fvp/fvp_bl2_el3_setup.c \