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;
}