]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
feat(fvp): emulate trapped RNDR
authorAndre Przywara <andre.przywara@arm.com>
Mon, 21 Nov 2022 17:07:25 +0000 (17:07 +0000)
committerManish Pandey <manish.pandey2@arm.com>
Wed, 21 Dec 2022 12:59:36 +0000 (12:59 +0000)
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

bl31/bl31_traps.c
docs/getting_started/porting-guide.rst
include/arch/aarch64/arch.h
include/arch/aarch64/arch_helpers.h
include/bl31/sync_handle.h
plat/arm/board/fvp/fvp_sync_traps.c [new file with mode: 0644]
plat/arm/board/fvp/platform.mk

index 7c01338dde7527ed7fbc7af941ab406bce1e3054..b12185ddc36c361dff56e8301e39668f13d4b539 100644 (file)
 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;
        }
index aa57e1db6be645ef325f636a9e4d02df0331a3ac..d57345d34b50c164e88c138e353447b1f67463d3 100644 (file)
@@ -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
 -----------
 
index f63e9232f71f38fce7ad5ed280793d1f8948e99a..9e13c3d1093b9b5e4d51c0da28850a2afbb1b964 100644 (file)
 #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
  ******************************************************************************/
index 50a5ad4adcf231fe1d61b2bb4a1834afff76eb1e..fe9b5a5639b0929e49a6ba4203b12f08b4334531 100644 (file)
@@ -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)
index 6ff88f949b488ad3b4276c201432988274c156d5..e211575a6ab2c3eb92da68ecc3ef9fc1f57d8fe6 100644 (file)
@@ -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 (file)
index 0000000..91240f7
--- /dev/null
@@ -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;
+}
index 51ba03524a4eb033840fa26076663317e6517b42..f28a6ff75f1572c78456485dc3bb7a2d4d060ead 100644 (file)
@@ -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          \