summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2022-11-21 17:07:25 +0000
committerManish Pandey <manish.pandey2@arm.com>2022-12-21 12:59:36 +0000
commit1ae75529bc2e5a213c3e458898c219c34aa99f65 (patch)
tree523085f30f0fa8bb7c9eb9294f6b14c61f0dca25
parentccd81f1e097c3eafe38523110c8eebabbe662508 (diff)
downloadarm-trusted-firmware-1ae75529bc2e5a213c3e458898c219c34aa99f65.tar.gz
feat(fvp): emulate trapped RNDR
When a platform decides to use FEAT_RNG_TRAP, every RNDR or RNDRSS read will trap into EL3. The platform can then emulate those instructions, by either executing the real CPU instructions, potentially conditioning the results, or use rate-limiting or filtering to protect the hardware entropy pool. Another possiblitiy would be to use some platform specific TRNG device to get entropy and returning this. To demonstrate platform specific usage, add a demo implementation for the FVP: It will execute the actual CPU instruction and just return the result. This should serve as reference code to implement platform specific policies. We change the definition of read_rndr() and read_rndrrs() to use the alternative sysreg encoding, so that all assemblers can handle that. Add documentation about the new platform specific RNG handler function. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Change-Id: Ibce817b3b06ad20129d15531b81402e3cc3e9a9e
-rw-r--r--bl31/bl31_traps.c5
-rw-r--r--docs/getting_started/porting-guide.rst33
-rw-r--r--include/arch/aarch64/arch.h6
-rw-r--r--include/arch/aarch64/arch_helpers.h4
-rw-r--r--include/bl31/sync_handle.h6
-rw-r--r--plat/arm/board/fvp/fvp_sync_traps.c62
-rw-r--r--plat/arm/board/fvp/platform.mk4
7 files changed, 118 insertions, 2 deletions
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
@@ -1282,6 +1282,12 @@
#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 HCRX_EL2 S3_4_C1_C2_2
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 <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;
+}
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 \