diff options
Diffstat (limited to 'services/std_svc/rmmd/trp')
-rw-r--r-- | services/std_svc/rmmd/trp/linker.ld.S | 72 | ||||
-rw-r--r-- | services/std_svc/rmmd/trp/trp.mk | 27 | ||||
-rw-r--r-- | services/std_svc/rmmd/trp/trp_entry.S | 153 | ||||
-rw-r--r-- | services/std_svc/rmmd/trp/trp_helpers.c | 58 | ||||
-rw-r--r-- | services/std_svc/rmmd/trp/trp_main.c | 185 | ||||
-rw-r--r-- | services/std_svc/rmmd/trp/trp_private.h | 61 |
6 files changed, 556 insertions, 0 deletions
diff --git a/services/std_svc/rmmd/trp/linker.ld.S b/services/std_svc/rmmd/trp/linker.ld.S new file mode 100644 index 0000000..9895cf9 --- /dev/null +++ b/services/std_svc/rmmd/trp/linker.ld.S @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/bl_common.ld.h> +#include <lib/xlat_tables/xlat_tables_defs.h> + +/* Mapped using 4K pages, requires us to align different sections with + * different property at the same granularity. */ +PAGE_SIZE_4K = 4096; + +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(trp_head) + +MEMORY { + RAM (rwx): ORIGIN = RMM_BASE, LENGTH = RMM_LIMIT - RMM_BASE +} + + +SECTIONS +{ + . = RMM_BASE; + + .text : { + *(.head.text) + . = ALIGN(8); + *(.text*) + } >RAM + + . = ALIGN(PAGE_SIZE_4K); + + .rodata : { + *(.rodata*) + } >RAM + + . = ALIGN(PAGE_SIZE_4K); + + __RW_START__ = . ; + + .data : { + *(.data*) + } >RAM + + .bss (NOLOAD) : { + __BSS_START__ = .; + *(.bss*) + __BSS_END__ = .; + } >RAM + __BSS_SIZE__ = SIZEOF(.bss); + + + STACK_SECTION >RAM + + + /* + * Define a linker symbol to mark the end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __RMM_END__ = .; + + + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } + /DISCARD/ : { *(.note*) } +} diff --git a/services/std_svc/rmmd/trp/trp.mk b/services/std_svc/rmmd/trp/trp.mk new file mode 100644 index 0000000..b7bd317 --- /dev/null +++ b/services/std_svc/rmmd/trp/trp.mk @@ -0,0 +1,27 @@ +# +# Copyright (c) 2021-2023 Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RMM_SOURCES += services/std_svc/rmmd/trp/trp_entry.S \ + services/std_svc/rmmd/trp/trp_main.c \ + services/std_svc/rmmd/trp/trp_helpers.c + +RMM_DEFAULT_LINKER_SCRIPT_SOURCE := services/std_svc/rmmd/trp/linker.ld.S + +ifneq ($(findstring gcc,$(notdir $(LD))),) + RMM_LDFLAGS += -Wl,--sort-section=alignment +else ifneq ($(findstring ld,$(notdir $(LD))),) + RMM_LDFLAGS += --sort-section=alignment +endif + +# Include the platform-specific TRP Makefile +# If no platform-specific TRP Makefile exists, it means TRP is not supported +# on this platform. +TRP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/trp/trp-${PLAT}.mk) +ifeq (,${TRP_PLAT_MAKEFILE}) + $(error TRP is not supported on platform ${PLAT}) +else + include ${TRP_PLAT_MAKEFILE} +endif diff --git a/services/std_svc/rmmd/trp/trp_entry.S b/services/std_svc/rmmd/trp/trp_entry.S new file mode 100644 index 0000000..3e1d8c9 --- /dev/null +++ b/services/std_svc/rmmd/trp/trp_entry.S @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <services/rmmd_svc.h> + +#include <platform_def.h> +#include "trp_private.h" + +.global trp_head +.global trp_smc + +.section ".head.text", "ax" + + /* --------------------------------------------- + * Populate the params in x0-x7 from the pointer + * to the smc args structure in x0. + * --------------------------------------------- + */ + .macro restore_args_call_smc + ldp x6, x7, [x0, #TRP_ARG6] + ldp x4, x5, [x0, #TRP_ARG4] + ldp x2, x3, [x0, #TRP_ARG2] + ldp x0, x1, [x0, #TRP_ARG0] + smc #0 + .endm + + /* --------------------------------------------- + * Entry point for TRP + * --------------------------------------------- + */ +trp_head: + /* + * Stash arguments from previous boot stage + */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + + /* + * Validate CPUId before allocating a stack. + */ + cmp x20, #PLATFORM_CORE_COUNT + b.lo 1f + + mov_imm x0, RMM_BOOT_COMPLETE + mov_imm x1, E_RMM_BOOT_CPU_ID_OUT_OF_RANGE + smc #0 + + /* EL3 should never return back here, so panic if it does */ + b trp_panic + +1: + bl plat_set_my_stack + + /* + * Find out whether this is a cold or warm boot + */ + ldr x1, cold_boot_flag + cbz x1, warm_boot + + /* + * Update cold boot flag to indicate cold boot is done + */ + adr x2, cold_boot_flag + str xzr, [x2] + + /* --------------------------------------------- + * Zero out BSS section + * --------------------------------------------- + */ + ldr x0, =__BSS_START__ + ldr x1, =__BSS_SIZE__ + bl zeromem + + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + bl trp_setup + bl trp_main + b 1f + +warm_boot: + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + bl trp_validate_warmboot_args + cbnz x0, trp_panic /* Failed to validate warmboot args */ + +1: + mov_imm x0, RMM_BOOT_COMPLETE + mov x1, xzr /* RMM_BOOT_SUCCESS */ + smc #0 + b trp_handler + +trp_panic: + no_ret plat_panic_handler + + /* + * Flag to mark if it is a cold boot. + * 1: cold boot, 0: warmboot. + */ +.align 3 +cold_boot_flag: + .dword 1 + + /* --------------------------------------------- + * Direct SMC call to BL31 service provided by + * RMM Dispatcher + * --------------------------------------------- + */ +func trp_smc + restore_args_call_smc + ret +endfunc trp_smc + + /* --------------------------------------------- + * RMI call handler + * --------------------------------------------- + */ +func trp_handler + /* + * Save Link Register and X4, as per SMCCC v1.2 its value + * must be preserved unless it contains result, as specified + * in the function definition. + */ + stp x4, lr, [sp, #-16]! + + /* + * Zero the space for X0-X3 in trp_smc_result structure + * and pass its address as the last argument. + */ + stp xzr, xzr, [sp, #-16]! + stp xzr, xzr, [sp, #-16]! + mov x7, sp + + bl trp_rmi_handler + + ldp x1, x2, [sp], #16 + ldp x3, x4, [sp], #16 + ldp x5, lr, [sp], #16 + + ldr x0, =RMM_RMI_REQ_COMPLETE + smc #0 + + b trp_handler +endfunc trp_handler diff --git a/services/std_svc/rmmd/trp/trp_helpers.c b/services/std_svc/rmmd/trp/trp_helpers.c new file mode 100644 index 0000000..159f3a5 --- /dev/null +++ b/services/std_svc/rmmd/trp/trp_helpers.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include <plat/common/platform.h> +#include <services/rmmd_svc.h> +#include "trp_private.h" + +/* + * Per cpu data structure to populate parameters for an SMC in C code and use + * a pointer to this structure in assembler code to populate x0-x7 + */ +static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT]; + +/* + * Set the arguments for SMC call + */ +trp_args_t *set_smc_args(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id; + trp_args_t *pcpu_smc_args; + + /* + * Return to Secure Monitor by raising an SMC. The results of the + * service are passed as an arguments to the SMC + */ + linear_id = plat_my_core_pos(); + pcpu_smc_args = &trp_smc_args[linear_id]; + write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0); + write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1); + write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2); + write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3); + write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4); + write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5); + write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6); + write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7); + + return pcpu_smc_args; +} + +/* + * Abort the boot process with the reason given in err. + */ +__dead2 void trp_boot_abort(uint64_t err) +{ + (void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0)); + panic(); +} diff --git a/services/std_svc/rmmd/trp/trp_main.c b/services/std_svc/rmmd/trp/trp_main.c new file mode 100644 index 0000000..33f2fb0 --- /dev/null +++ b/services/std_svc/rmmd/trp/trp_main.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <plat/common/platform.h> +#include <services/rmm_core_manifest.h> +#include <services/rmmd_svc.h> +#include <services/trp/platform_trp.h> +#include <trp_helpers.h> +#include "trp_private.h" + +#include <platform_def.h> + +/* Parameters received from the previous image */ +static unsigned int trp_boot_abi_version; +static uintptr_t trp_shared_region_start; + +/* Parameters received from boot manifest */ +uint32_t trp_boot_manifest_version; + +/******************************************************************************* + * Setup function for TRP. + ******************************************************************************/ +void trp_setup(uint64_t x0, + uint64_t x1, + uint64_t x2, + uint64_t x3) +{ + /* + * Validate boot parameters + * + * According to the Boot Interface ABI v.0.1, + * the parameters received from EL3 are: + * x0: CPUID (verified earlier, so not used) + * x1: Boot Interface version + * x2: PLATFORM_CORE_COUNT + * x3: Pointer to the shared memory area. + */ + + (void)x0; + + if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) { + trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH); + } + + if ((void *)x3 == NULL) { + trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER); + } + + if (x2 > TRP_PLATFORM_CORE_COUNT) { + trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE); + } + + trp_boot_abi_version = x1; + trp_shared_region_start = x3; + flush_dcache_range((uintptr_t)&trp_boot_abi_version, + sizeof(trp_boot_abi_version)); + flush_dcache_range((uintptr_t)&trp_shared_region_start, + sizeof(trp_shared_region_start)); + + /* Perform early platform-specific setup */ + trp_early_platform_setup((struct rmm_manifest *)trp_shared_region_start); +} + +int trp_validate_warmboot_args(uint64_t x0, uint64_t x1, + uint64_t x2, uint64_t x3) +{ + /* + * Validate boot parameters for warm boot + * + * According to the Boot Interface ABI v.0.1, the parameters + * received from EL3 during warm boot are: + * + * x0: CPUID (verified earlier so not used here) + * [x1:x3]: RES0 + */ + + (void)x0; + + return ((x1 | x2 | x3) == 0UL) ? 0 : E_RMM_BOOT_UNKNOWN; +} + +/* Main function for TRP */ +void trp_main(void) +{ + NOTICE("TRP: %s\n", version_string); + NOTICE("TRP: %s\n", build_message); + NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n", + TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR); + NOTICE("TRP: Boot Manifest Version: v.%u.%u\n", + RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version), + RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version)); + INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE); + INFO("TRP: Shared region base address: 0x%lx\n", + (unsigned long)trp_shared_region_start); + INFO("TRP: Total size: 0x%lx bytes\n", + (unsigned long)(RMM_END - RMM_BASE)); + INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n", + TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version), + TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version)); +} + +/******************************************************************************* + * Returning RMI version back to Normal World + ******************************************************************************/ +static void trp_ret_rmi_version(unsigned long long rmi_version, + struct trp_smc_result *smc_ret) +{ + if (rmi_version != RMI_ABI_VERSION) { + smc_ret->x[0] = RMI_ERROR_INPUT; + } else { + smc_ret->x[0] = RMI_SUCCESS; + } + VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, + RMI_ABI_VERSION_MINOR); + smc_ret->x[1] = RMI_ABI_VERSION; + smc_ret->x[2] = RMI_ABI_VERSION; +} + +/******************************************************************************* + * Transitioning granule of NON-SECURE type to REALM type + ******************************************************************************/ +static void trp_asc_mark_realm(unsigned long long x1, + struct trp_smc_result *smc_ret) +{ + VERBOSE("Delegating granule 0x%llx\n", x1); + smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1, + 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); + + if (smc_ret->x[0] != 0ULL) { + ERROR("Granule transition from NON-SECURE type to REALM type " + "failed 0x%llx\n", smc_ret->x[0]); + } +} + +/******************************************************************************* + * Transitioning granule of REALM type to NON-SECURE type + ******************************************************************************/ +static void trp_asc_mark_nonsecure(unsigned long long x1, + struct trp_smc_result *smc_ret) +{ + VERBOSE("Undelegating granule 0x%llx\n", x1); + smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1, + 0UL, 0UL, 0UL, 0UL, 0UL, 0UL)); + + if (smc_ret->x[0] != 0ULL) { + ERROR("Granule transition from REALM type to NON-SECURE type " + "failed 0x%llx\n", smc_ret->x[0]); + } +} + +/******************************************************************************* + * Main RMI SMC handler function + ******************************************************************************/ +void trp_rmi_handler(unsigned long fid, + unsigned long long x1, unsigned long long x2, + unsigned long long x3, unsigned long long x4, + unsigned long long x5, unsigned long long x6, + struct trp_smc_result *smc_ret) +{ + /* Not used in the current implementation */ + (void)x2; + (void)x3; + (void)x4; + (void)x5; + (void)x6; + + switch (fid) { + case RMI_RMM_REQ_VERSION: + trp_ret_rmi_version(x1, smc_ret); + break; + case RMI_RMM_GRANULE_DELEGATE: + trp_asc_mark_realm(x1, smc_ret); + break; + case RMI_RMM_GRANULE_UNDELEGATE: + trp_asc_mark_nonsecure(x1, smc_ret); + break; + default: + ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid); + smc_ret->x[0] = SMC_UNK; + } +} diff --git a/services/std_svc/rmmd/trp/trp_private.h b/services/std_svc/rmmd/trp/trp_private.h new file mode 100644 index 0000000..d8c6960 --- /dev/null +++ b/services/std_svc/rmmd/trp/trp_private.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRP_PRIVATE_H +#define TRP_PRIVATE_H + +#include <services/rmmd_svc.h> +#include <trp_helpers.h> + +/* Definitions for RMM-EL3 Interface ABI VERSION */ +#define TRP_RMM_EL3_ABI_VERS_MAJOR RMM_EL3_IFC_VERSION_MAJOR +#define TRP_RMM_EL3_ABI_VERS_MINOR RMM_EL3_IFC_VERSION_MINOR +#define TRP_RMM_EL3_ABI_VERS (((TRP_RMM_EL3_ABI_VERS_MAJOR & 0x7FFF) << 16) | \ + (TRP_RMM_EL3_ABI_VERS_MINOR & 0xFFFF)) + +#define TRP_PLATFORM_CORE_COUNT PLATFORM_CORE_COUNT + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +#define write_trp_arg(args, offset, val) (((args)->regs[offset >> 3]) \ + = val) +/* RMI SMC64 FIDs handled by the TRP */ +#define RMI_RMM_REQ_VERSION SMC64_RMI_FID(U(0)) +#define RMI_RMM_GRANULE_DELEGATE SMC64_RMI_FID(U(1)) +#define RMI_RMM_GRANULE_UNDELEGATE SMC64_RMI_FID(U(2)) + +/* Definitions for RMI VERSION */ +#define RMI_ABI_VERSION_MAJOR U(0x0) +#define RMI_ABI_VERSION_MINOR U(0x0) +#define RMI_ABI_VERSION (((RMI_ABI_VERSION_MAJOR & 0x7FFF) \ + << 16) | \ + (RMI_ABI_VERSION_MINOR & 0xFFFF)) + +#define TRP_RMM_EL3_VERSION_GET_MAJOR(x) \ + RMM_EL3_IFC_VERSION_GET_MAJOR((x)) +#define TRP_RMM_EL3_VERSION_GET_MINOR(x) \ + RMM_EL3_IFC_VERSION_GET_MAJOR_MINOR((x)) + +/* Helper to issue SMC calls to BL31 */ +uint64_t trp_smc(trp_args_t *); + +/* The main function to executed only by Primary CPU */ +void trp_main(void); + +/* Setup TRP. Executed only by Primary CPU */ +void trp_setup(uint64_t x0, + uint64_t x1, + uint64_t x2, + uint64_t x3); + +/* Validate arguments for warm boot only */ +int trp_validate_warmboot_args(uint64_t x0, uint64_t x1, + uint64_t x2, uint64_t x3); + +#endif /* __ASSEMBLER__ */ +#endif /* TRP_PRIVATE_H */ |