feat(rmm-eac4): modify RMI_PSCI_COMPLETE command

This patch makes the following changes in
RMI_PSCI_COMPLETE command handler in according to
RMM Specification 1.0-eac3:
- added 'status' parameter passed in X3 register
- added 'status' failure condition.
PSCI and SMC return codes changed to comply with MISRA C
Rule 10.1 from UL(n) to (unsigned long)(n).

Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
Change-Id: Ib5ec506433a58f17591bef85a2b48663ac3969c0
diff --git a/runtime/core/handler.c b/runtime/core/handler.c
index fd8f97e..3dbff55 100644
--- a/runtime/core/handler.c
+++ b/runtime/core/handler.c
@@ -145,7 +145,7 @@
 	HANDLER(RTT_MAP_UNPROTECTED,	4, 0, smc_rtt_map_unprotected,	 false, false),
 	HANDLER(RTT_UNMAP_UNPROTECTED,	3, 1, smc_rtt_unmap_unprotected, false, false),
 	HANDLER(RTT_READ_ENTRY,		3, 4, smc_rtt_read_entry,	 false, true),
-	HANDLER(PSCI_COMPLETE,		2, 0, smc_psci_complete,	 true,  true),
+	HANDLER(PSCI_COMPLETE,		3, 0, smc_psci_complete,	 true,  true),
 	HANDLER(REC_AUX_COUNT,		1, 1, smc_rec_aux_count,	 true,  true),
 	HANDLER(RTT_INIT_RIPAS,		3, 1, smc_rtt_init_ripas,	 false, true),
 	HANDLER(RTT_SET_RIPAS,		4, 1, smc_rtt_set_ripas,	 false, true)
diff --git a/runtime/include/psci.h b/runtime/include/psci.h
index b3b33da..426ab72 100644
--- a/runtime/include/psci.h
+++ b/runtime/include/psci.h
@@ -76,16 +76,16 @@
 #define SMC32_PSCI_MEM_PROTECT_CHECK_RANGE	SMC32_PSCI_FID(0x14U)
 #define SMC64_PSCI_MEM_PROTECT_CHECK_RANGE	SMC64_PSCI_FID(0x14U)
 
-#define PSCI_RETURN_SUCCESS		UL(0)
-#define PSCI_RETURN_NOT_SUPPORTED	UL(-1)
-#define PSCI_RETURN_INVALID_PARAMS	UL(-2)
-#define PSCI_RETURN_DENIED		UL(-3)
-#define PSCI_RETURN_ALREADY_ON		UL(-4)
-#define PSCI_RETURN_ON_PENDING		UL(-5)
-#define PSCI_RETURN_INTERNAL_FAILURE	UL(-6)
-#define PSCI_RETURN_NOT_PRESENT		UL(-7)
-#define PSCI_RETURN_DISABLED		UL(-8)
-#define PSCI_RETURN_INVALID_ADDRESS	UL(-9)
+#define PSCI_RETURN_SUCCESS		(unsigned long)(0)
+#define PSCI_RETURN_NOT_SUPPORTED	(unsigned long)(-1)
+#define PSCI_RETURN_INVALID_PARAMS	(unsigned long)(-2)
+#define PSCI_RETURN_DENIED		(unsigned long)(-3)
+#define PSCI_RETURN_ALREADY_ON		(unsigned long)(-4)
+#define PSCI_RETURN_ON_PENDING		(unsigned long)(-5)
+#define PSCI_RETURN_INTERNAL_FAILURE	(unsigned long)(-6)
+#define PSCI_RETURN_NOT_PRESENT		(unsigned long)(-7)
+#define PSCI_RETURN_DISABLED		(unsigned long)(-8)
+#define PSCI_RETURN_INVALID_ADDRESS	(unsigned long)(-9)
 
 #define PSCI_AFFINITY_INFO_ON		UL(0)
 #define PSCI_AFFINITY_INFO_OFF		UL(1)
@@ -98,6 +98,6 @@
 struct rec;
 
 unsigned long psci_complete_request(struct rec *calling_rec,
-				    struct rec *target_rec);
+				    struct rec *target_rec, unsigned long status);
 
 #endif /* PSCI_H */
diff --git a/runtime/include/smc-handler.h b/runtime/include/smc-handler.h
index 1d6a41a..685f3c5 100644
--- a/runtime/include/smc-handler.h
+++ b/runtime/include/smc-handler.h
@@ -81,7 +81,8 @@
 			struct smc_result *res);
 
 unsigned long smc_psci_complete(unsigned long calling_rec_addr,
-				unsigned long target_rec_addr);
+				unsigned long target_rec_addr,
+				unsigned long status);
 
 void smc_rtt_init_ripas(unsigned long rd_addr,
 			unsigned long base,
diff --git a/runtime/rmi/rec.c b/runtime/rmi/rec.c
index 342f4b4..c7d2c49 100644
--- a/runtime/rmi/rec.c
+++ b/runtime/rmi/rec.c
@@ -420,7 +420,8 @@
 }
 
 unsigned long smc_psci_complete(unsigned long calling_rec_addr,
-				unsigned long target_rec_addr)
+				unsigned long target_rec_addr,
+				unsigned long status)
 {
 	struct granule *g_calling_rec, *g_target_rec;
 	struct rec  *calling_rec, *target_rec;
@@ -464,7 +465,7 @@
 	target_rec = granule_map(g_target_rec, SLOT_REC2);
 	assert(target_rec != NULL);
 
-	ret = psci_complete_request(calling_rec, target_rec);
+	ret = psci_complete_request(calling_rec, target_rec, status);
 
 	buffer_unmap(target_rec);
 	buffer_unmap(calling_rec);
diff --git a/runtime/rsi/psci.c b/runtime/rsi/psci.c
index a3752e5..b9cbd91 100644
--- a/runtime/rsi/psci.c
+++ b/runtime/rsi/psci.c
@@ -331,13 +331,22 @@
  */
 static unsigned long complete_psci_cpu_on(struct rec *target_rec,
 					  unsigned long entry_point_address,
-					  unsigned long caller_sctlr_el1)
+					  unsigned long caller_sctlr_el1,
+					  unsigned long status)
 {
 	if ((granule_refcount_read_acquire(target_rec->g_rec) != 0UL) ||
 		target_rec->runnable) {
 		return PSCI_RETURN_ALREADY_ON;
 	}
 
+	/*
+	 * Host is permitted to deny a PSCI_CPU_ON request,
+	 * if the target CPU is not already on.
+	 */
+	if (status == PSCI_RETURN_DENIED) {
+		return PSCI_RETURN_DENIED;
+	}
+
 	psci_reset_rec(target_rec, caller_sctlr_el1);
 	target_rec->pc = entry_point_address;
 	target_rec->runnable = true;
@@ -355,9 +364,10 @@
 }
 
 unsigned long psci_complete_request(struct rec *calling_rec,
-				    struct rec *target_rec)
+				    struct rec *target_rec, unsigned long status)
 {
-	unsigned long ret = PSCI_RETURN_NOT_SUPPORTED;
+	unsigned long ret = RMI_SUCCESS;
+	unsigned long rec_ret = PSCI_RETURN_NOT_SUPPORTED;
 	unsigned long mpidr = calling_rec->regs[1];
 
 	if (!calling_rec->psci_info.pending) {
@@ -375,23 +385,41 @@
 	switch (calling_rec->regs[0]) {
 	case SMC32_PSCI_CPU_ON:
 	case SMC64_PSCI_CPU_ON:
-		ret = complete_psci_cpu_on(target_rec,
-					   calling_rec->regs[2],
-					   calling_rec->sysregs.sctlr_el1);
+		if ((status != PSCI_RETURN_SUCCESS) &&
+		    (status != PSCI_RETURN_DENIED)) {
+			return RMI_ERROR_INPUT;
+		}
+
+		rec_ret = complete_psci_cpu_on(target_rec,
+						calling_rec->regs[2],
+						calling_rec->sysregs.sctlr_el1,
+						status);
+		/*
+		 * If the target CPU is already running and the Host has denied the
+		 * PSCI_CPU_ON request, then return error back to Host.
+		 */
+		if ((status == PSCI_RETURN_DENIED) &&
+		   (rec_ret == PSCI_RETURN_ALREADY_ON)) {
+			ret = RMI_ERROR_INPUT;
+		}
 		break;
 	case SMC32_PSCI_AFFINITY_INFO:
 	case SMC64_PSCI_AFFINITY_INFO:
-		ret = complete_psci_affinity_info(target_rec);
+		if (status != PSCI_RETURN_SUCCESS) {
+			return RMI_ERROR_INPUT;
+		}
+
+		rec_ret = complete_psci_affinity_info(target_rec);
 		break;
 	default:
 		assert(false);
 	}
 
-	calling_rec->regs[0] = ret;
+	calling_rec->regs[0] = rec_ret;
 	calling_rec->regs[1] = 0;
 	calling_rec->regs[2] = 0;
 	calling_rec->regs[3] = 0;
 	calling_rec->psci_info.pending = false;
 
-	return RMI_SUCCESS;
+	return ret;
 }