diff --git a/bl31/bl31_traps.c b/bl31/bl31_traps.c index 7c01338dd..b12185ddc 100644 --- a/bl31/bl31_traps.c +++ b/bl31/bl31_traps.c @@ -12,6 +12,11 @@ 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; } diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst index aa57e1db6..d57345d34 100644 --- a/docs/getting_started/porting-guide.rst +++ b/docs/getting_started/porting-guide.rst @@ -3396,6 +3396,39 @@ This function must be implemented in assembly. 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 ----------- diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index f63e9232f..9e13c3d10 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -1281,6 +1281,12 @@ #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 ******************************************************************************/ diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index 50a5ad4ad..fe9b5a563 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -546,8 +546,8 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(rgsr_el1, RGSR_EL1) 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) diff --git a/include/bl31/sync_handle.h b/include/bl31/sync_handle.h index 6ff88f949..e211575a6 100644 --- a/include/bl31/sync_handle.h +++ b/include/bl31/sync_handle.h @@ -15,6 +15,9 @@ #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 @@ -50,6 +53,9 @@ static inline bool is_sysreg_iss_write(uint64_t esr) */ 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 diff --git a/plat/arm/board/fvp/fvp_sync_traps.c b/plat/arm/board/fvp/fvp_sync_traps.c new file mode 100644 index 000000000..91240f753 --- /dev/null +++ b/plat/arm/board/fvp/fvp_sync_traps.c @@ -0,0 +1,62 @@ +/* + * 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 + +#include +#include +#include +#include + +/* + * 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; +} diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 51ba03524..f28a6ff75 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -198,6 +198,10 @@ BL31_SOURCES += plat/arm/board/fvp/fvp_plat_attest_token.c \ 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 \