mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 01:24:27 +00:00
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
This commit is contained in:
parent
ccd81f1e09
commit
1ae75529bc
7 changed files with 118 additions and 2 deletions
|
@ -12,6 +12,11 @@
|
||||||
int handle_sysreg_trap(uint64_t esr_el3, cpu_context_t *ctx)
|
int handle_sysreg_trap(uint64_t esr_el3, cpu_context_t *ctx)
|
||||||
{
|
{
|
||||||
switch (esr_el3 & ISS_SYSREG_OPCODE_MASK) {
|
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:
|
default:
|
||||||
return TRAP_RET_UNHANDLED;
|
return TRAP_RET_UNHANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3396,6 +3396,39 @@ This function must be implemented in assembly.
|
||||||
The default implementation of this function calls
|
The default implementation of this function calls
|
||||||
``report_unhandled_exception``.
|
``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
|
Build flags
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
@ -1281,6 +1281,12 @@
|
||||||
#define RGSR_EL1 S3_0_C1_C0_5
|
#define RGSR_EL1 S3_0_C1_C0_5
|
||||||
#define GCR_EL1 S3_0_C1_C0_6
|
#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
|
* FEAT_HCX - Extended Hypervisor Configuration Register
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
|
@ -546,8 +546,8 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(rgsr_el1, RGSR_EL1)
|
||||||
DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1)
|
DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1)
|
||||||
|
|
||||||
/* Armv8.5 FEAT_RNG Registers */
|
/* Armv8.5 FEAT_RNG Registers */
|
||||||
DEFINE_SYSREG_READ_FUNC(rndr)
|
DEFINE_RENAME_SYSREG_READ_FUNC(rndr, RNDR)
|
||||||
DEFINE_SYSREG_READ_FUNC(rndrrs)
|
DEFINE_RENAME_SYSREG_READ_FUNC(rndrrs, RNDRRS)
|
||||||
|
|
||||||
/* FEAT_HCX Register */
|
/* FEAT_HCX Register */
|
||||||
DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2)
|
DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2)
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
#define ISS_SYSREG_REG_SHIFT 5U
|
#define ISS_SYSREG_REG_SHIFT 5U
|
||||||
#define ISS_SYSREG_DIRECTION_MASK 0x000001UL
|
#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_UNHANDLED -1
|
||||||
#define TRAP_RET_REPEAT 0
|
#define TRAP_RET_REPEAT 0
|
||||||
#define TRAP_RET_CONTINUE 1
|
#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);
|
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 /* __ASSEMBLER__ */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
62
plat/arm/board/fvp/fvp_sync_traps.c
Normal file
62
plat/arm/board/fvp/fvp_sync_traps.c
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -198,6 +198,10 @@ BL31_SOURCES += plat/arm/board/fvp/fvp_plat_attest_token.c \
|
||||||
plat/arm/board/fvp/fvp_realm_attest_key.c
|
plat/arm/board/fvp/fvp_realm_attest_key.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq (${ENABLE_FEAT_RNG_TRAP},1)
|
||||||
|
BL31_SOURCES += plat/arm/board/fvp/fvp_sync_traps.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (${BL2_AT_EL3},1)
|
ifeq (${BL2_AT_EL3},1)
|
||||||
BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
|
BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
|
||||||
plat/arm/board/fvp/fvp_bl2_el3_setup.c \
|
plat/arm/board/fvp/fvp_bl2_el3_setup.c \
|
||||||
|
|
Loading…
Add table
Reference in a new issue