feat(smc): support SMC calls with no ret vals in x8

The current implementation of the SMC library assumes that x8
contains the address of an smc_ret_values structure. Although
this can be convenient, it prevents from using registers x8-x17
as arguments, since it assumes there is an address in x8.

This patch implements an alternative API for SMC calls, allowing
the use of registers x1-x17 as input arguments and the use of
registers x0-x17 as output arguments without assuming a pointer
in x8.

Signed-off-by: Juan Pablo Conde <juanpablo.conde@arm.com>
Change-Id: I0016116b8d2ee4ef5aac9473f31e38434cda4943
diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h
index 36e2e0f..c65b061 100644
--- a/include/lib/tftf_lib.h
+++ b/include/lib/tftf_lib.h
@@ -140,48 +140,109 @@
 void waitms(uint64_t ms);
 void waitus(uint64_t us);
 
+/* Define fields in common for smc_args and smc_args_ext */
+#define FID_COMMON_ARGS()						\
+	/*								\
+	 * Function identifier. Identifies which function is being	\
+	 * invoked.							\
+	 */								\
+	uint32_t	fid;						\
+									\
+	u_register_t	arg1;						\
+	u_register_t	arg2;						\
+	u_register_t	arg3;						\
+	u_register_t	arg4;						\
+	u_register_t	arg5;						\
+	u_register_t	arg6;						\
+	u_register_t	arg7;
+
+/* Define fields in common for smc_ret_values and smc_ret_values_ext */
+#define COMMON_RETVALS()						\
+	u_register_t	ret0;						\
+	u_register_t	ret1;						\
+	u_register_t	ret2;						\
+	u_register_t	ret3;						\
+	u_register_t	ret4;						\
+	u_register_t	ret5;						\
+	u_register_t	ret6;						\
+	u_register_t	ret7;
+
+
 /*
- * SMC calls take a function identifier and up to 7 arguments.
+ * SMC calls take a function identifier and up to 7 arguments if using x8
+ * as an address pointing to a structure where return values are stored.
  * Additionally, few SMC calls that originate from EL2 leverage the seventh
  * argument explicitly. Given that TFTF runs in EL2, we need to be able to
  * specify it.
  */
 typedef struct {
-	/* Function identifier. Identifies which function is being invoked. */
-	uint32_t	fid;
-
-	u_register_t	arg1;
-	u_register_t	arg2;
-	u_register_t	arg3;
-	u_register_t	arg4;
-	u_register_t	arg5;
-	u_register_t	arg6;
-	u_register_t	arg7;
+	FID_COMMON_ARGS()
 } smc_args;
 
-/* SMC calls can return up to 8 register values */
+/*
+ * If x8 is not used as an address pointing to a structure where the return
+ * values are stored, SMC calls take up to 17 arguments.
+ */
 typedef struct {
-	u_register_t	ret0;
-	u_register_t	ret1;
-	u_register_t	ret2;
-	u_register_t	ret3;
-	u_register_t	ret4;
-	u_register_t	ret5;
-	u_register_t	ret6;
-	u_register_t	ret7;
+	FID_COMMON_ARGS()
+	u_register_t	arg8;
+	u_register_t	arg9;
+	u_register_t	arg10;
+	u_register_t	arg11;
+	u_register_t	arg12;
+	u_register_t	arg13;
+	u_register_t	arg14;
+	u_register_t	arg15;
+	u_register_t	arg16;
+	u_register_t	arg17;
+} smc_args_ext;
+
+/*
+ * SMC calls can return up to 8 register values if x8 is used as an address
+ * pointing to a structure where the return values are stored.
+ */
+typedef struct {
+	COMMON_RETVALS()
 } smc_ret_values;
 
 /*
- * Trigger an SMC call.
+ * If x8 is not used as an address pointing to a structure where the return
+ * values are stored, SMC calls return up to 18 register values.
+ */
+typedef struct {
+	COMMON_RETVALS()
+	u_register_t	ret8;
+	u_register_t	ret9;
+	u_register_t	ret10;
+	u_register_t	ret11;
+	u_register_t	ret12;
+	u_register_t	ret13;
+	u_register_t	ret14;
+	u_register_t	ret15;
+	u_register_t	ret16;
+	u_register_t	ret17;
+} smc_ret_values_ext;
+
+/*
+ * Trigger an SMC call. Return values are stored in structure pointed by address
+ * stored in x8.
  */
 smc_ret_values tftf_smc(const smc_args *args);
 
+/*
+ * Trigger an SMC call. Return values are stored in structure pointed by 'ret'
+ */
+void tftf_smc_no_retval_x8(const smc_args_ext *args, smc_ret_values_ext *ret);
+
 /* Assembler routine to trigger a SMC call. */
 smc_ret_values asm_tftf_smc64(uint32_t fid, u_register_t arg1, u_register_t arg2,
 			      u_register_t arg3, u_register_t arg4,
 			      u_register_t arg5, u_register_t arg6,
 			      u_register_t arg7);
 
+/* Assembler routine to trigger a SMC call without smc_ret_values in x8. */
+u_register_t asm_tftf_smc64_no_retval_x8(const smc_args_ext *args,
+					  smc_ret_values_ext *ret);
 /*
  * Update the SVE hint for the current CPU. Any SMC call made through tftf_smc
  * will update the SVE hint bit in the SMC Function ID.