diff options
33 files changed, 724 insertions, 166 deletions
@@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -1018,6 +1018,7 @@ $(eval $(call add_defines,\ SPM_MM \ SPMD_SPM_AT_SEL2 \ TRUSTED_BOARD_BOOT \ + TRNG_SUPPORT \ USE_COHERENT_MEM \ USE_DEBUGFS \ ARM_IO_IN_DTB \ diff --git a/bl31/bl31.mk b/bl31/bl31.mk index e299fe139..2088533ac 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -68,6 +68,11 @@ BL31_SOURCES += services/std_svc/sdei/sdei_dispatch.S \ services/std_svc/sdei/sdei_state.c endif +ifeq (${TRNG_SUPPORT},1) +BL31_SOURCES += services/std_svc/trng/trng_main.c \ + services/std_svc/trng/trng_entropy_pool.c +endif + ifeq (${ENABLE_SPE_FOR_LOWER_ELS},1) BL31_SOURCES += lib/extensions/spe/spe.c endif diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst index d063ec7e6..be3f0bb0f 100644 --- a/docs/getting_started/porting-guide.rst +++ b/docs/getting_started/porting-guide.rst @@ -2009,6 +2009,53 @@ interrupt and the interrupt ID are passed as parameters. The default implementation only prints out a warning message. +.. _porting_guide_trng_requirements: + +TRNG porting requirements +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The |TRNG| backend requires the platform to provide the following values +and mandatory functions. + +Values +...... + +value: uuid_t plat_trng_uuid [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This value must be defined to the UUID of the TRNG backend that is specific to +the hardware after ``plat_trng_setup`` function is called. This value must +conform to the SMCCC calling convention; The most significant 32 bits of the +UUID must not equal ``0xffffffff`` or the signed integer ``-1`` as this value in +w0 indicates failure to get a TRNG source. + +Functions +......... + +Function: void plat_entropy_setup(void) [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: none + Return: none + +This function is expected to do platform-specific initialization of any TRNG +hardware. This may include generating a UUID from a hardware-specific seed. + +Function: bool plat_get_entropy(uint64_t \*out) [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uint64_t * + Return: bool + Out : when the return value is true, the entropy has been written into the + storage pointed to + +This function writes entropy into storage provided by the caller. If no entropy +is available, it must return false and the storage must not be written. + Power State Coordination Interface (in BL31) -------------------------------------------- @@ -2941,7 +2988,7 @@ amount of open resources per driver. -------------- -*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.* +*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.* .. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf .. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html diff --git a/docs/global_substitutions.txt b/docs/global_substitutions.txt index d33155b9a..24ac8300e 100644 --- a/docs/global_substitutions.txt +++ b/docs/global_substitutions.txt @@ -56,6 +56,7 @@ .. |TF-M| replace:: :term:`TF-M` .. |TLB| replace:: :term:`TLB` .. |TLK| replace:: :term:`TLK` +.. |TRNG| replace:: :term:`TRNG` .. |TSP| replace:: :term:`TSP` .. |TZC| replace:: :term:`TZC` .. |UBSAN| replace:: :term:`UBSAN` diff --git a/docs/glossary.rst b/docs/glossary.rst index 08add3a70..54820e4b6 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -193,6 +193,9 @@ You can find additional definitions in the `Arm Glossary`_. TLK Trusted Little Kernel. A Trusted OS from NVIDIA. + TRNG + True Randon Number Generator (hardware based) + TSP Test Secure Payload diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst index ea72962e8..235b7b687 100644 --- a/docs/plat/arm/fvp/index.rst +++ b/docs/plat/arm/fvp/index.rst @@ -142,6 +142,11 @@ Arm FVP Platform Specific Build Options HW_CONFIG blob instead of the DTS file. This option is useful to override the default HW_CONFIG selected by the build system. +- ``FVP_GICR_REGION_PROTECTION``: Mark the redistributor pages of + inactive/fused CPU cores as read-only. The default value of this option + is ``0``, which means the redistributor pages of all CPU cores are marked + as read and write. + Booting Firmware Update images ------------------------------ diff --git a/fdts/tc0.dts b/fdts/tc0.dts index f1ade19e6..2d7611cf2 100644 --- a/fdts/tc0.dts +++ b/fdts/tc0.dts @@ -38,6 +38,18 @@ core3 { cpu = <&CPU3>; }; + core4 { + cpu = <&CPU4>; + }; + core5 { + cpu = <&CPU5>; + }; + core6 { + cpu = <&CPU6>; + }; + core7 { + cpu = <&CPU7>; + }; }; }; @@ -102,6 +114,42 @@ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x400>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x500>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x600>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + }; + + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x700>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + }; + }; memory@80000000 { diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h index 342239a52..01d663834 100644 --- a/include/drivers/st/stm32mp1_ddr_regs.h +++ b/include/drivers/st/stm32mp1_ddr_regs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ @@ -284,7 +284,7 @@ struct stm32mp1_ddrphy { #define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3) #define DDRCTRL_PWRCTL_SELFREF_SW BIT(5) -#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(19, 12) +#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(23, 16) #define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16) #define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0) diff --git a/include/plat/common/plat_trng.h b/include/plat/common/plat_trng.h new file mode 100644 index 000000000..a9f73b679 --- /dev/null +++ b/include/plat/common/plat_trng.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_TRNG_H +#define PLAT_TRNG_H + +#include <tools_share/uuid.h> + +/* TRNG platform functions */ + +extern uuid_t plat_trng_uuid; +void plat_entropy_setup(void); +bool plat_get_entropy(uint64_t *out); + +#endif /* PLAT_TRNG_H */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index ebcc85577..1def86ea7 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,6 +13,9 @@ #if defined(SPD_spmd) #include <services/spm_core_manifest.h> #endif +#if TRNG_SUPPORT +#include "plat_trng.h" +#endif /******************************************************************************* * Forward declarations diff --git a/include/services/trng_svc.h b/include/services/trng_svc.h new file mode 100644 index 000000000..ed4d557ca --- /dev/null +++ b/include/services/trng_svc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRNG_SVC_H +#define TRNG_SVC_H + +#include <stdbool.h> +#include <stdint.h> + +#include <lib/smccc.h> + +/* SMC function IDs for TRNG queries */ +#define ARM_TRNG_VERSION U(0x84000050) +#define ARM_TRNG_FEATURES U(0x84000051) +#define ARM_TRNG_GET_UUID U(0x84000052) +#define ARM_TRNG_RND32 U(0x84000053) +#define ARM_TRNG_RND64 U(0xc4000053) + +/* TRNG version numbers */ +#define TRNG_VERSION_MAJOR (0x1) +#define TRNG_VERSION_MINOR (0x0) + +/* TRNG Error Numbers */ +#define TRNG_E_SUCCESS (0) +#define TRNG_E_NOT_SUPPORTED (-1) +#define TRNG_E_INVALID_PARAMS (-2) +#define TRNG_E_NO_ENTROPY (-3) +#define TRNG_E_NOT_IMPLEMENTED (-4) + +#if TRNG_SUPPORT +void trng_setup(void); +bool is_trng_fid(uint32_t smc_fid); +#else +static inline void trng_setup(void) +{ +} + +static inline bool is_trng_fid(uint32_t smc_fid) +{ + return false; +} +#endif +uintptr_t trng_smc_handler( + uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags +); + +#endif /* TRNG_SVC_H */ diff --git a/lib/cpus/aarch64/rainier.S b/lib/cpus/aarch64/rainier.S index f7afd0ba1..3017a5012 100644 --- a/lib/cpus/aarch64/rainier.S +++ b/lib/cpus/aarch64/rainier.S @@ -21,10 +21,6 @@ #error "Rainier CPU supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" #endif -#if ERRATA_RAINIER_IC_TRAP - .global rainier_errata_ic_trap_handler -#endif - /* -------------------------------------------------- * Disable speculative loads if Rainier supports * SSBS. @@ -45,42 +41,6 @@ func rainier_disable_speculative_loads ret endfunc rainier_disable_speculative_loads -/* -------------------------------------------------- - * Errata Workaround for Neoverse N1 Erratum 1542419. - * This applies to revisions r3p0 - r4p0 of Neoverse N1 - * Since Rainier core is based on Neoverse N1 r4p0, this - * errata applies to Rainier core r0p0 - * Inputs: - * x0: variant[4:7] and revision[0:3] of current cpu. - * Shall clobber: x0-x17 - * -------------------------------------------------- - */ -func errata_n1_1542419_wa - /* Compare x0 against revision r3p0 and r4p0 */ - mov x17, x30 - bl check_errata_1542419 - cbz x0, 1f - - /* Apply instruction patching sequence */ - mov x0, xzr - msr CPUPSELR_EL3, x0 - ldr x0, =0xEE670D35 - msr CPUPOR_EL3, x0 - ldr x0, =0xFFFF0FFF - msr CPUPMR_EL3, x0 - ldr x0, =0x08000020007D - msr CPUPCR_EL3, x0 - isb -1: - ret x17 -endfunc errata_n1_1542419_wa - -func check_errata_1542419 - /* Applies to Rainier core r0p0. */ - mov x1, #0x00 - b cpu_rev_var_ls -endfunc check_errata_1542419 - func rainier_reset_func mov x19, x30 @@ -95,11 +55,6 @@ func rainier_reset_func bl cpu_get_rev_var mov x18, x0 -#if ERRATA_N1_1542419 - mov x0, x18 - bl errata_n1_1542419_wa -#endif - #if ENABLE_AMU /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ mrs x0, actlr_el3 @@ -146,53 +101,11 @@ func rainier_errata_report bl cpu_get_rev_var mov x8, x0 - /* - * Report all errata. The revision-variant information is passed to - * checking functions of each errata. - */ - report_errata ERRATA_N1_1542419, rainier, 1542419 - ldp x8, x30, [sp], #16 ret endfunc rainier_errata_report #endif -/* - * Handle trap of EL0 IC IVAU instructions to EL3 by executing a TLB - * inner-shareable invalidation to an arbitrary address followed by a DSB. - * - * x1: Exception Syndrome - */ -func rainier_errata_ic_trap_handler - cmp x1, #RAINIER_EC_IC_TRAP - b.ne 1f - tlbi vae3is, xzr - dsb sy - - # Skip the IC instruction itself - mrs x3, elr_el3 - add x3, x3, #4 - msr elr_el3, x3 - - ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] - ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] - ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] - ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] - -#if IMAGE_BL31 && RAS_EXTENSION - /* - * Issue Error Synchronization Barrier to synchronize SErrors before - * exiting EL3. We're running with EAs unmasked, so any synchronized - * errors would be taken immediately; therefore no need to inspect - * DISR_EL1 register. - */ - esb -#endif - eret -1: - ret -endfunc rainier_errata_ic_trap_handler - /* --------------------------------------------- * This function provides Rainier specific * register information for crash reporting. @@ -212,7 +125,6 @@ func rainier_cpu_reg_dump ret endfunc rainier_cpu_reg_dump -declare_cpu_ops_eh rainier, RAINIER_MIDR, \ +declare_cpu_ops rainier, RAINIER_MIDR, \ rainier_reset_func, \ - rainier_errata_ic_trap_handler, \ rainier_core_pwr_dwn diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 5217a8514..e94f3c31a 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2020, ARM Limited. All rights reserved. +# Copyright (c) 2016-2021, ARM Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -209,6 +209,9 @@ SAVE_KEYS := 0 # Software Delegated Exception support SDEI_SUPPORT := 0 +# True Random Number firmware Interface +TRNG_SUPPORT := 0 + # Whether code and read-only data should be put on separate memory pages. The # platform Makefile is free to override this value. SEPARATE_CODE_AND_RODATA := 0 diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index 6e479ac4f..52686faca 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -48,6 +48,18 @@ arm_config_t arm_config; DEVICE1_SIZE, \ MT_DEVICE | MT_RW | MT_SECURE) +#if FVP_GICR_REGION_PROTECTION +#define MAP_GICD_MEM MAP_REGION_FLAT(BASE_GICD_BASE, \ + BASE_GICD_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* Map all core's redistributor memory as read-only. After boots up, + * per-core map its redistributor memory as read-write */ +#define MAP_GICR_MEM MAP_REGION_FLAT(BASE_GICR_BASE, \ + (BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\ + MT_DEVICE | MT_RO | MT_SECURE) +#endif /* FVP_GICR_REGION_PROTECTION */ + /* * Need to be mapped with write permissions in order to set a new non-volatile * counter value. @@ -70,7 +82,9 @@ const mmap_region_t plat_arm_mmap[] = { V2M_MAP_FLASH0_RW, V2M_MAP_IOFPGA, MAP_DEVICE0, +#if FVP_INTERCONNECT_DRIVER == FVP_CCN MAP_DEVICE1, +#endif #if TRUSTED_BOARD_BOOT /* To access the Root of Trust Public Key registers. */ MAP_DEVICE2, @@ -86,7 +100,9 @@ const mmap_region_t plat_arm_mmap[] = { V2M_MAP_FLASH0_RW, V2M_MAP_IOFPGA, MAP_DEVICE0, +#if FVP_INTERCONNECT_DRIVER == FVP_CCN MAP_DEVICE1, +#endif ARM_MAP_NS_DRAM1, #ifdef __aarch64__ ARM_MAP_DRAM2, @@ -134,7 +150,12 @@ const mmap_region_t plat_arm_mmap[] = { ARM_MAP_EL3_TZC_DRAM, V2M_MAP_IOFPGA, MAP_DEVICE0, +#if FVP_GICR_REGION_PROTECTION + MAP_GICD_MEM, + MAP_GICR_MEM, +#else MAP_DEVICE1, +#endif /* FVP_GICR_REGION_PROTECTION */ ARM_V2M_MAP_MEM_PROTECT, #if SPM_MM ARM_SPM_BUF_EL3_MMAP, diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h index 4efe69258..831eb35b7 100644 --- a/plat/arm/board/fvp/fvp_def.h +++ b/plat/arm/board/fvp/fvp_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -135,7 +135,16 @@ /* Base FVP compatible GIC memory map */ #define BASE_GICD_BASE UL(0x2f000000) +#define BASE_GICD_SIZE UL(0x10000) #define BASE_GICR_BASE UL(0x2f100000) + +#if GIC_ENABLE_V4_EXTN +/* GICv4 redistributor size: 256KB */ +#define BASE_GICR_SIZE UL(0x40000) +#else +#define BASE_GICR_SIZE UL(0x20000) +#endif /* GIC_ENABLE_V4_EXTN */ + #define BASE_GICC_BASE UL(0x2c000000) #define BASE_GICH_BASE UL(0x2c010000) #define BASE_GICV_BASE UL(0x2c02f000) diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c index 3e04d6b67..8f3e7b702 100644 --- a/plat/arm/board/fvp/fvp_gicv3.c +++ b/plat/arm/board/fvp/fvp_gicv3.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,6 +15,11 @@ #include <plat/arm/common/fconf_sec_intr_config.h> #include <plat/common/platform.h> +#if FVP_GICR_REGION_PROTECTION +/* To indicate GICR region of the core initialized as Read-Write */ +static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false}; +#endif /* FVP_GICR_REGION_PROTECTION */ + /* The GICv3 driver only needs to be initialized in EL3 */ static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT]; @@ -61,8 +66,39 @@ static gicv3_driver_data_t fvp_gic_data = { .mpidr_to_core_pos = fvp_gicv3_mpidr_hash }; +/****************************************************************************** + * This function gets called per core to make its redistributor frame rw + *****************************************************************************/ +static void fvp_gicv3_make_rdistrif_rw(void) +{ +#if FVP_GICR_REGION_PROTECTION + unsigned int core_pos = plat_my_core_pos(); + + /* Make the redistributor frame RW if it is not done previously */ + if (fvp_gicr_rw_region_init[core_pos] != true) { + int ret = xlat_change_mem_attributes(BASE_GICR_BASE + + (core_pos * BASE_GICR_SIZE), + BASE_GICR_SIZE, + MT_EXECUTE_NEVER | + MT_DEVICE | MT_RW | + MT_SECURE); + + if (ret != 0) { + ERROR("Failed to make redistributor frame \ + read write = %d\n", ret); + panic(); + } else { + fvp_gicr_rw_region_init[core_pos] = true; + } + } +#else + return; +#endif /* FVP_GICR_REGION_PROTECTION */ +} + void plat_arm_gic_driver_init(void) { + fvp_gicv3_make_rdistrif_rw(); /* * Get GICD and GICR base addressed through FCONF APIs. * FCONF is not supported in BL32 for FVP. @@ -117,6 +153,8 @@ void plat_arm_gic_pcpu_init(void) int result; const uint64_t *plat_gicr_frames = fvp_gicr_frames; + fvp_gicv3_make_rdistrif_rw(); + do { result = gicv3_rdistif_probe(*plat_gicr_frames); diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 0a6fa56ad..6c09d7268 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -16,6 +16,10 @@ FVP_MAX_CPUS_PER_CLUSTER := 4 # Default number of threads per CPU on FVP FVP_MAX_PE_PER_CPU := 1 +# Disable redistributor frame of inactive/fused CPU cores by marking it as read +# only; enable redistributor frames of all CPU cores by default. +FVP_GICR_REGION_PROTECTION := 0 + FVP_DT_PREFIX := fvp-base-gicv3-psci # The FVP platform depends on this macro to build with correct GIC driver. @@ -30,6 +34,9 @@ $(eval $(call add_define,FVP_MAX_CPUS_PER_CLUSTER)) # Pass FVP_MAX_PE_PER_CPU to the build system. $(eval $(call add_define,FVP_MAX_PE_PER_CPU)) +# Pass FVP_GICR_REGION_PROTECTION to the build system. +$(eval $(call add_define,FVP_GICR_REGION_PROTECTION)) + # Sanity check the cluster count and if FVP_CLUSTER_COUNT <= 2, # choose the CCI driver , else the CCN driver ifeq ($(FVP_CLUSTER_COUNT), 0) diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 78704b583..61cfb610c 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -108,7 +108,7 @@ ifeq ($(USE_ROMLIB),1) all : bl1_romlib.bin endif -bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/romlib/romlib.bin +bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin romlib.bin @echo "Building combined BL1 and ROMLIB binary for Juno $@" ./lib/romlib/gen_combined_bl1_romlib.sh -o bl1_romlib.bin $(BUILD_PLAT) diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c index 5b91e87e1..59dd37b17 100644 --- a/plat/arm/board/morello/morello_bl31_setup.c +++ b/plat/arm/board/morello/morello_bl31_setup.c @@ -8,6 +8,7 @@ #include <drivers/arm/css/css_mhu_doorbell.h> #include <drivers/arm/css/scmi.h> #include <drivers/arm/css/sds.h> +#include <lib/cassert.h> #include <plat/arm/common/plat_arm.h> #include "morello_def.h" @@ -17,18 +18,21 @@ * Platform information structure stored in SDS. * This structure holds information about platform's DDR * size which is an information about multichip setup - * - multichip mode - * - slave_count - * - Local DDR size in GB, DDR memory in master board - * - Remote DDR size in GB, DDR memory in slave board + * - Local DDR size in bytes, DDR memory in master board + * - Remote DDR size in bytes, DDR memory in slave board + * - slave_count + * - multichip mode */ struct morello_plat_info { - bool multichip_mode; + uint64_t local_ddr_size; + uint64_t remote_ddr_size; uint8_t slave_count; - uint8_t local_ddr_size; - uint8_t remote_ddr_size; + bool multichip_mode; } __packed; +/* Compile time assertion to ensure the size of structure is 18 bytes */ +CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE, + assert_invalid_plat_info_size); /* * BL33 image information structure stored in SDS. * This structure holds the source & destination addresses and @@ -80,6 +84,7 @@ void bl31_platform_setup(void) int ret; struct morello_plat_info plat_info; struct morello_bl33_info bl33_info; + struct morello_plat_info *copy_dest; ret = sds_init(); if (ret != SDS_OK) { @@ -99,8 +104,8 @@ void bl31_platform_setup(void) /* Validate plat_info SDS */ if ((plat_info.local_ddr_size == 0U) - || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY_GB) - || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY_GB) + || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY) + || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY) || (plat_info.slave_count > MORELLO_MAX_SLAVE_COUNT)) { ERROR("platform info SDS is corrupted\n"); panic(); @@ -127,5 +132,6 @@ void bl31_platform_setup(void) * and platform information should be passed to BL33 using NT_FW_CONFIG * passing mechanism. */ - mmio_write_32(MORELLO_PLATFORM_INFO_BASE, *(uint32_t *)&plat_info); + copy_dest = (struct morello_plat_info *)MORELLO_PLATFORM_INFO_BASE; + *copy_dest = plat_info; } diff --git a/plat/arm/board/morello/morello_def.h b/plat/arm/board/morello/morello_def.h index 09db3032b..793729b99 100644 --- a/plat/arm/board/morello/morello_def.h +++ b/plat/arm/board/morello/morello_def.h @@ -18,8 +18,8 @@ /* SDS Platform information defines */ #define MORELLO_SDS_PLATFORM_INFO_STRUCT_ID U(8) #define MORELLO_SDS_PLATFORM_INFO_OFFSET U(0) -#define MORELLO_SDS_PLATFORM_INFO_SIZE U(4) -#define MORELLO_MAX_DDR_CAPACITY_GB U(64) +#define MORELLO_SDS_PLATFORM_INFO_SIZE U(18) +#define MORELLO_MAX_DDR_CAPACITY U(0x1000000000) #define MORELLO_MAX_SLAVE_COUNT U(16) /* SDS BL33 image information defines */ @@ -28,6 +28,6 @@ #define MORELLO_SDS_BL33_INFO_SIZE U(12) /* Base address of non-secure SRAM where Platform information will be filled */ -#define MORELLO_PLATFORM_INFO_BASE UL(0x06008000) +#define MORELLO_PLATFORM_INFO_BASE UL(0x06000000) #endif /* MORELLO_DEF_H */ diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk index 2a23bc60f..fc7d4d363 100644 --- a/plat/arm/board/morello/platform.mk +++ b/plat/arm/board/morello/platform.mk @@ -65,5 +65,3 @@ USE_COHERENT_MEM := 0 include plat/arm/common/arm_common.mk include plat/arm/css/common/css_common.mk include plat/arm/board/common/board_common.mk - -override ERRATA_N1_1542419 := 1 diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk index 6be611360..03771dc3d 100644 --- a/plat/arm/board/rdn2/platform.mk +++ b/plat/arm/board/rdn2/platform.mk @@ -1,4 +1,4 @@ -# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -57,3 +57,4 @@ NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config)) override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk index 5033b1874..2ffd139c9 100644 --- a/plat/arm/board/rdv1/platform.mk +++ b/plat/arm/board/rdv1/platform.mk @@ -1,4 +1,4 @@ -# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -57,3 +57,4 @@ NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG})) override CTX_INCLUDE_AARCH32_REGS := 0 +override ENABLE_AMU := 1 diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts b/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts index b6c543ade..2f459b013 100644 --- a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts +++ b/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts @@ -20,30 +20,27 @@ binary_size = <0x80000>; }; - chosen { - linux,initrd-start = <0>; - linux,initrd-end = <0>; - }; - hypervisor { compatible = "hafnium,hafnium"; vm1 { is_ffa_partition; debug_name = "cactus-primary"; load_address = <0xfe000000>; + vcpu_count = <8>; + mem_size = <1048576>; }; vm2 { is_ffa_partition; debug_name = "cactus-secondary"; load_address = <0xfe100000>; - vcpu_count = <4>; + vcpu_count = <8>; mem_size = <1048576>; }; vm3 { is_ffa_partition; debug_name = "cactus-tertiary"; load_address = <0xfe200000>; - vcpu_count = <4>; + vcpu_count = <8>; mem_size = <1048576>; }; }; @@ -60,9 +57,37 @@ }; /* - * SPM(Hafnium) requires secondary cpu nodes are declared in + * SPMC (Hafnium) requires secondary cpu nodes are declared in * descending order */ + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x700>; + enable-method = "psci"; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x600>; + enable-method = "psci"; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x500>; + enable-method = "psci"; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x400>; + enable-method = "psci"; + }; + CPU3:cpu@300 { device_type = "cpu"; compatible = "arm,armv8"; diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts index a58b9113e..221039c43 100644 --- a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts +++ b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts @@ -5,13 +5,6 @@ */ /dts-v1/; -#define AFF 00 - -#include "fvp-defs.dtsi" -#undef POST -#define POST \ - }; - / { compatible = "arm,ffa-core-manifest-1.0"; #address-cells = <2>; @@ -27,21 +20,14 @@ binary_size = <0x80000>; }; - /* - * temporary: This entry is added based on v2.4 hafnium and will be - * removed when rebased to upstream master. - */ - chosen { - linux,initrd-start = <0>; - linux,initrd-end = <0>; - }; - hypervisor { compatible = "hafnium,hafnium"; vm1 { is_ffa_partition; debug_name = "op-tee"; load_address = <0xfd280000>; + vcpu_count = <8>; + mem_size = <30928896>; /* 32MB TZC DRAM - SPMC region */ }; }; @@ -49,25 +35,65 @@ #address-cells = <0x2>; #size-cells = <0x0>; - CPU_0 + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; /* - * SPMC (Hafnium) requires secondary core nodes are declared - * in descending order. + * SPMC (Hafnium) requires secondary cpu nodes are declared in + * descending order */ - CPU_3 - CPU_2 - CPU_1 - }; + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x700>; + enable-method = "psci"; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x600>; + enable-method = "psci"; + }; - /* - * temporary: This device-memory region is added based on v2.4 hafnium - * and will be removed when rebased to upstream master. As first - * Secure Partition no longer maps device memory. - */ - device-memory@21000000 { - device_type = "device-memory"; - reg = <0x0 0x21000000 0x5f000000>; + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x500>; + enable-method = "psci"; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x400>; + enable-method = "psci"; + }; + + CPU3:cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x300>; + enable-method = "psci"; + }; + + CPU2:cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x200>; + enable-method = "psci"; + }; + + CPU1:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + }; }; /* 32MB of TC0_TZC_DRAM1_BASE */ diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc0/include/platform_def.h index 2ff2699b3..30b5ab716 100644 --- a/plat/arm/board/tc0/include/platform_def.h +++ b/plat/arm/board/tc0/include/platform_def.h @@ -17,7 +17,7 @@ #include <plat/arm/soc/common/soc_css_def.h> #include <plat/common/common_def.h> -#define PLATFORM_CORE_COUNT 4 +#define PLATFORM_CORE_COUNT 8 #define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */ @@ -202,7 +202,7 @@ #define PLAT_ARM_SCMI_CHANNEL_COUNT 1 #define PLAT_ARM_CLUSTER_COUNT U(1) -#define PLAT_MAX_CPUS_PER_CLUSTER U(4) +#define PLAT_MAX_CPUS_PER_CLUSTER U(8) #define PLAT_MAX_PE_PER_CPU U(1) #define PLAT_CSS_MHU_BASE UL(0x45400000) diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk index 6cc5f4618..393d09cff 100644 --- a/plat/arm/board/tc0/platform.mk +++ b/plat/arm/board/tc0/platform.mk @@ -43,7 +43,8 @@ TC0_BASE = plat/arm/board/tc0 PLAT_INCLUDES += -I${TC0_BASE}/include/ -TC0_CPU_SOURCES := lib/cpus/aarch64/cortex_matterhorn.S +TC0_CPU_SOURCES := lib/cpus/aarch64/cortex_klein.S \ + lib/cpus/aarch64/cortex_matterhorn.S INTERCONNECT_SOURCES := ${TC0_BASE}/tc0_interconnect.c diff --git a/plat/arm/board/tc0/tc0_topology.c b/plat/arm/board/tc0/tc0_topology.c index 5478fbc32..8cfc3b50e 100644 --- a/plat/arm/board/tc0/tc0_topology.c +++ b/plat/arm/board/tc0/tc0_topology.c @@ -33,6 +33,9 @@ const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = { (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)), (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)), (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)), + (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)), }; /******************************************************************************* diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c index 89e2cab08..36c3fbb6c 100644 --- a/plat/arm/css/sgi/sgi_bl31_setup.c +++ b/plat/arm/css/sgi/sgi_bl31_setup.c @@ -108,12 +108,11 @@ void sgi_bl31_common_platform_setup(void) const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) { /* - * For RD-E1-Edge and RD-V1 platforms, only CPU power ON/OFF - * PSCI platform callbacks are supported. + * For RD-E1-Edge, only CPU power ON/OFF, PSCI platform callbacks are + * supported. */ if (((sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) && - (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID)) || - (sgi_plat_info.platform_id == RD_V1_SID_VER_PART_NUM)) { + (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID))) { ops->cpu_standby = NULL; ops->system_off = NULL; ops->system_reset = NULL; diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c index cdd17bc1d..23f13ab82 100644 --- a/services/std_svc/std_svc_setup.c +++ b/services/std_svc/std_svc_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,6 +17,7 @@ #include <services/spm_mm_svc.h> #include <services/spmd_svc.h> #include <services/std_svc.h> +#include <services/trng_svc.h> #include <smccc_helpers.h> #include <tools_share/uuid.h> @@ -63,6 +64,8 @@ static int32_t std_svc_setup(void) sdei_init(); #endif + trng_setup(); + return ret; } @@ -139,6 +142,13 @@ static uintptr_t std_svc_smc_handler(uint32_t smc_fid, } #endif +#if TRNG_SUPPORT + if (is_trng_fid(smc_fid)) { + return trng_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } +#endif + switch (smc_fid) { case ARM_STD_SVC_CALL_COUNT: /* diff --git a/services/std_svc/trng/trng_entropy_pool.c b/services/std_svc/trng/trng_entropy_pool.c new file mode 100644 index 000000000..ac13b1d7a --- /dev/null +++ b/services/std_svc/trng/trng_entropy_pool.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> +#include <lib/spinlock.h> +#include <plat/common/plat_trng.h> + +/* + * # Entropy pool + * Note that the TRNG Firmware interface can request up to 192 bits of entropy + * in a single call or three 64bit words per call. We have 4 words in the pool + * so that when we have 1-63 bits in the pool, and we have a request for + * 192 bits of entropy, we don't have to throw out the leftover 1-63 bits of + * entropy. + */ +#define WORDS_IN_POOL (4) +static uint64_t entropy[WORDS_IN_POOL]; +/* index in bits of the first bit of usable entropy */ +static uint32_t entropy_bit_index; +/* then number of valid bits in the entropy pool */ +static uint32_t entropy_bit_size; + +static spinlock_t trng_pool_lock; + +#define BITS_PER_WORD (sizeof(entropy[0]) * 8) +#define BITS_IN_POOL (WORDS_IN_POOL * BITS_PER_WORD) +#define ENTROPY_MIN_WORD (entropy_bit_index / BITS_PER_WORD) +#define ENTROPY_FREE_BIT (entropy_bit_size + entropy_bit_index) +#define _ENTROPY_FREE_WORD (ENTROPY_FREE_BIT / BITS_PER_WORD) +#define ENTROPY_FREE_INDEX (_ENTROPY_FREE_WORD % WORDS_IN_POOL) +/* ENTROPY_WORD_INDEX(0) includes leftover bits in the lower bits */ +#define ENTROPY_WORD_INDEX(i) ((ENTROPY_MIN_WORD + i) % WORDS_IN_POOL) + +/* + * Fill the entropy pool until we have at least as many bits as requested. + * Returns true after filling the pool, and false if the entropy source is out + * of entropy and the pool could not be filled. + * Assumes locks are taken. + */ +static bool trng_fill_entropy(uint32_t nbits) +{ + while (nbits > entropy_bit_size) { + bool valid = plat_get_entropy(&entropy[ENTROPY_FREE_INDEX]); + + if (valid) { + entropy_bit_size += BITS_PER_WORD; + assert(entropy_bit_size <= BITS_IN_POOL); + } else { + return false; + } + } + return true; +} + +/* + * Pack entropy into the out buffer, filling and taking locks as needed. + * Returns true on success, false on failure. + * + * Note: out must have enough space for nbits of entropy + */ +bool trng_pack_entropy(uint32_t nbits, uint64_t *out) +{ + bool success = true; + + spin_lock(&trng_pool_lock); + + if (!trng_fill_entropy(nbits)) { + success = false; + goto out; + } + + const unsigned int rshift = entropy_bit_index % BITS_PER_WORD; + const unsigned int lshift = BITS_PER_WORD - rshift; + const int to_fill = ((nbits + BITS_PER_WORD - 1) / BITS_PER_WORD); + int word_i; + + for (word_i = 0; word_i < to_fill; word_i++) { + /* + * Repack the entropy from the pool into the passed in out + * buffer. This takes the lower bits from the valid upper bits + * of word_i and the upper bits from the lower bits of + * (word_i + 1). + * + * I found the following diagram useful. note: `e` represents + * valid entropy, ` ` represents invalid bits (not entropy) and + * `x` represents valid entropy that must not end up in the + * packed word. + * + * |---------entropy pool----------| + * C var |--(word_i + 1)-|----word_i-----| + * bit idx |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| + * [x,x,e,e,e,e,e,e|e,e, , , , , , ] + * | [e,e,e,e,e,e,e,e] | + * | |--out[word_i]--| | + * lshift|---| |--rshift---| + * + * ==== Which is implemented as ==== + * + * |---------entropy pool----------| + * C var |--(word_i + 1)-|----word_i-----| + * bit idx |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| + * [x,x,e,e,e,e,e,e|e,e, , , , , , ] + * C expr << lshift >> rshift + * bit idx 5 4 3 2 1 0 7 6 + * [e,e,e,e,e,e,0,0|0,0,0,0,0,0,e,e] + * ==== bit-wise or ==== + * 5 4 3 2 1 0 7 6 + * [e,e,e,e,e,e,e,e] + */ + out[word_i] = 0; + out[word_i] |= entropy[ENTROPY_WORD_INDEX(word_i)] >> rshift; + + /* + * Note that a shift of 64 bits is treated as a shift of 0 bits. + * When the shift amount is the same as the BITS_PER_WORD, we + * don't want to include the next word of entropy, so we skip + * the `|=` operation. + */ + if (lshift != BITS_PER_WORD) { + out[word_i] |= entropy[ENTROPY_WORD_INDEX(word_i + 1)] + << lshift; + } + } + const uint64_t mask = ~0ULL >> (BITS_PER_WORD - (nbits % BITS_PER_WORD)); + + out[to_fill - 1] &= mask; + + entropy_bit_index = (entropy_bit_index + nbits) % BITS_IN_POOL; + entropy_bit_size -= nbits; + +out: + spin_unlock(&trng_pool_lock); + + return success; +} + +void trng_entropy_pool_setup(void) +{ + int i; + + for (i = 0; i < WORDS_IN_POOL; i++) { + entropy[i] = 0; + } + entropy_bit_index = 0; + entropy_bit_size = 0; +} diff --git a/services/std_svc/trng/trng_entropy_pool.h b/services/std_svc/trng/trng_entropy_pool.h new file mode 100644 index 000000000..fab2367d2 --- /dev/null +++ b/services/std_svc/trng/trng_entropy_pool.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRNG_ENTROPY_POOL_H +#define TRNG_ENTROPY_POOL_H + +#include <stdbool.h> +#include <stdint.h> + +bool trng_pack_entropy(uint32_t nbits, uint64_t *out); +void trng_entropy_pool_setup(void); + +#endif /* TRNG_ENTROPY_POOL_H */ diff --git a/services/std_svc/trng/trng_main.c b/services/std_svc/trng/trng_main.c new file mode 100644 index 000000000..38aa64997 --- /dev/null +++ b/services/std_svc/trng/trng_main.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> + +#include <arch_features.h> +#include <lib/smccc.h> +#include <services/trng_svc.h> +#include <smccc_helpers.h> + +#include <plat/common/plat_trng.h> + +#include "trng_entropy_pool.h" + +static const uuid_t uuid_null; + +/* handle the RND call in SMC 32 bit mode */ +static uintptr_t trng_rnd32(uint32_t nbits, void *handle) +{ + uint32_t mask = ~0U; + uint64_t ent[2]; + + if (nbits == 0U || nbits > 96U) { + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + } + + if (!trng_pack_entropy(nbits, &ent[0])) { + SMC_RET1(handle, TRNG_E_NO_ENTROPY); + } + + if ((nbits % 32U) != 0U) { + mask >>= 32U - (nbits % 32U); + } + + switch ((nbits - 1U) / 32U) { + case 0: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask); + break; /* unreachable */ + case 1: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, (ent[0] >> 32) & mask, + ent[0] & 0xFFFFFFFF); + break; /* unreachable */ + case 2: + SMC_RET4(handle, TRNG_E_SUCCESS, ent[1] & mask, + (ent[0] >> 32) & 0xFFFFFFFF, ent[0] & 0xFFFFFFFF); + break; /* unreachable */ + default: + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + break; /* unreachable */ + } +} + +/* handle the RND call in SMC 64 bit mode */ +static uintptr_t trng_rnd64(uint32_t nbits, void *handle) +{ + uint64_t mask = ~0ULL; + uint64_t ent[3]; + + if (nbits == 0U || nbits > 192U) { + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + } + + if (!trng_pack_entropy(nbits, &ent[0])) { + SMC_RET1(handle, TRNG_E_NO_ENTROPY); + } + + /* Mask off higher bits if only part of register requested */ + if ((nbits % 64U) != 0U) { + mask >>= 64U - (nbits % 64U); + } + + switch ((nbits - 1U) / 64U) { + case 0: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask); + break; /* unreachable */ + case 1: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, ent[1] & mask, ent[0]); + break; /* unreachable */ + case 2: + SMC_RET4(handle, TRNG_E_SUCCESS, ent[2] & mask, ent[1], ent[0]); + break; /* unreachable */ + default: + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + break; /* unreachable */ + } +} + +void trng_setup(void) +{ + trng_entropy_pool_setup(); + plat_entropy_setup(); +} + +/* Predicate indicating that a function id is part of TRNG */ +bool is_trng_fid(uint32_t smc_fid) +{ + return ((smc_fid == ARM_TRNG_VERSION) || + (smc_fid == ARM_TRNG_FEATURES) || + (smc_fid == ARM_TRNG_GET_UUID) || + (smc_fid == ARM_TRNG_RND32) || + (smc_fid == ARM_TRNG_RND64)); +} + +uintptr_t trng_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, + u_register_t x3, u_register_t x4, void *cookie, + void *handle, u_register_t flags) +{ + if (!memcmp(&plat_trng_uuid, &uuid_null, sizeof(uuid_t))) { + SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED); + } + + switch (smc_fid) { + case ARM_TRNG_VERSION: + SMC_RET1(handle, MAKE_SMCCC_VERSION( + TRNG_VERSION_MAJOR, TRNG_VERSION_MINOR + )); + break; /* unreachable */ + case ARM_TRNG_FEATURES: + if (is_trng_fid((uint32_t)x1)) { + SMC_RET1(handle, TRNG_E_SUCCESS); + } else { + SMC_RET1(handle, TRNG_E_NOT_SUPPORTED); + } + break; /* unreachable */ + case ARM_TRNG_GET_UUID: + SMC_UUID_RET(handle, plat_trng_uuid); + break; /* unreachable */ + case ARM_TRNG_RND32: + return trng_rnd32((uint32_t)x1, handle); + case ARM_TRNG_RND64: + return trng_rnd64((uint32_t)x1, handle); + default: + WARN("Unimplemented TRNG Service Call: 0x%x\n", + smc_fid); + SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED); + break; /* unreachable */ + } +} |