1532ed618SSoby Mathew /* 27fabe1a8SRoberto Vargas * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. 3532ed618SSoby Mathew * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5532ed618SSoby Mathew */ 6532ed618SSoby Mathew 7*e02f469fSSathees Balya #ifndef RUNTIME_SVC_H 8*e02f469fSSathees Balya #define RUNTIME_SVC_H 9532ed618SSoby Mathew 10532ed618SSoby Mathew #include <bl_common.h> /* to include exception types */ 112f370465SAntonio Nino Diaz #include <cassert.h> 12085e80ecSAntonio Nino Diaz #include <smccc_helpers.h> /* to include SMCCC definitions */ 132f370465SAntonio Nino Diaz #include <utils_def.h> 14532ed618SSoby Mathew 15532ed618SSoby Mathew /******************************************************************************* 16532ed618SSoby Mathew * Structure definition, typedefs & constants for the runtime service framework 17532ed618SSoby Mathew ******************************************************************************/ 18532ed618SSoby Mathew 19532ed618SSoby Mathew /* 20532ed618SSoby Mathew * Constants to allow the assembler access a runtime service 21532ed618SSoby Mathew * descriptor 22532ed618SSoby Mathew */ 231ae0a49aSSoby Mathew #ifdef AARCH32 2481542c00SAntonio Nino Diaz #define RT_SVC_SIZE_LOG2 U(4) 2581542c00SAntonio Nino Diaz #define RT_SVC_DESC_INIT U(8) 2681542c00SAntonio Nino Diaz #define RT_SVC_DESC_HANDLE U(12) 271ae0a49aSSoby Mathew #else 2881542c00SAntonio Nino Diaz #define RT_SVC_SIZE_LOG2 U(5) 2981542c00SAntonio Nino Diaz #define RT_SVC_DESC_INIT U(16) 3081542c00SAntonio Nino Diaz #define RT_SVC_DESC_HANDLE U(24) 311ae0a49aSSoby Mathew #endif /* AARCH32 */ 3281542c00SAntonio Nino Diaz #define SIZEOF_RT_SVC_DESC (U(1) << RT_SVC_SIZE_LOG2) 331ae0a49aSSoby Mathew 34532ed618SSoby Mathew 35532ed618SSoby Mathew /* 362f370465SAntonio Nino Diaz * In SMCCC 1.X, the function identifier has 6 bits for the owning entity number 372f370465SAntonio Nino Diaz * and a single bit for the type of smc call. When taken together, those values 382f370465SAntonio Nino Diaz * limit the maximum number of runtime services to 128. 392f370465SAntonio Nino Diaz * 402f370465SAntonio Nino Diaz * In SMCCC 2.X the type bit is always 1 and there are only 4 OEN bits in the 412f370465SAntonio Nino Diaz * compatibility namespace, so the total number of services is 16. The LSB of 422f370465SAntonio Nino Diaz * namespace is also added to these 4 bits to make space for the vendor service 432f370465SAntonio Nino Diaz * handler and so the total number of runtime services is 32. 44532ed618SSoby Mathew */ 452f370465SAntonio Nino Diaz #if SMCCC_MAJOR_VERSION == 1 4681542c00SAntonio Nino Diaz #define MAX_RT_SVCS U(128) 472f370465SAntonio Nino Diaz #elif SMCCC_MAJOR_VERSION == 2 4881542c00SAntonio Nino Diaz #define MAX_RT_SVCS U(32) 492f370465SAntonio Nino Diaz #endif 50532ed618SSoby Mathew 51532ed618SSoby Mathew #ifndef __ASSEMBLY__ 52532ed618SSoby Mathew 53532ed618SSoby Mathew /* Prototype for runtime service initializing function */ 54532ed618SSoby Mathew typedef int32_t (*rt_svc_init_t)(void); 55532ed618SSoby Mathew 56532ed618SSoby Mathew /* 57532ed618SSoby Mathew * Prototype for runtime service SMC handler function. x0 (SMC Function ID) to 58532ed618SSoby Mathew * x4 are as passed by the caller. Rest of the arguments to SMC and the context 59532ed618SSoby Mathew * can be accessed using the handle pointer. The cookie parameter is reserved 60532ed618SSoby Mathew * for future use 61532ed618SSoby Mathew */ 62532ed618SSoby Mathew typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, 63532ed618SSoby Mathew u_register_t x1, 64532ed618SSoby Mathew u_register_t x2, 65532ed618SSoby Mathew u_register_t x3, 66532ed618SSoby Mathew u_register_t x4, 67532ed618SSoby Mathew void *cookie, 68532ed618SSoby Mathew void *handle, 69532ed618SSoby Mathew u_register_t flags); 70532ed618SSoby Mathew typedef struct rt_svc_desc { 71532ed618SSoby Mathew uint8_t start_oen; 72532ed618SSoby Mathew uint8_t end_oen; 732f370465SAntonio Nino Diaz #if SMCCC_MAJOR_VERSION == 1 74532ed618SSoby Mathew uint8_t call_type; 752f370465SAntonio Nino Diaz #elif SMCCC_MAJOR_VERSION == 2 762f370465SAntonio Nino Diaz uint8_t is_vendor; 772f370465SAntonio Nino Diaz #endif 78532ed618SSoby Mathew const char *name; 79532ed618SSoby Mathew rt_svc_init_t init; 80532ed618SSoby Mathew rt_svc_handle_t handle; 81532ed618SSoby Mathew } rt_svc_desc_t; 82532ed618SSoby Mathew 83532ed618SSoby Mathew /* 842f370465SAntonio Nino Diaz * Convenience macros to declare a service descriptor 85532ed618SSoby Mathew */ 862f370465SAntonio Nino Diaz #if SMCCC_MAJOR_VERSION == 1 872f370465SAntonio Nino Diaz 88532ed618SSoby Mathew #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \ 89532ed618SSoby Mathew static const rt_svc_desc_t __svc_desc_ ## _name \ 90532ed618SSoby Mathew __section("rt_svc_descs") __used = { \ 91*e02f469fSSathees Balya .start_oen = (_start), \ 92*e02f469fSSathees Balya .end_oen = (_end), \ 93*e02f469fSSathees Balya .call_type = (_type), \ 94532ed618SSoby Mathew .name = #_name, \ 95*e02f469fSSathees Balya .init = (_setup), \ 96*e02f469fSSathees Balya .handle = (_smch) \ 972f370465SAntonio Nino Diaz } 982f370465SAntonio Nino Diaz 992f370465SAntonio Nino Diaz #elif SMCCC_MAJOR_VERSION == 2 1002f370465SAntonio Nino Diaz 1012f370465SAntonio Nino Diaz #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \ 1022f370465SAntonio Nino Diaz static const rt_svc_desc_t __svc_desc_ ## _name \ 1032f370465SAntonio Nino Diaz __section("rt_svc_descs") __used = { \ 104*e02f469fSSathees Balya .start_oen = (_start), \ 105*e02f469fSSathees Balya .end_oen = (_end), \ 1062f370465SAntonio Nino Diaz .is_vendor = 0, \ 1072f370465SAntonio Nino Diaz .name = #_name, \ 108*e02f469fSSathees Balya .init = (_setup), \ 109*e02f469fSSathees Balya .handle = (_smch), \ 1102f370465SAntonio Nino Diaz }; \ 1112f370465SAntonio Nino Diaz CASSERT((_type) == SMC_TYPE_FAST, rt_svc_type_check_ ## _name) 1122f370465SAntonio Nino Diaz 1132f370465SAntonio Nino Diaz /* 1142f370465SAntonio Nino Diaz * The higher 16 entries of the runtime services are used for the vendor 1152f370465SAntonio Nino Diaz * specific descriptor. 1162f370465SAntonio Nino Diaz */ 1172f370465SAntonio Nino Diaz #define DECLARE_RT_SVC_VENDOR(_setup, _smch) \ 1182f370465SAntonio Nino Diaz static const rt_svc_desc_t __svc_desc_vendor \ 1192f370465SAntonio Nino Diaz __section("rt_svc_descs") __used = { \ 1202f370465SAntonio Nino Diaz .start_oen = 0, \ 1212f370465SAntonio Nino Diaz .end_oen = 15, \ 1222f370465SAntonio Nino Diaz .is_vendor = 1, \ 1232f370465SAntonio Nino Diaz .name = "vendor_rt_svc", \ 1242f370465SAntonio Nino Diaz .init = _setup, \ 1252f370465SAntonio Nino Diaz .handle = _smch, \ 1262f370465SAntonio Nino Diaz } 1272f370465SAntonio Nino Diaz 1282f370465SAntonio Nino Diaz #endif /* SMCCC_MAJOR_VERSION */ 129532ed618SSoby Mathew 130532ed618SSoby Mathew /* 131532ed618SSoby Mathew * Compile time assertions related to the 'rt_svc_desc' structure to: 132532ed618SSoby Mathew * 1. ensure that the assembler and the compiler view of the size 133532ed618SSoby Mathew * of the structure are the same. 134532ed618SSoby Mathew * 2. ensure that the assembler and the compiler see the initialisation 135532ed618SSoby Mathew * routine at the same offset. 136532ed618SSoby Mathew * 3. ensure that the assembler and the compiler see the handler 137532ed618SSoby Mathew * routine at the same offset. 138532ed618SSoby Mathew */ 139532ed618SSoby Mathew CASSERT((sizeof(rt_svc_desc_t) == SIZEOF_RT_SVC_DESC), \ 140532ed618SSoby Mathew assert_sizeof_rt_svc_desc_mismatch); 141532ed618SSoby Mathew CASSERT(RT_SVC_DESC_INIT == __builtin_offsetof(rt_svc_desc_t, init), \ 142532ed618SSoby Mathew assert_rt_svc_desc_init_offset_mismatch); 143532ed618SSoby Mathew CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \ 144532ed618SSoby Mathew assert_rt_svc_desc_handle_offset_mismatch); 145532ed618SSoby Mathew 146532ed618SSoby Mathew 1472f370465SAntonio Nino Diaz #if SMCCC_MAJOR_VERSION == 1 148532ed618SSoby Mathew /* 14981542c00SAntonio Nino Diaz * This function combines the call type and the owning entity number 15081542c00SAntonio Nino Diaz * corresponding to a runtime service to generate a unique owning entity number. 15181542c00SAntonio Nino Diaz * This unique oen is used to access an entry in the 'rt_svc_descs_indices' 15281542c00SAntonio Nino Diaz * array. The entry contains the index of the service descriptor in the 15381542c00SAntonio Nino Diaz * 'rt_svc_descs' array. 154532ed618SSoby Mathew */ 15581542c00SAntonio Nino Diaz static inline uint32_t get_unique_oen(uint32_t oen, uint32_t call_type) 15681542c00SAntonio Nino Diaz { 15781542c00SAntonio Nino Diaz return ((call_type & FUNCID_TYPE_MASK) << FUNCID_OEN_WIDTH) | 15881542c00SAntonio Nino Diaz (oen & FUNCID_OEN_MASK); 15981542c00SAntonio Nino Diaz } 160532ed618SSoby Mathew 1611ae0a49aSSoby Mathew /* 16281542c00SAntonio Nino Diaz * This function generates the unique owning entity number from the SMC Function 163b3323cd6SAntonio Nino Diaz * ID. This unique oen is used to access an entry in the 'rt_svc_descs_indices' 164b3323cd6SAntonio Nino Diaz * array to invoke the corresponding runtime service handler during SMC 165b3323cd6SAntonio Nino Diaz * handling. 1661ae0a49aSSoby Mathew */ 16781542c00SAntonio Nino Diaz static inline uint32_t get_unique_oen_from_smc_fid(uint32_t fid) 16881542c00SAntonio Nino Diaz { 16981542c00SAntonio Nino Diaz return get_unique_oen(GET_SMC_OEN(fid), GET_SMC_TYPE(fid)); 17081542c00SAntonio Nino Diaz } 1712f370465SAntonio Nino Diaz 1722f370465SAntonio Nino Diaz #elif SMCCC_MAJOR_VERSION == 2 1732f370465SAntonio Nino Diaz 1742f370465SAntonio Nino Diaz /* 17581542c00SAntonio Nino Diaz * This function combines the owning entity number corresponding to a runtime 1762f370465SAntonio Nino Diaz * service with one extra bit for the vendor namespace to generate an index into 1772f370465SAntonio Nino Diaz * the 'rt_svc_descs_indices' array. The entry contains the index of the service 1782f370465SAntonio Nino Diaz * descriptor in the 'rt_svc_descs' array. 1792f370465SAntonio Nino Diaz */ 18081542c00SAntonio Nino Diaz static inline uint32_t get_rt_desc_idx(uint32_t oen, uint32_t is_vendor) 18181542c00SAntonio Nino Diaz { 18281542c00SAntonio Nino Diaz return ((is_vendor & 1U) << FUNCID_OEN_WIDTH) | 18381542c00SAntonio Nino Diaz (oen & FUNCID_OEN_MASK); 18481542c00SAntonio Nino Diaz } 1852f370465SAntonio Nino Diaz 1862f370465SAntonio Nino Diaz #endif 1871ae0a49aSSoby Mathew 188532ed618SSoby Mathew /******************************************************************************* 189532ed618SSoby Mathew * Function & variable prototypes 190532ed618SSoby Mathew ******************************************************************************/ 191532ed618SSoby Mathew void runtime_svc_init(void); 1921ae0a49aSSoby Mathew uintptr_t handle_runtime_svc(uint32_t smc_fid, void *cookie, void *handle, 1931ae0a49aSSoby Mathew unsigned int flags); 1949f85f9e3SJoel Hutton IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_START__, RT_SVC_DESCS_START); 1959f85f9e3SJoel Hutton IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_END__, RT_SVC_DESCS_END); 196532ed618SSoby Mathew void init_crash_reporting(void); 197532ed618SSoby Mathew 1987fabe1a8SRoberto Vargas extern uint8_t rt_svc_descs_indices[MAX_RT_SVCS]; 1997fabe1a8SRoberto Vargas 200532ed618SSoby Mathew #endif /*__ASSEMBLY__*/ 201*e02f469fSSathees Balya #endif /* RUNTIME_SVC_H */ 202