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 <antonio.ninodiaz@arm.com>
diff --git a/include/common/runtime_svc.h b/include/common/runtime_svc.h
index 706c211..b8cf8de 100644
--- a/include/common/runtime_svc.h
+++ b/include/common/runtime_svc.h
@@ -8,8 +8,9 @@
 #define __RUNTIME_SVC_H__
 
 #include <bl_common.h>		/* to include exception types */
+#include <cassert.h>
 #include <smccc_helpers.h>	/* to include SMCCC definitions */
-
+#include <utils_def.h>
 
 /*******************************************************************************
  * 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 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 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)
+
+/*
- * Convenience macro to declare a service descriptor
+ * 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 @@
 	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 @@
  * 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
diff --git a/include/lib/smccc.h b/include/lib/smccc.h
index b1d4dea..1e7af6a 100644
--- a/include/lib/smccc.h
+++ b/include/lib/smccc.h
@@ -9,83 +9,41 @@
 
 #include <utils_def.h>
 
-/*******************************************************************************
- * Bit definitions inside the function id as per the SMC calling convention
- ******************************************************************************/
-#define FUNCID_TYPE_SHIFT		U(31)
-#define FUNCID_CC_SHIFT			U(30)
-#define FUNCID_OEN_SHIFT		U(24)
-#define FUNCID_NUM_SHIFT		U(0)
+#define SMCCC_VERSION_MAJOR_SHIFT	U(16)
+#define SMCCC_VERSION_MAJOR_MASK	U(0x7FFF)
+#define SMCCC_VERSION_MINOR_SHIFT	U(0)
+#define SMCCC_VERSION_MINOR_MASK	U(0xFFFF)
+#define MAKE_SMCCC_VERSION(_major, _minor) \
+	( (((uint32_t)(_major) & SMCCC_VERSION_MAJOR_MASK) << SMCCC_VERSION_MAJOR_SHIFT) \
+	| (((uint32_t)(_minor) & SMCCC_VERSION_MINOR_MASK) << SMCCC_VERSION_MINOR_SHIFT))
 
-#define FUNCID_TYPE_MASK		U(0x1)
-#define FUNCID_CC_MASK			U(0x1)
-#define FUNCID_OEN_MASK			U(0x3f)
-#define FUNCID_NUM_MASK			U(0xffff)
-
-#define FUNCID_TYPE_WIDTH		U(1)
-#define FUNCID_CC_WIDTH			U(1)
-#define FUNCID_OEN_WIDTH		U(6)
-#define FUNCID_NUM_WIDTH		U(16)
-
-#define GET_SMC_CC(id)			((id >> FUNCID_CC_SHIFT) & \
-					 FUNCID_CC_MASK)
-#define GET_SMC_TYPE(id)		((id >> FUNCID_TYPE_SHIFT) & \
-					 FUNCID_TYPE_MASK)
-
-#define SMC_64				U(1)
-#define SMC_32				U(0)
-#define SMC_OK				U(0)
-#define SMC_UNK				-1
-#define SMC_TYPE_FAST			ULL(1)
-#if !ERROR_DEPRECATED
-#define SMC_TYPE_STD			ULL(0)
+#if SMCCC_MAJOR_VERSION == 1
+# define SMCCC_MINOR_VERSION U(1)
+# include <smccc_v1.h>
+#elif SMCCC_MAJOR_VERSION == 2
+# define SMCCC_MINOR_VERSION U(0)
+# include <smccc_v2.h>
+#else
+# error "Unsupported version of SMCCC."
 #endif
-#define SMC_TYPE_YIELD			U(0)
-#define SMC_PREEMPTED			-2
-/*******************************************************************************
- * Owning entity number definitions inside the function id as per the SMC
- * calling convention
- ******************************************************************************/
-#define OEN_ARM_START			U(0)
-#define OEN_ARM_END			U(0)
-#define OEN_CPU_START			U(1)
-#define OEN_CPU_END			U(1)
-#define OEN_SIP_START			U(2)
-#define OEN_SIP_END			U(2)
-#define OEN_OEM_START			U(3)
-#define OEN_OEM_END			U(3)
-#define OEN_STD_START			U(4)	/* Standard Service Calls */
-#define OEN_STD_END			U(4)
-#define OEN_TAP_START			U(48)	/* Trusted Applications */
-#define OEN_TAP_END			U(49)
-#define OEN_TOS_START			U(50)	/* Trusted OS */
-#define OEN_TOS_END			U(63)
-#define OEN_LIMIT			U(64)
+
+/* Various flags passed to SMC handlers */
+#define SMC_FROM_SECURE		(U(0) << 0)
+#define SMC_FROM_NON_SECURE	(U(1) << 0)
 
 #ifndef __ASSEMBLY__
 
 #include <cassert.h>
 #include <stdint.h>
 
-#define SMCCC_MAJOR_VERSION U(1)
-#define SMCCC_MINOR_VERSION U(1)
-
-#define MAKE_SMCCC_VERSION(_major, _minor) (((_major) << 16) | (_minor))
-
-/* Various flags passed to SMC handlers */
-#define SMC_FROM_SECURE		(U(0) << 0)
-#define SMC_FROM_NON_SECURE	(U(1) << 0)
-
 #define is_caller_non_secure(_f)	(((_f) & SMC_FROM_NON_SECURE) != U(0))
 #define is_caller_secure(_f)		(!is_caller_non_secure(_f))
 
 /* The macro below is used to identify a Standard Service SMC call */
-#define is_std_svc_call(_fid)		((((_fid) >> FUNCID_OEN_SHIFT) & \
-					   FUNCID_OEN_MASK) == OEN_STD_START)
+#define is_std_svc_call(_fid)		(GET_SMC_OEN(_fid) == OEN_STD_START)
 
 /* The macro below is used to identify a Arm Architectural Service SMC call */
-#define is_arm_arch_svc_call(_fid)	((((_fid) >> FUNCID_OEN_SHIFT) & \
-					   FUNCID_OEN_MASK) == OEN_ARM_START)
+#define is_arm_arch_svc_call(_fid)	(GET_SMC_OEN(_fid) == OEN_ARM_START)
 
 /* The macro below is used to identify a valid Fast SMC call */
 #define is_valid_fast_smc(_fid)		((!(((_fid) >> 16) & U(0xff))) && \
diff --git a/include/lib/smccc_v1.h b/include/lib/smccc_v1.h
new file mode 100644
index 0000000..8718d15
--- /dev/null
+++ b/include/lib/smccc_v1.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SMCCC_V1_H
+#define SMCCC_V1_H
+
+#ifndef __SMCCC_H__
+#error "This file must only be included from smccc.h"
+#endif
+
+/*******************************************************************************
+ * Bit definitions inside the function id as per the SMC calling convention
+ ******************************************************************************/
+#define FUNCID_TYPE_SHIFT		U(31)
+#define FUNCID_TYPE_MASK		U(0x1)
+#define FUNCID_TYPE_WIDTH		U(1)
+
+#define FUNCID_CC_SHIFT			U(30)
+#define FUNCID_CC_MASK			U(0x1)
+#define FUNCID_CC_WIDTH			U(1)
+
+#define FUNCID_OEN_SHIFT		U(24)
+#define FUNCID_OEN_MASK			U(0x3f)
+#define FUNCID_OEN_WIDTH		U(6)
+
+#define FUNCID_NUM_SHIFT		U(0)
+#define FUNCID_NUM_MASK			U(0xffff)
+#define FUNCID_NUM_WIDTH		U(16)
+
+#define GET_SMC_TYPE(id)		(((id) >> FUNCID_TYPE_SHIFT) & \
+					 FUNCID_TYPE_MASK)
+#define GET_SMC_CC(id)			(((id) >> FUNCID_CC_SHIFT) & \
+					 FUNCID_CC_MASK)
+#define GET_SMC_OEN(id)			(((id) >> FUNCID_OEN_SHIFT) & \
+					 FUNCID_OEN_MASK)
+
+/*******************************************************************************
+ * Owning entity number definitions inside the function id as per the SMC
+ * calling convention
+ ******************************************************************************/
+#define OEN_ARM_START			U(0)
+#define OEN_ARM_END			U(0)
+#define OEN_CPU_START			U(1)
+#define OEN_CPU_END			U(1)
+#define OEN_SIP_START			U(2)
+#define OEN_SIP_END			U(2)
+#define OEN_OEM_START			U(3)
+#define OEN_OEM_END			U(3)
+#define OEN_STD_START			U(4)	/* Standard Service Calls */
+#define OEN_STD_END			U(4)
+#define OEN_STD_HYP_START		U(5)	/* Standard Hypervisor Service calls */
+#define OEN_STD_HYP_END			U(5)
+#define OEN_VEN_HYP_START		U(6)	/* Vendor Hypervisor Service calls */
+#define OEN_VEN_HYP_END			U(6)
+#define OEN_TAP_START			U(48)	/* Trusted Applications */
+#define OEN_TAP_END			U(49)
+#define OEN_TOS_START			U(50)	/* Trusted OS */
+#define OEN_TOS_END			U(63)
+#define OEN_LIMIT			U(64)
+
+/* Flags and error codes */
+#define SMC_64				U(1)
+#define SMC_32				U(0)
+
+#define SMC_TYPE_FAST			ULL(1)
+#if !ERROR_DEPRECATED
+#define SMC_TYPE_STD			ULL(0)
+#endif
+#define SMC_TYPE_YIELD			ULL(0)
+
+#define SMC_OK				ULL(0)
+#define SMC_UNK				-1
+#define SMC_PREEMPTED			-2	/* Not defined by the SMCCC */
+
+#endif /* SMCCC_V1_H */
diff --git a/include/lib/smccc_v2.h b/include/lib/smccc_v2.h
new file mode 100644
index 0000000..628c160
--- /dev/null
+++ b/include/lib/smccc_v2.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SMCCC_V2_H
+#define SMCCC_V2_H
+
+#ifndef __SMCCC_H__
+#error "This file must only be included from smccc.h"
+#endif
+
+/*******************************************************************************
+ * Bit definitions inside the function id as per the SMC calling convention
+ ******************************************************************************/
+#define FUNCID_TYPE_SHIFT		U(31)
+#define FUNCID_TYPE_MASK		U(0x1)
+#define FUNCID_TYPE_WIDTH		U(1)
+
+#define FUNCID_CC_SHIFT			U(30)
+#define FUNCID_CC_MASK			U(0x1)
+#define FUNCID_CC_WIDTH			U(1)
+
+#define FUNCID_NAMESPACE_SHIFT		U(28)
+#define FUNCID_NAMESPACE_MASK		U(0x3)
+#define FUNCID_NAMESPACE_WIDTH		U(2)
+
+#define FUNCID_OEN_SHIFT		U(24)
+#define FUNCID_OEN_MASK			U(0xf)
+#define FUNCID_OEN_WIDTH		U(4)
+
+#define FUNCID_NUM_SHIFT		U(0)
+#define FUNCID_NUM_MASK			U(0xffff)
+#define FUNCID_NUM_WIDTH		U(16)
+
+#define GET_SMC_TYPE(id)		(((id) >> FUNCID_TYPE_SHIFT) & \
+					 FUNCID_TYPE_MASK)
+#define GET_SMC_CC(id)			(((id) >> FUNCID_CC_SHIFT) & \
+					 FUNCID_CC_MASK)
+#define GET_SMC_NAMESPACE(id)		(((id) >> FUNCID_NAMESPACE_SHIFT) & \
+					 FUNCID_NAMESPACE_MASK)
+#define GET_SMC_OEN(id)			(((id) >> FUNCID_OEN_SHIFT) & \
+					 FUNCID_OEN_MASK)
+
+/*******************************************************************************
+ * Owning entity number definitions inside the function id as per the SMC
+ * calling convention
+ ******************************************************************************/
+#define OEN_ARM_START			U(0)
+#define OEN_ARM_END			U(0)
+#define OEN_CPU_START			U(1)
+#define OEN_CPU_END			U(1)
+#define OEN_SIP_START			U(2)
+#define OEN_SIP_END			U(2)
+#define OEN_OEM_START			U(3)
+#define OEN_OEM_END			U(3)
+#define OEN_STD_START			U(4)	/* Standard Service Calls */
+#define OEN_STD_END			U(4)
+#define OEN_STD_HYP_START		U(5)	/* Standard Hypervisor Service calls */
+#define OEN_STD_HYP_END			U(5)
+#define OEN_VEN_HYP_START		U(6)	/* Vendor Hypervisor Service calls */
+#define OEN_VEN_HYP_END			U(6)
+#define OEN_LIMIT			U(16)
+
+/*******************************************************************************
+ * Service namespaces as per the SMC Calling Convention v2.X
+ ******************************************************************************/
+#define FUNCID_NAMESPACE_START		U(0)
+#define FUNCID_NAMESPACE_COMPAT		U(0)
+#define FUNCID_NAMESPACE_VENDOR		U(1)
+#define FUNCID_NAMESPACE_SPRT		U(2)
+#define FUNCID_NAMESPACE_SPCI		U(3)
+#define FUNCID_NAMESPACE_LIMIT		U(4)
+
+/* Flags and error codes */
+#define SMC_64				U(1)
+#define SMC_32				U(0)
+
+#define SMC_TYPE_FAST			ULL(1)
+
+#define SMC_OK				ULL(0)
+#define SMC_UNK				-1
+
+#endif /* SMCCC_V2_H */