1 /* 2 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 8 #include <common/debug.h> 9 #include <plat/common/platform.h> 10 #include <services/rmmd_svc.h> 11 #include <services/trp/platform_trp.h> 12 13 #include <platform_def.h> 14 #include "trp_private.h" 15 16 /* Parameters received from the previous image */ 17 static unsigned int trp_boot_abi_version; 18 static uintptr_t trp_shared_region_start; 19 20 /******************************************************************************* 21 * Per cpu data structure to populate parameters for an SMC in C code and use 22 * a pointer to this structure in assembler code to populate x0-x7 23 ******************************************************************************/ 24 static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT]; 25 26 /******************************************************************************* 27 * Set the arguments for SMC call 28 ******************************************************************************/ 29 static trp_args_t *set_smc_args(uint64_t arg0, 30 uint64_t arg1, 31 uint64_t arg2, 32 uint64_t arg3, 33 uint64_t arg4, 34 uint64_t arg5, 35 uint64_t arg6, 36 uint64_t arg7) 37 { 38 uint32_t linear_id; 39 trp_args_t *pcpu_smc_args; 40 41 /* 42 * Return to Secure Monitor by raising an SMC. The results of the 43 * service are passed as an arguments to the SMC 44 */ 45 linear_id = plat_my_core_pos(); 46 pcpu_smc_args = &trp_smc_args[linear_id]; 47 write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0); 48 write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1); 49 write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2); 50 write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3); 51 write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4); 52 write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5); 53 write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6); 54 write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7); 55 56 return pcpu_smc_args; 57 } 58 59 /* 60 * Abort the boot process with the reason given in err. 61 */ 62 __dead2 static void trp_boot_abort(uint64_t err) 63 { 64 (void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0)); 65 panic(); 66 } 67 68 /******************************************************************************* 69 * Setup function for TRP. 70 ******************************************************************************/ 71 void trp_setup(uint64_t x0, 72 uint64_t x1, 73 uint64_t x2, 74 uint64_t x3) 75 { 76 /* 77 * Validate boot parameters. 78 * 79 * According to the Boot Interface ABI v.0.1, the 80 * parameters recived from EL3 are: 81 * x0: CPUID (verified earlier so not used) 82 * x1: Boot Interface version 83 * x2: PLATFORM_CORE_COUNT 84 * x3: Pointer to the shared memory area. 85 */ 86 87 (void)x0; 88 89 if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) { 90 trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH); 91 } 92 93 if ((void *)x3 == NULL) { 94 trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER); 95 } 96 97 if (x2 > TRP_PLATFORM_CORE_COUNT) { 98 trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE); 99 } 100 101 trp_boot_abi_version = x1; 102 trp_shared_region_start = x3; 103 flush_dcache_range((uintptr_t)&trp_boot_abi_version, 104 sizeof(trp_boot_abi_version)); 105 flush_dcache_range((uintptr_t)&trp_shared_region_start, 106 sizeof(trp_shared_region_start)); 107 108 /* Perform early platform-specific setup */ 109 trp_early_platform_setup(); 110 } 111 112 /* Main function for TRP */ 113 void trp_main(void) 114 { 115 NOTICE("TRP: %s\n", version_string); 116 NOTICE("TRP: %s\n", build_message); 117 NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n", 118 TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR); 119 INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE); 120 INFO("TRP: Base address for the shared region : 0x%lx\n", 121 (unsigned long)trp_shared_region_start); 122 INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END 123 - RMM_BASE)); 124 INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n", 125 TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version), 126 TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version)); 127 } 128 129 /******************************************************************************* 130 * Returning RMI version back to Normal World 131 ******************************************************************************/ 132 static trp_args_t *trp_ret_rmi_version(void) 133 { 134 VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, 135 RMI_ABI_VERSION_MINOR); 136 return set_smc_args(RMMD_RMI_REQ_COMPLETE, RMI_ABI_VERSION, 137 0, 0, 0, 0, 0, 0); 138 } 139 140 /******************************************************************************* 141 * Transitioning granule of NON-SECURE type to REALM type 142 ******************************************************************************/ 143 static trp_args_t *trp_asc_mark_realm(unsigned long long x1) 144 { 145 unsigned long long ret; 146 147 VERBOSE("Delegating granule 0x%llx\n", x1); 148 ret = trp_smc(set_smc_args(RMMD_GTSI_DELEGATE, x1, 0, 0, 0, 0, 0, 0)); 149 150 if (ret != 0ULL) { 151 ERROR("Granule transition from NON-SECURE type to REALM type " 152 "failed 0x%llx\n", ret); 153 } 154 return set_smc_args(RMMD_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0); 155 } 156 157 /******************************************************************************* 158 * Transitioning granule of REALM type to NON-SECURE type 159 ******************************************************************************/ 160 static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1) 161 { 162 unsigned long long ret; 163 164 VERBOSE("Undelegating granule 0x%llx\n", x1); 165 ret = trp_smc(set_smc_args(RMMD_GTSI_UNDELEGATE, x1, 0, 0, 0, 0, 0, 0)); 166 167 if (ret != 0ULL) { 168 ERROR("Granule transition from REALM type to NON-SECURE type " 169 "failed 0x%llx\n", ret); 170 } 171 return set_smc_args(RMMD_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0); 172 } 173 174 /******************************************************************************* 175 * Main RMI SMC handler function 176 ******************************************************************************/ 177 trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1) 178 { 179 switch (fid) { 180 case RMI_RMM_REQ_VERSION: 181 return trp_ret_rmi_version(); 182 case RMI_RMM_GRANULE_DELEGATE: 183 return trp_asc_mark_realm(x1); 184 case RMI_RMM_GRANULE_UNDELEGATE: 185 return trp_asc_mark_nonsecure(x1); 186 default: 187 ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid); 188 } 189 return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0); 190 } 191