1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <stdint.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <common/debug.h> 11*91f16700Schasinglulu #include <common/runtime_svc.h> 12*91f16700Schasinglulu #include <lib/el3_runtime/cpu_data.h> 13*91f16700Schasinglulu #include <lib/pmf/pmf.h> 14*91f16700Schasinglulu #include <lib/psci/psci.h> 15*91f16700Schasinglulu #include <lib/runtime_instr.h> 16*91f16700Schasinglulu #include <services/drtm_svc.h> 17*91f16700Schasinglulu #include <services/errata_abi_svc.h> 18*91f16700Schasinglulu #include <services/pci_svc.h> 19*91f16700Schasinglulu #include <services/rmmd_svc.h> 20*91f16700Schasinglulu #include <services/sdei.h> 21*91f16700Schasinglulu #include <services/spm_mm_svc.h> 22*91f16700Schasinglulu #include <services/spmc_svc.h> 23*91f16700Schasinglulu #include <services/spmd_svc.h> 24*91f16700Schasinglulu #include <services/std_svc.h> 25*91f16700Schasinglulu #include <services/trng_svc.h> 26*91f16700Schasinglulu #include <smccc_helpers.h> 27*91f16700Schasinglulu #include <tools_share/uuid.h> 28*91f16700Schasinglulu 29*91f16700Schasinglulu /* Standard Service UUID */ 30*91f16700Schasinglulu static uuid_t arm_svc_uid = { 31*91f16700Schasinglulu {0x5b, 0x90, 0x8d, 0x10}, 32*91f16700Schasinglulu {0x63, 0xf8}, 33*91f16700Schasinglulu {0xe8, 0x47}, 34*91f16700Schasinglulu 0xae, 0x2d, 35*91f16700Schasinglulu {0xc0, 0xfb, 0x56, 0x41, 0xf6, 0xe2} 36*91f16700Schasinglulu }; 37*91f16700Schasinglulu 38*91f16700Schasinglulu /* Setup Standard Services */ 39*91f16700Schasinglulu static int32_t std_svc_setup(void) 40*91f16700Schasinglulu { 41*91f16700Schasinglulu uintptr_t svc_arg; 42*91f16700Schasinglulu int ret = 0; 43*91f16700Schasinglulu 44*91f16700Schasinglulu svc_arg = get_arm_std_svc_args(PSCI_FID_MASK); 45*91f16700Schasinglulu assert(svc_arg); 46*91f16700Schasinglulu 47*91f16700Schasinglulu /* 48*91f16700Schasinglulu * PSCI is one of the specifications implemented as a Standard Service. 49*91f16700Schasinglulu * The `psci_setup()` also does EL3 architectural setup. 50*91f16700Schasinglulu */ 51*91f16700Schasinglulu if (psci_setup((const psci_lib_args_t *)svc_arg) != PSCI_E_SUCCESS) { 52*91f16700Schasinglulu ret = 1; 53*91f16700Schasinglulu } 54*91f16700Schasinglulu 55*91f16700Schasinglulu #if SPM_MM 56*91f16700Schasinglulu if (spm_mm_setup() != 0) { 57*91f16700Schasinglulu ret = 1; 58*91f16700Schasinglulu } 59*91f16700Schasinglulu #endif 60*91f16700Schasinglulu 61*91f16700Schasinglulu #if defined(SPD_spmd) 62*91f16700Schasinglulu if (spmd_setup() != 0) { 63*91f16700Schasinglulu ret = 1; 64*91f16700Schasinglulu } 65*91f16700Schasinglulu #endif 66*91f16700Schasinglulu 67*91f16700Schasinglulu #if ENABLE_RME 68*91f16700Schasinglulu if (rmmd_setup() != 0) { 69*91f16700Schasinglulu ret = 1; 70*91f16700Schasinglulu } 71*91f16700Schasinglulu #endif 72*91f16700Schasinglulu 73*91f16700Schasinglulu #if SDEI_SUPPORT 74*91f16700Schasinglulu /* SDEI initialisation */ 75*91f16700Schasinglulu sdei_init(); 76*91f16700Schasinglulu #endif 77*91f16700Schasinglulu 78*91f16700Schasinglulu #if TRNG_SUPPORT 79*91f16700Schasinglulu /* TRNG initialisation */ 80*91f16700Schasinglulu trng_setup(); 81*91f16700Schasinglulu #endif /* TRNG_SUPPORT */ 82*91f16700Schasinglulu 83*91f16700Schasinglulu #if DRTM_SUPPORT 84*91f16700Schasinglulu if (drtm_setup() != 0) { 85*91f16700Schasinglulu ret = 1; 86*91f16700Schasinglulu } 87*91f16700Schasinglulu #endif /* DRTM_SUPPORT */ 88*91f16700Schasinglulu 89*91f16700Schasinglulu return ret; 90*91f16700Schasinglulu } 91*91f16700Schasinglulu 92*91f16700Schasinglulu /* 93*91f16700Schasinglulu * Top-level Standard Service SMC handler. This handler will in turn dispatch 94*91f16700Schasinglulu * calls to PSCI SMC handler 95*91f16700Schasinglulu */ 96*91f16700Schasinglulu static uintptr_t std_svc_smc_handler(uint32_t smc_fid, 97*91f16700Schasinglulu u_register_t x1, 98*91f16700Schasinglulu u_register_t x2, 99*91f16700Schasinglulu u_register_t x3, 100*91f16700Schasinglulu u_register_t x4, 101*91f16700Schasinglulu void *cookie, 102*91f16700Schasinglulu void *handle, 103*91f16700Schasinglulu u_register_t flags) 104*91f16700Schasinglulu { 105*91f16700Schasinglulu if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { 106*91f16700Schasinglulu /* 32-bit SMC function, clear top parameter bits */ 107*91f16700Schasinglulu 108*91f16700Schasinglulu x1 &= UINT32_MAX; 109*91f16700Schasinglulu x2 &= UINT32_MAX; 110*91f16700Schasinglulu x3 &= UINT32_MAX; 111*91f16700Schasinglulu x4 &= UINT32_MAX; 112*91f16700Schasinglulu } 113*91f16700Schasinglulu 114*91f16700Schasinglulu /* 115*91f16700Schasinglulu * Dispatch PSCI calls to PSCI SMC handler and return its return 116*91f16700Schasinglulu * value 117*91f16700Schasinglulu */ 118*91f16700Schasinglulu if (is_psci_fid(smc_fid)) { 119*91f16700Schasinglulu uint64_t ret; 120*91f16700Schasinglulu 121*91f16700Schasinglulu #if ENABLE_RUNTIME_INSTRUMENTATION 122*91f16700Schasinglulu 123*91f16700Schasinglulu /* 124*91f16700Schasinglulu * Flush cache line so that even if CPU power down happens 125*91f16700Schasinglulu * the timestamp update is reflected in memory. 126*91f16700Schasinglulu */ 127*91f16700Schasinglulu PMF_WRITE_TIMESTAMP(rt_instr_svc, 128*91f16700Schasinglulu RT_INSTR_ENTER_PSCI, 129*91f16700Schasinglulu PMF_CACHE_MAINT, 130*91f16700Schasinglulu get_cpu_data(cpu_data_pmf_ts[CPU_DATA_PMF_TS0_IDX])); 131*91f16700Schasinglulu #endif 132*91f16700Schasinglulu 133*91f16700Schasinglulu ret = psci_smc_handler(smc_fid, x1, x2, x3, x4, 134*91f16700Schasinglulu cookie, handle, flags); 135*91f16700Schasinglulu 136*91f16700Schasinglulu #if ENABLE_RUNTIME_INSTRUMENTATION 137*91f16700Schasinglulu PMF_CAPTURE_TIMESTAMP(rt_instr_svc, 138*91f16700Schasinglulu RT_INSTR_EXIT_PSCI, 139*91f16700Schasinglulu PMF_NO_CACHE_MAINT); 140*91f16700Schasinglulu #endif 141*91f16700Schasinglulu 142*91f16700Schasinglulu SMC_RET1(handle, ret); 143*91f16700Schasinglulu } 144*91f16700Schasinglulu 145*91f16700Schasinglulu #if SPM_MM 146*91f16700Schasinglulu /* 147*91f16700Schasinglulu * Dispatch SPM calls to SPM SMC handler and return its return 148*91f16700Schasinglulu * value 149*91f16700Schasinglulu */ 150*91f16700Schasinglulu if (is_spm_mm_fid(smc_fid)) { 151*91f16700Schasinglulu return spm_mm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, 152*91f16700Schasinglulu handle, flags); 153*91f16700Schasinglulu } 154*91f16700Schasinglulu #endif 155*91f16700Schasinglulu 156*91f16700Schasinglulu #if defined(SPD_spmd) 157*91f16700Schasinglulu /* 158*91f16700Schasinglulu * Dispatch FFA calls to the FFA SMC handler implemented by the SPM 159*91f16700Schasinglulu * dispatcher and return its return value 160*91f16700Schasinglulu */ 161*91f16700Schasinglulu if (is_ffa_fid(smc_fid)) { 162*91f16700Schasinglulu return spmd_ffa_smc_handler(smc_fid, x1, x2, x3, x4, cookie, 163*91f16700Schasinglulu handle, flags); 164*91f16700Schasinglulu } 165*91f16700Schasinglulu #endif 166*91f16700Schasinglulu 167*91f16700Schasinglulu #if SDEI_SUPPORT 168*91f16700Schasinglulu if (is_sdei_fid(smc_fid)) { 169*91f16700Schasinglulu return sdei_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, 170*91f16700Schasinglulu flags); 171*91f16700Schasinglulu } 172*91f16700Schasinglulu #endif 173*91f16700Schasinglulu 174*91f16700Schasinglulu #if TRNG_SUPPORT 175*91f16700Schasinglulu if (is_trng_fid(smc_fid)) { 176*91f16700Schasinglulu return trng_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, 177*91f16700Schasinglulu flags); 178*91f16700Schasinglulu } 179*91f16700Schasinglulu #endif /* TRNG_SUPPORT */ 180*91f16700Schasinglulu 181*91f16700Schasinglulu #if ERRATA_ABI_SUPPORT 182*91f16700Schasinglulu if (is_errata_fid(smc_fid)) { 183*91f16700Schasinglulu return errata_abi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, 184*91f16700Schasinglulu handle, flags); 185*91f16700Schasinglulu } 186*91f16700Schasinglulu #endif /* ERRATA_ABI_SUPPORT */ 187*91f16700Schasinglulu 188*91f16700Schasinglulu #if ENABLE_RME 189*91f16700Schasinglulu 190*91f16700Schasinglulu if (is_rmmd_el3_fid(smc_fid)) { 191*91f16700Schasinglulu return rmmd_rmm_el3_handler(smc_fid, x1, x2, x3, x4, cookie, 192*91f16700Schasinglulu handle, flags); 193*91f16700Schasinglulu } 194*91f16700Schasinglulu 195*91f16700Schasinglulu if (is_rmi_fid(smc_fid)) { 196*91f16700Schasinglulu return rmmd_rmi_handler(smc_fid, x1, x2, x3, x4, cookie, 197*91f16700Schasinglulu handle, flags); 198*91f16700Schasinglulu } 199*91f16700Schasinglulu #endif 200*91f16700Schasinglulu 201*91f16700Schasinglulu #if SMC_PCI_SUPPORT 202*91f16700Schasinglulu if (is_pci_fid(smc_fid)) { 203*91f16700Schasinglulu return pci_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, 204*91f16700Schasinglulu flags); 205*91f16700Schasinglulu } 206*91f16700Schasinglulu #endif 207*91f16700Schasinglulu 208*91f16700Schasinglulu #if DRTM_SUPPORT 209*91f16700Schasinglulu if (is_drtm_fid(smc_fid)) { 210*91f16700Schasinglulu return drtm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, 211*91f16700Schasinglulu flags); 212*91f16700Schasinglulu } 213*91f16700Schasinglulu #endif /* DRTM_SUPPORT */ 214*91f16700Schasinglulu 215*91f16700Schasinglulu switch (smc_fid) { 216*91f16700Schasinglulu case ARM_STD_SVC_CALL_COUNT: 217*91f16700Schasinglulu /* 218*91f16700Schasinglulu * Return the number of Standard Service Calls. PSCI is the only 219*91f16700Schasinglulu * standard service implemented; so return number of PSCI calls 220*91f16700Schasinglulu */ 221*91f16700Schasinglulu SMC_RET1(handle, PSCI_NUM_CALLS); 222*91f16700Schasinglulu 223*91f16700Schasinglulu case ARM_STD_SVC_UID: 224*91f16700Schasinglulu /* Return UID to the caller */ 225*91f16700Schasinglulu SMC_UUID_RET(handle, arm_svc_uid); 226*91f16700Schasinglulu 227*91f16700Schasinglulu case ARM_STD_SVC_VERSION: 228*91f16700Schasinglulu /* Return the version of current implementation */ 229*91f16700Schasinglulu SMC_RET2(handle, STD_SVC_VERSION_MAJOR, STD_SVC_VERSION_MINOR); 230*91f16700Schasinglulu 231*91f16700Schasinglulu default: 232*91f16700Schasinglulu VERBOSE("Unimplemented Standard Service Call: 0x%x \n", smc_fid); 233*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 234*91f16700Schasinglulu } 235*91f16700Schasinglulu } 236*91f16700Schasinglulu 237*91f16700Schasinglulu /* Register Standard Service Calls as runtime service */ 238*91f16700Schasinglulu DECLARE_RT_SVC( 239*91f16700Schasinglulu std_svc, 240*91f16700Schasinglulu 241*91f16700Schasinglulu OEN_STD_START, 242*91f16700Schasinglulu OEN_STD_END, 243*91f16700Schasinglulu SMC_TYPE_FAST, 244*91f16700Schasinglulu std_svc_setup, 245*91f16700Schasinglulu std_svc_smc_handler 246*91f16700Schasinglulu ); 247