150a3056aSZelalem Aweke /* 2319fb084SSoby Mathew * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. 350a3056aSZelalem Aweke * 450a3056aSZelalem Aweke * SPDX-License-Identifier: BSD-3-Clause 550a3056aSZelalem Aweke */ 650a3056aSZelalem Aweke 750a3056aSZelalem Aweke 850a3056aSZelalem Aweke #include <common/debug.h> 950a3056aSZelalem Aweke #include <plat/common/platform.h> 10319fb084SSoby Mathew #include <services/rmmd_svc.h> 1150a3056aSZelalem Aweke #include <services/trp/platform_trp.h> 1250a3056aSZelalem Aweke 1350a3056aSZelalem Aweke #include <platform_def.h> 1450a3056aSZelalem Aweke #include "trp_private.h" 1550a3056aSZelalem Aweke 16*8c980a4aSJavier Almansa Sobrino /* Parameters received from the previous image */ 17*8c980a4aSJavier Almansa Sobrino static unsigned int trp_boot_abi_version; 18*8c980a4aSJavier Almansa Sobrino static uintptr_t trp_shared_region_start; 19*8c980a4aSJavier Almansa Sobrino 2050a3056aSZelalem Aweke /******************************************************************************* 2150a3056aSZelalem Aweke * Per cpu data structure to populate parameters for an SMC in C code and use 2250a3056aSZelalem Aweke * a pointer to this structure in assembler code to populate x0-x7 2350a3056aSZelalem Aweke ******************************************************************************/ 2450a3056aSZelalem Aweke static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT]; 2550a3056aSZelalem Aweke 2650a3056aSZelalem Aweke /******************************************************************************* 2750a3056aSZelalem Aweke * Set the arguments for SMC call 2850a3056aSZelalem Aweke ******************************************************************************/ 2950a3056aSZelalem Aweke static trp_args_t *set_smc_args(uint64_t arg0, 3050a3056aSZelalem Aweke uint64_t arg1, 3150a3056aSZelalem Aweke uint64_t arg2, 3250a3056aSZelalem Aweke uint64_t arg3, 3350a3056aSZelalem Aweke uint64_t arg4, 3450a3056aSZelalem Aweke uint64_t arg5, 3550a3056aSZelalem Aweke uint64_t arg6, 3650a3056aSZelalem Aweke uint64_t arg7) 3750a3056aSZelalem Aweke { 3850a3056aSZelalem Aweke uint32_t linear_id; 3950a3056aSZelalem Aweke trp_args_t *pcpu_smc_args; 4050a3056aSZelalem Aweke 4150a3056aSZelalem Aweke /* 4250a3056aSZelalem Aweke * Return to Secure Monitor by raising an SMC. The results of the 4350a3056aSZelalem Aweke * service are passed as an arguments to the SMC 4450a3056aSZelalem Aweke */ 4550a3056aSZelalem Aweke linear_id = plat_my_core_pos(); 4650a3056aSZelalem Aweke pcpu_smc_args = &trp_smc_args[linear_id]; 4750a3056aSZelalem Aweke write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0); 4850a3056aSZelalem Aweke write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1); 4950a3056aSZelalem Aweke write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2); 5050a3056aSZelalem Aweke write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3); 5150a3056aSZelalem Aweke write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4); 5250a3056aSZelalem Aweke write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5); 5350a3056aSZelalem Aweke write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6); 5450a3056aSZelalem Aweke write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7); 5550a3056aSZelalem Aweke 5650a3056aSZelalem Aweke return pcpu_smc_args; 5750a3056aSZelalem Aweke } 5850a3056aSZelalem Aweke 59*8c980a4aSJavier Almansa Sobrino /* 60*8c980a4aSJavier Almansa Sobrino * Abort the boot process with the reason given in err. 61*8c980a4aSJavier Almansa Sobrino */ 62*8c980a4aSJavier Almansa Sobrino __dead2 static void trp_boot_abort(uint64_t err) 63*8c980a4aSJavier Almansa Sobrino { 64*8c980a4aSJavier Almansa Sobrino (void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0)); 65*8c980a4aSJavier Almansa Sobrino panic(); 66*8c980a4aSJavier Almansa Sobrino } 67*8c980a4aSJavier Almansa Sobrino 6850a3056aSZelalem Aweke /******************************************************************************* 6950a3056aSZelalem Aweke * Setup function for TRP. 7050a3056aSZelalem Aweke ******************************************************************************/ 71*8c980a4aSJavier Almansa Sobrino void trp_setup(uint64_t x0, 72*8c980a4aSJavier Almansa Sobrino uint64_t x1, 73*8c980a4aSJavier Almansa Sobrino uint64_t x2, 74*8c980a4aSJavier Almansa Sobrino uint64_t x3) 7550a3056aSZelalem Aweke { 76*8c980a4aSJavier Almansa Sobrino /* 77*8c980a4aSJavier Almansa Sobrino * Validate boot parameters. 78*8c980a4aSJavier Almansa Sobrino * 79*8c980a4aSJavier Almansa Sobrino * According to the Boot Interface ABI v.0.1, the 80*8c980a4aSJavier Almansa Sobrino * parameters recived from EL3 are: 81*8c980a4aSJavier Almansa Sobrino * x0: CPUID (verified earlier so not used) 82*8c980a4aSJavier Almansa Sobrino * x1: Boot Interface version 83*8c980a4aSJavier Almansa Sobrino * x2: PLATFORM_CORE_COUNT 84*8c980a4aSJavier Almansa Sobrino * x3: Pointer to the shared memory area. 85*8c980a4aSJavier Almansa Sobrino */ 86*8c980a4aSJavier Almansa Sobrino 87*8c980a4aSJavier Almansa Sobrino (void)x0; 88*8c980a4aSJavier Almansa Sobrino 89*8c980a4aSJavier Almansa Sobrino if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) { 90*8c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH); 91*8c980a4aSJavier Almansa Sobrino } 92*8c980a4aSJavier Almansa Sobrino 93*8c980a4aSJavier Almansa Sobrino if ((void *)x3 == NULL) { 94*8c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER); 95*8c980a4aSJavier Almansa Sobrino } 96*8c980a4aSJavier Almansa Sobrino 97*8c980a4aSJavier Almansa Sobrino if (x2 > TRP_PLATFORM_CORE_COUNT) { 98*8c980a4aSJavier Almansa Sobrino trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE); 99*8c980a4aSJavier Almansa Sobrino } 100*8c980a4aSJavier Almansa Sobrino 101*8c980a4aSJavier Almansa Sobrino trp_boot_abi_version = x1; 102*8c980a4aSJavier Almansa Sobrino trp_shared_region_start = x3; 103*8c980a4aSJavier Almansa Sobrino flush_dcache_range((uintptr_t)&trp_boot_abi_version, 104*8c980a4aSJavier Almansa Sobrino sizeof(trp_boot_abi_version)); 105*8c980a4aSJavier Almansa Sobrino flush_dcache_range((uintptr_t)&trp_shared_region_start, 106*8c980a4aSJavier Almansa Sobrino sizeof(trp_shared_region_start)); 107*8c980a4aSJavier Almansa Sobrino 10850a3056aSZelalem Aweke /* Perform early platform-specific setup */ 10950a3056aSZelalem Aweke trp_early_platform_setup(); 11050a3056aSZelalem Aweke } 11150a3056aSZelalem Aweke 11250a3056aSZelalem Aweke /* Main function for TRP */ 11350a3056aSZelalem Aweke void trp_main(void) 11450a3056aSZelalem Aweke { 11550a3056aSZelalem Aweke NOTICE("TRP: %s\n", version_string); 11650a3056aSZelalem Aweke NOTICE("TRP: %s\n", build_message); 117*8c980a4aSJavier Almansa Sobrino NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n", 118*8c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR); 11950a3056aSZelalem Aweke INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE); 120*8c980a4aSJavier Almansa Sobrino INFO("TRP: Base address for the shared region : 0x%lx\n", 121*8c980a4aSJavier Almansa Sobrino (unsigned long)trp_shared_region_start); 12250a3056aSZelalem Aweke INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END 12350a3056aSZelalem Aweke - RMM_BASE)); 124*8c980a4aSJavier Almansa Sobrino INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n", 125*8c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version), 126*8c980a4aSJavier Almansa Sobrino TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version)); 12750a3056aSZelalem Aweke } 12850a3056aSZelalem Aweke 12950a3056aSZelalem Aweke /******************************************************************************* 13050a3056aSZelalem Aweke * Returning RMI version back to Normal World 13150a3056aSZelalem Aweke ******************************************************************************/ 13250a3056aSZelalem Aweke static trp_args_t *trp_ret_rmi_version(void) 13350a3056aSZelalem Aweke { 13450a3056aSZelalem Aweke VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, 13550a3056aSZelalem Aweke RMI_ABI_VERSION_MINOR); 136319fb084SSoby Mathew return set_smc_args(RMMD_RMI_REQ_COMPLETE, RMI_ABI_VERSION, 13750a3056aSZelalem Aweke 0, 0, 0, 0, 0, 0); 13850a3056aSZelalem Aweke } 13950a3056aSZelalem Aweke 14050a3056aSZelalem Aweke /******************************************************************************* 14150a3056aSZelalem Aweke * Transitioning granule of NON-SECURE type to REALM type 14250a3056aSZelalem Aweke ******************************************************************************/ 14350a3056aSZelalem Aweke static trp_args_t *trp_asc_mark_realm(unsigned long long x1) 14450a3056aSZelalem Aweke { 14550a3056aSZelalem Aweke unsigned long long ret; 14650a3056aSZelalem Aweke 14750a3056aSZelalem Aweke VERBOSE("Delegating granule 0x%llx\n", x1); 148319fb084SSoby Mathew ret = trp_smc(set_smc_args(RMMD_GTSI_DELEGATE, x1, 0, 0, 0, 0, 0, 0)); 14950a3056aSZelalem Aweke 15050a3056aSZelalem Aweke if (ret != 0ULL) { 15150a3056aSZelalem Aweke ERROR("Granule transition from NON-SECURE type to REALM type " 15250a3056aSZelalem Aweke "failed 0x%llx\n", ret); 15350a3056aSZelalem Aweke } 154319fb084SSoby Mathew return set_smc_args(RMMD_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0); 15550a3056aSZelalem Aweke } 15650a3056aSZelalem Aweke 15750a3056aSZelalem Aweke /******************************************************************************* 15850a3056aSZelalem Aweke * Transitioning granule of REALM type to NON-SECURE type 15950a3056aSZelalem Aweke ******************************************************************************/ 16050a3056aSZelalem Aweke static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1) 16150a3056aSZelalem Aweke { 16250a3056aSZelalem Aweke unsigned long long ret; 16350a3056aSZelalem Aweke 16450a3056aSZelalem Aweke VERBOSE("Undelegating granule 0x%llx\n", x1); 165319fb084SSoby Mathew ret = trp_smc(set_smc_args(RMMD_GTSI_UNDELEGATE, x1, 0, 0, 0, 0, 0, 0)); 16650a3056aSZelalem Aweke 16750a3056aSZelalem Aweke if (ret != 0ULL) { 16850a3056aSZelalem Aweke ERROR("Granule transition from REALM type to NON-SECURE type " 16950a3056aSZelalem Aweke "failed 0x%llx\n", ret); 17050a3056aSZelalem Aweke } 171319fb084SSoby Mathew return set_smc_args(RMMD_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0); 17250a3056aSZelalem Aweke } 17350a3056aSZelalem Aweke 17450a3056aSZelalem Aweke /******************************************************************************* 17550a3056aSZelalem Aweke * Main RMI SMC handler function 17650a3056aSZelalem Aweke ******************************************************************************/ 17750a3056aSZelalem Aweke trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1) 17850a3056aSZelalem Aweke { 17950a3056aSZelalem Aweke switch (fid) { 18050a3056aSZelalem Aweke case RMI_RMM_REQ_VERSION: 18150a3056aSZelalem Aweke return trp_ret_rmi_version(); 18250a3056aSZelalem Aweke case RMI_RMM_GRANULE_DELEGATE: 18350a3056aSZelalem Aweke return trp_asc_mark_realm(x1); 18450a3056aSZelalem Aweke case RMI_RMM_GRANULE_UNDELEGATE: 18550a3056aSZelalem Aweke return trp_asc_mark_nonsecure(x1); 18650a3056aSZelalem Aweke default: 18750a3056aSZelalem Aweke ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid); 18850a3056aSZelalem Aweke } 18950a3056aSZelalem Aweke return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0); 19050a3056aSZelalem Aweke } 191