Merge "fix(rmmd): preserve x4-x7 as per SMCCCv1.1" into integration
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 7f85b63..e9004c7 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -48,10 +48,6 @@
  * Static function declaration.
  ******************************************************************************/
 static int32_t rmm_init(void);
-static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
-					uint32_t dst_sec_state, uint64_t x1,
-					uint64_t x2, uint64_t x3, uint64_t x4,
-					void *handle);
 
 /*******************************************************************************
  * This function takes an RMM context pointer and performs a synchronous entry
@@ -191,10 +187,10 @@
 /*******************************************************************************
  * Forward SMC to the other security state
  ******************************************************************************/
-static uint64_t	rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
-					uint32_t dst_sec_state, uint64_t x1,
-					uint64_t x2, uint64_t x3, uint64_t x4,
-					void *handle)
+static uint64_t	rmmd_smc_forward(uint32_t src_sec_state,
+					uint32_t dst_sec_state, uint64_t x0,
+					uint64_t x1, uint64_t x2, uint64_t x3,
+					uint64_t x4, void *handle)
 {
 	/* Save incoming security state */
 	cm_el1_sysregs_context_save(src_sec_state);
@@ -205,10 +201,20 @@
 	cm_el2_sysregs_context_restore(dst_sec_state);
 	cm_set_next_eret_context(dst_sec_state);
 
-	SMC_RET8(cm_get_context(dst_sec_state), 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));
+	/*
+	 * As per SMCCCv1.1, we need to preserve x4 to x7 unless
+	 * being used as return args. Hence we differentiate the
+	 * onward and backward path. Support upto 8 args in the
+	 * onward path and 4 args in return path.
+	 */
+	if (src_sec_state == NON_SECURE) {
+		SMC_RET8(cm_get_context(dst_sec_state), x0, 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));
+	} else {
+		SMC_RET4(cm_get_context(dst_sec_state), x0, x1, x2, x3);
+	}
 }
 
 /*******************************************************************************
@@ -237,7 +243,7 @@
 	 */
 	if (src_sec_state == SMC_FROM_NON_SECURE) {
 		VERBOSE("RMM: RMI call from non-secure world.\n");
-		return rmmd_smc_forward(smc_fid, NON_SECURE, REALM,
+		return rmmd_smc_forward(NON_SECURE, REALM, smc_fid,
 					x1, x2, x3, x4, handle);
 	}
 
@@ -250,7 +256,7 @@
 			rmmd_rmm_sync_exit(x1);
 		}
 
-		return rmmd_smc_forward(x1, REALM, NON_SECURE,
+		return rmmd_smc_forward(REALM, NON_SECURE, x1,
 					x2, x3, x4, 0, handle);
 
 	default: