1 /* 2 * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <stdint.h> 9 10 #include <common/debug.h> 11 #include <common/runtime_svc.h> 12 #include <lib/el3_runtime/cpu_data.h> 13 #include <lib/pmf/pmf.h> 14 #include <lib/psci/psci.h> 15 #include <lib/runtime_instr.h> 16 #include <services/sdei.h> 17 #include <services/spm_svc.h> 18 #include <services/std_svc.h> 19 #include <smccc_helpers.h> 20 #include <tools_share/uuid.h> 21 22 /* Standard Service UUID */ 23 static uuid_t arm_svc_uid = { 24 {0x5b, 0x90, 0x8d, 0x10}, 25 {0x63, 0xf8}, 26 {0xe8, 0x47}, 27 0xae, 0x2d, 28 {0xc0, 0xfb, 0x56, 0x41, 0xf6, 0xe2} 29 }; 30 31 /* Setup Standard Services */ 32 static int32_t std_svc_setup(void) 33 { 34 uintptr_t svc_arg; 35 int ret = 0; 36 37 svc_arg = get_arm_std_svc_args(PSCI_FID_MASK); 38 assert(svc_arg); 39 40 /* 41 * PSCI is one of the specifications implemented as a Standard Service. 42 * The `psci_setup()` also does EL3 architectural setup. 43 */ 44 if (psci_setup((const psci_lib_args_t *)svc_arg) != PSCI_E_SUCCESS) { 45 ret = 1; 46 } 47 48 #if ENABLE_SPM 49 if (spm_setup() != 0) { 50 ret = 1; 51 } 52 #endif 53 54 #if SDEI_SUPPORT 55 /* SDEI initialisation */ 56 sdei_init(); 57 #endif 58 59 return ret; 60 } 61 62 /* 63 * Top-level Standard Service SMC handler. This handler will in turn dispatch 64 * calls to PSCI SMC handler 65 */ 66 static uintptr_t std_svc_smc_handler(uint32_t smc_fid, 67 u_register_t x1, 68 u_register_t x2, 69 u_register_t x3, 70 u_register_t x4, 71 void *cookie, 72 void *handle, 73 u_register_t flags) 74 { 75 /* 76 * Dispatch PSCI calls to PSCI SMC handler and return its return 77 * value 78 */ 79 if (is_psci_fid(smc_fid)) { 80 uint64_t ret; 81 82 #if ENABLE_RUNTIME_INSTRUMENTATION 83 84 /* 85 * Flush cache line so that even if CPU power down happens 86 * the timestamp update is reflected in memory. 87 */ 88 PMF_WRITE_TIMESTAMP(rt_instr_svc, 89 RT_INSTR_ENTER_PSCI, 90 PMF_CACHE_MAINT, 91 get_cpu_data(cpu_data_pmf_ts[CPU_DATA_PMF_TS0_IDX])); 92 #endif 93 94 ret = psci_smc_handler(smc_fid, x1, x2, x3, x4, 95 cookie, handle, flags); 96 97 #if ENABLE_RUNTIME_INSTRUMENTATION 98 PMF_CAPTURE_TIMESTAMP(rt_instr_svc, 99 RT_INSTR_EXIT_PSCI, 100 PMF_NO_CACHE_MAINT); 101 #endif 102 103 SMC_RET1(handle, ret); 104 } 105 106 #if ENABLE_SPM && SPM_DEPRECATED 107 /* 108 * Dispatch SPM calls to SPM SMC handler and return its return 109 * value 110 */ 111 if (is_spm_fid(smc_fid)) { 112 return spm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, 113 handle, flags); 114 } 115 #endif 116 117 #if SDEI_SUPPORT 118 if (is_sdei_fid(smc_fid)) { 119 return sdei_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, 120 flags); 121 } 122 #endif 123 124 switch (smc_fid) { 125 case ARM_STD_SVC_CALL_COUNT: 126 /* 127 * Return the number of Standard Service Calls. PSCI is the only 128 * standard service implemented; so return number of PSCI calls 129 */ 130 SMC_RET1(handle, PSCI_NUM_CALLS); 131 132 case ARM_STD_SVC_UID: 133 /* Return UID to the caller */ 134 SMC_UUID_RET(handle, arm_svc_uid); 135 136 case ARM_STD_SVC_VERSION: 137 /* Return the version of current implementation */ 138 SMC_RET2(handle, STD_SVC_VERSION_MAJOR, STD_SVC_VERSION_MINOR); 139 140 default: 141 WARN("Unimplemented Standard Service Call: 0x%x \n", smc_fid); 142 SMC_RET1(handle, SMC_UNK); 143 } 144 } 145 146 /* Register Standard Service Calls as runtime service */ 147 DECLARE_RT_SVC( 148 std_svc, 149 150 OEN_STD_START, 151 OEN_STD_END, 152 SMC_TYPE_FAST, 153 std_svc_setup, 154 std_svc_smc_handler 155 ); 156