From 2f370465241c85b2fe38a1eb69b457b9fed97207 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Mon, 23 Apr 2018 15:43:29 +0100 Subject: Add support for the SMC Calling Convention 2.0 Due to differences in the bitfields of the SMC IDs, it is not possible to support SMCCC 1.X and 2.0 at the same time. The behaviour of `SMCCC_MAJOR_VERSION` has changed. Now, it is a build option that specifies the major version of the SMCCC that the Trusted Firmware supports. The only two allowed values are 1 and 2, and it defaults to 1. The value of `SMCCC_MINOR_VERSION` is derived from it. Note: Support for SMCCC v2.0 is an experimental feature to enable prototyping of secure partition specifications. Support for this convention is disabled by default and could be removed without notice. Change-Id: I88abf9ccf08e9c66a13ce55c890edea54d9f16a7 Signed-off-by: Antonio Nino Diaz --- include/common/runtime_svc.h | 96 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 17 deletions(-) (limited to 'include/common/runtime_svc.h') diff --git a/include/common/runtime_svc.h b/include/common/runtime_svc.h index 706c2118..b8cf8ded 100644 --- a/include/common/runtime_svc.h +++ b/include/common/runtime_svc.h @@ -8,8 +8,9 @@ #define __RUNTIME_SVC_H__ #include /* to include exception types */ +#include #include /* to include SMCCC definitions */ - +#include /******************************************************************************* * Structure definition, typedefs & constants for the runtime service framework @@ -32,11 +33,20 @@ /* - * The function identifier has 6 bits for the owning entity number and - * single bit for the type of smc call. When taken together these - * values limit the maximum number of runtime services to 128. + * In SMCCC 1.X, the function identifier has 6 bits for the owning entity number + * and a single bit for the type of smc call. When taken together, those values + * limit the maximum number of runtime services to 128. + * + * In SMCCC 2.X the type bit is always 1 and there are only 4 OEN bits in the + * compatibility namespace, so the total number of services is 16. The LSB of + * namespace is also added to these 4 bits to make space for the vendor service + * handler and so the total number of runtime services is 32. */ +#if SMCCC_MAJOR_VERSION == 1 #define MAX_RT_SVCS 128 +#elif SMCCC_MAJOR_VERSION == 2 +#define MAX_RT_SVCS 32 +#endif #ifndef __ASSEMBLY__ @@ -60,24 +70,62 @@ typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, typedef struct rt_svc_desc { uint8_t start_oen; uint8_t end_oen; +#if SMCCC_MAJOR_VERSION == 1 uint8_t call_type; +#elif SMCCC_MAJOR_VERSION == 2 + uint8_t is_vendor; +#endif const char *name; rt_svc_init_t init; rt_svc_handle_t handle; } rt_svc_desc_t; /* - * Convenience macro to declare a service descriptor + * Convenience macros to declare a service descriptor + */ +#if SMCCC_MAJOR_VERSION == 1 + +#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \ + static const rt_svc_desc_t __svc_desc_ ## _name \ + __section("rt_svc_descs") __used = { \ + .start_oen = _start, \ + .end_oen = _end, \ + .call_type = _type, \ + .name = #_name, \ + .init = _setup, \ + .handle = _smch \ + } + +#elif SMCCC_MAJOR_VERSION == 2 + +#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \ + static const rt_svc_desc_t __svc_desc_ ## _name \ + __section("rt_svc_descs") __used = { \ + .start_oen = _start, \ + .end_oen = _end, \ + .is_vendor = 0, \ + .name = #_name, \ + .init = _setup, \ + .handle = _smch, \ + }; \ + CASSERT((_type) == SMC_TYPE_FAST, rt_svc_type_check_ ## _name) + +/* + * The higher 16 entries of the runtime services are used for the vendor + * specific descriptor. */ -#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \ - static const rt_svc_desc_t __svc_desc_ ## _name \ - __section("rt_svc_descs") __used = { \ - .start_oen = _start, \ - .end_oen = _end, \ - .call_type = _type, \ - .name = #_name, \ - .init = _setup, \ - .handle = _smch } +#define DECLARE_RT_SVC_VENDOR(_setup, _smch) \ + static const rt_svc_desc_t __svc_desc_vendor \ + __section("rt_svc_descs") __used = { \ + .start_oen = 0, \ + .end_oen = 15, \ + .is_vendor = 1, \ + .name = "vendor_rt_svc", \ + .init = _setup, \ + .handle = _smch, \ + } + +#endif /* SMCCC_MAJOR_VERSION */ /* * Compile time assertions related to the 'rt_svc_desc' structure to: @@ -96,6 +144,7 @@ CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \ assert_rt_svc_desc_handle_offset_mismatch); +#if SMCCC_MAJOR_VERSION == 1 /* * This macro combines the call type and the owning entity number corresponding * to a runtime service to generate a unique owning entity number. This unique @@ -112,9 +161,22 @@ CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \ * array to invoke the corresponding runtime service handler during SMC * handling. */ -#define get_unique_oen_from_smc_fid(fid) \ - get_unique_oen(((fid) >> FUNCID_OEN_SHIFT), \ - ((fid) >> FUNCID_TYPE_SHIFT)) +#define get_unique_oen_from_smc_fid(fid) \ + get_unique_oen(GET_SMC_OEN(fid), GET_SMC_TYPE(fid)) + +#elif SMCCC_MAJOR_VERSION == 2 + +/* + * This macro combines the owning entity number corresponding to a runtime + * service with one extra bit for the vendor namespace to generate an index into + * the 'rt_svc_descs_indices' array. The entry contains the index of the service + * descriptor in the 'rt_svc_descs' array. + */ +#define get_rt_desc_idx(oen, is_vendor) \ + (((uint32_t)(oen) & FUNCID_OEN_MASK) | \ + (((uint32_t)(is_vendor) & 1U) << FUNCID_OEN_WIDTH)) + +#endif /******************************************************************************* * Function & variable prototypes -- cgit v1.2.3