feat(spmd): introduce FFA_PARTITION_INFO_GET_REGS

Add code in SPMD to forward calls to FFA_PARTITION_INFO_GET_REGS. This
is a new ABI that allows getting partition information without the need
for rx/tx buffer, that helps in situations where having an rx/tx buffer
mapped and available is difficult (ex. uefi runtime services).
Currently, the spmc at el3 does not support this new ABI.
The new ABI uses registers x8-x17 to return partition information so
changes are made to ensure those registers are passed through to the
SPMC and restored on the return path.

Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@gmail.com>
Change-Id: I1fe5956763e054e4f8d62292fc1247e7120bb5a4
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index dde1622..3c207ad 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -581,10 +581,40 @@
 #endif
 	cm_set_next_eret_context(secure_state_out);
 
+#if SPMD_SPM_AT_SEL2
+	/*
+	 * If SPMC is at SEL2, save additional registers x8-x17, which may
+	 * be used in FF-A calls such as FFA_PARTITION_INFO_GET_REGS.
+	 * Note that technically, all SPMCs can support this, but this code is
+	 * under ifdef to minimize breakage in case other SPMCs do not save
+	 * and restore x8-x17.
+	 * We also need to pass through these registers since not all FF-A ABIs
+	 * modify x8-x17, in which case, SMCCC requires that these registers be
+	 * preserved, so the SPMD passes through these registers and expects the
+	 * SPMC to save and restore (potentially also modify) them.
+	 */
+	SMC_RET18(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
+			SMC_GET_GP(handle, CTX_GPREG_X5),
+			SMC_GET_GP(handle, CTX_GPREG_X6),
+			SMC_GET_GP(handle, CTX_GPREG_X7),
+			SMC_GET_GP(handle, CTX_GPREG_X8),
+			SMC_GET_GP(handle, CTX_GPREG_X9),
+			SMC_GET_GP(handle, CTX_GPREG_X10),
+			SMC_GET_GP(handle, CTX_GPREG_X11),
+			SMC_GET_GP(handle, CTX_GPREG_X12),
+			SMC_GET_GP(handle, CTX_GPREG_X13),
+			SMC_GET_GP(handle, CTX_GPREG_X14),
+			SMC_GET_GP(handle, CTX_GPREG_X15),
+			SMC_GET_GP(handle, CTX_GPREG_X16),
+			SMC_GET_GP(handle, CTX_GPREG_X17)
+			);
+
+#else
 	SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
 			SMC_GET_GP(handle, CTX_GPREG_X5),
 			SMC_GET_GP(handle, CTX_GPREG_X6),
 			SMC_GET_GP(handle, CTX_GPREG_X7));
+#endif
 }
 
 /*******************************************************************************
@@ -1042,7 +1072,23 @@
 			return spmd_ffa_error_return(handle, FFA_ERROR_DENIED);
 		}
 		break; /* Not reached */
+#if MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED
+	case FFA_PARTITION_INFO_GET_REGS_SMC64:
+		if (secure_origin) {
+			/* TODO: Future patches to enable support for this */
+			return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
+		}
 
+		/* Call only supported with SMCCC 1.2+ */
+		if (MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION) < 0x10002) {
+			return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
+		}
+
+		return spmd_smc_forward(smc_fid, secure_origin,
+					x1, x2, x3, x4, cookie,
+					handle, flags);
+		break; /* Not reached */
+#endif
 	default:
 		WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
 		return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);