feat(spmd): el3 direct message API
This patch implements an API that is exposed to SPMD logical partitions
that can be used to send direct messages to a secure partition.
It also adds required code in the SPMD smc handler to complete the
direct response appropriately.
Change-Id: I2d0e38415f13ad4fd28f8984d565036b7d3a9e71
Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@gmail.com>
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 9b06b55..b1bf795 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -863,6 +863,16 @@
spmd_spm_core_sync_exit(x2);
}
+ /*
+ * If there was an SPMD logical partition direct request on-going,
+ * return back to the SPMD logical partition so the error can be
+ * consumed.
+ */
+ if (is_spmd_logical_sp_dir_req_in_progress(ctx)) {
+ assert(secure_origin);
+ spmd_spm_core_sync_exit(0ULL);
+ }
+
return spmd_smc_forward(smc_fid, secure_origin,
x1, x2, x3, x4, cookie,
handle, flags);
@@ -1052,6 +1062,31 @@
case FFA_MSG_SEND_DIRECT_REQ_SMC32:
case FFA_MSG_SEND_DIRECT_REQ_SMC64:
+ /*
+ * Regardless of secure_origin, SPMD logical partitions cannot
+ * handle direct messages. They can only initiate direct
+ * messages and consume direct responses or errors.
+ */
+ if (is_spmd_lp_id(ffa_endpoint_source(x1)) ||
+ is_spmd_lp_id(ffa_endpoint_destination(x1))) {
+ return spmd_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER
+ );
+ }
+
+ /*
+ * When there is an ongoing SPMD logical partition direct
+ * request, there cannot be another direct request. Return
+ * error in this case. Panic'ing is an option but that does
+ * not provide the opportunity for caller to abort based on
+ * error codes.
+ */
+ if (is_spmd_logical_sp_dir_req_in_progress(ctx)) {
+ assert(secure_origin);
+ return spmd_ffa_error_return(handle,
+ FFA_ERROR_DENIED);
+ }
+
if (!secure_origin) {
/* Validate source endpoint is non-secure for non-secure caller. */
if (ffa_is_secure_world_id(ffa_endpoint_source(x1))) {
@@ -1079,7 +1114,9 @@
break; /* Not reached */
case FFA_MSG_SEND_DIRECT_RESP_SMC32:
- if (secure_origin && spmd_is_spmc_message(x1)) {
+ case FFA_MSG_SEND_DIRECT_RESP_SMC64:
+ if (secure_origin && (spmd_is_spmc_message(x1) ||
+ is_spmd_logical_sp_dir_req_in_progress(ctx))) {
spmd_spm_core_sync_exit(0ULL);
} else {
/* Forward direct message to the other world */
@@ -1119,7 +1156,6 @@
/* Forward the call to the other world */
/* fallthrough */
case FFA_MSG_SEND:
- case FFA_MSG_SEND_DIRECT_RESP_SMC64:
case FFA_MEM_DONATE_SMC32:
case FFA_MEM_DONATE_SMC64:
case FFA_MEM_LEND_SMC32:
@@ -1136,11 +1172,14 @@
case FFA_SUCCESS_SMC32:
case FFA_SUCCESS_SMC64:
/*
- * TODO: Assume that no requests originate from EL3 at the
- * moment. This will change if a SP service is required in
- * response to secure interrupts targeted to EL3. Until then
- * simply forward the call to the Normal world.
+ * If there is an ongoing direct request from an SPMD logical
+ * partition, return an error.
*/
+ if (is_spmd_logical_sp_dir_req_in_progress(ctx)) {
+ assert(secure_origin);
+ return spmd_ffa_error_return(handle,
+ FFA_ERROR_DENIED);
+ }
return spmd_smc_forward(smc_fid, secure_origin,
x1, x2, x3, x4, cookie,
@@ -1167,6 +1206,12 @@
FFA_ERROR_NOT_SUPPORTED);
}
+ if (is_spmd_logical_sp_dir_req_in_progress(ctx)) {
+ assert(secure_origin);
+ return spmd_ffa_error_return(handle,
+ FFA_ERROR_DENIED);
+ }
+
return spmd_smc_forward(smc_fid, secure_origin,
x1, x2, x3, x4, cookie,
handle, flags);