mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 09:34:18 +00:00
feat(ff-a): support FFA_MSG_SEND_DIRECT_REQ2/RESP2
StandaloneMm which is S-EL0 partition uses FFA_MSG_SEND_DIRECT_REQ2/RESP2 to handle multiple services. For this, add support for FFA_MSG_SEND_DIRECT_REQ2/RESP2 in el3_spmc restrictly up to use 8 registers. although FF-A v1.2 defines FFA_MSG_SEND_DIRECT_REQ2/RESP2 with ability to pass/return up to 18 registers. Signed-off-by: Levi Yun <yeoreum.yun@arm.com> Change-Id: I8ab1c332d269d9d131330bb2debd10d75bdba1ee
This commit is contained in:
parent
ddf72e6a36
commit
09a580b796
4 changed files with 68 additions and 6 deletions
|
@ -210,6 +210,8 @@
|
|||
#define FFA_PARTITION_DIRECT_REQ_RECV U(1 << 0)
|
||||
#define FFA_PARTITION_DIRECT_REQ_SEND U(1 << 1)
|
||||
#define FFA_PARTITION_INDIRECT_MSG U(1 << 2)
|
||||
#define FFA_PARTITION_DIRECT_REQ2_RECV U(1 << 9)
|
||||
#define FFA_PARTITION_DIRECT_REQ2_SEND U(1 << 10)
|
||||
|
||||
/*
|
||||
* Reserve a special value for traffic targeted to the Hypervisor or SPM.
|
||||
|
|
|
@ -134,6 +134,9 @@ struct sp_exec_ctx {
|
|||
|
||||
/* Track the source partition ID to validate a direct response. */
|
||||
uint16_t dir_req_origin_id;
|
||||
|
||||
/* Track direct message function id to validate a direct response. */
|
||||
uint16_t dir_req_funcid;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -304,6 +304,7 @@ static bool direct_msg_validate_lp_resp(uint16_t origin_id, uint16_t lp_id,
|
|||
void *handle)
|
||||
{
|
||||
/* Retrieve populated Direct Response Arguments. */
|
||||
uint64_t smc_fid = SMC_GET_GP(handle, CTX_GPREG_X0);
|
||||
uint64_t x1 = SMC_GET_GP(handle, CTX_GPREG_X1);
|
||||
uint64_t x2 = SMC_GET_GP(handle, CTX_GPREG_X2);
|
||||
uint16_t src_id = ffa_endpoint_source(x1);
|
||||
|
@ -323,13 +324,29 @@ static bool direct_msg_validate_lp_resp(uint16_t origin_id, uint16_t lp_id,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!direct_msg_validate_arg2(x2)) {
|
||||
if ((smc_fid != FFA_MSG_SEND_DIRECT_RESP2_SMC64) &&
|
||||
!direct_msg_validate_arg2(x2)) {
|
||||
ERROR("Invalid EL3 LP message encoding.\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Helper function to check that partition can receive direct msg or not.
|
||||
******************************************************************************/
|
||||
static bool direct_msg_receivable(uint32_t properties, uint16_t dir_req_fnum)
|
||||
{
|
||||
if ((dir_req_fnum == FFA_FNUM_MSG_SEND_DIRECT_REQ &&
|
||||
((properties & FFA_PARTITION_DIRECT_REQ_RECV) == 0U)) ||
|
||||
(dir_req_fnum == FFA_FNUM_MSG_SEND_DIRECT_REQ2 &&
|
||||
((properties & FFA_PARTITION_DIRECT_REQ2_RECV) == 0U))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handle direct request messages and route to the appropriate destination.
|
||||
******************************************************************************/
|
||||
|
@ -345,14 +362,21 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
|
|||
{
|
||||
uint16_t src_id = ffa_endpoint_source(x1);
|
||||
uint16_t dst_id = ffa_endpoint_destination(x1);
|
||||
uint16_t dir_req_funcid;
|
||||
struct el3_lp_desc *el3_lp_descs;
|
||||
struct secure_partition_desc *sp;
|
||||
unsigned int idx;
|
||||
|
||||
/* Check if arg2 has been populated correctly based on message type. */
|
||||
if (!direct_msg_validate_arg2(x2)) {
|
||||
return spmc_ffa_error_return(handle,
|
||||
FFA_ERROR_INVALID_PARAMETER);
|
||||
dir_req_funcid = (smc_fid != FFA_MSG_SEND_DIRECT_REQ2_SMC64) ?
|
||||
FFA_FNUM_MSG_SEND_DIRECT_REQ : FFA_FNUM_MSG_SEND_DIRECT_REQ2;
|
||||
|
||||
/*
|
||||
* Sanity check for DIRECT_REQ:
|
||||
* Check if arg2 has been populated correctly based on message type
|
||||
*/
|
||||
if ((dir_req_funcid == FFA_FNUM_MSG_SEND_DIRECT_REQ) &&
|
||||
!direct_msg_validate_arg2(x2)) {
|
||||
return spmc_ffa_error_return(handle, FFA_ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/* Validate Sender is either the current SP or from the normal world. */
|
||||
|
@ -368,6 +392,10 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
|
|||
/* Check if the request is destined for a Logical Partition. */
|
||||
for (unsigned int i = 0U; i < MAX_EL3_LP_DESCS_COUNT; i++) {
|
||||
if (el3_lp_descs[i].sp_id == dst_id) {
|
||||
if (!direct_msg_receivable(el3_lp_descs[i].properties, dir_req_funcid)) {
|
||||
return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
|
||||
}
|
||||
|
||||
uint64_t ret = el3_lp_descs[i].direct_req(
|
||||
smc_fid, secure_origin, x1, x2,
|
||||
x3, x4, cookie, handle, flags);
|
||||
|
@ -402,6 +430,10 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
|
|||
FFA_ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (!direct_msg_receivable(sp->properties, dir_req_funcid)) {
|
||||
return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
|
||||
}
|
||||
|
||||
/* Protect the runtime state of a UP S-EL0 SP with a lock. */
|
||||
if (sp->runtime_el == S_EL0) {
|
||||
spin_lock(&sp->rt_state_lock);
|
||||
|
@ -430,6 +462,7 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
|
|||
sp->ec[idx].rt_state = RT_STATE_RUNNING;
|
||||
sp->ec[idx].rt_model = RT_MODEL_DIR_REQ;
|
||||
sp->ec[idx].dir_req_origin_id = src_id;
|
||||
sp->ec[idx].dir_req_funcid = dir_req_funcid;
|
||||
|
||||
if (sp->runtime_el == S_EL0) {
|
||||
spin_unlock(&sp->rt_state_lock);
|
||||
|
@ -453,9 +486,13 @@ static uint64_t direct_resp_smc_handler(uint32_t smc_fid,
|
|||
uint64_t flags)
|
||||
{
|
||||
uint16_t dst_id = ffa_endpoint_destination(x1);
|
||||
uint16_t dir_req_funcid;
|
||||
struct secure_partition_desc *sp;
|
||||
unsigned int idx;
|
||||
|
||||
dir_req_funcid = (smc_fid != FFA_MSG_SEND_DIRECT_RESP2_SMC64) ?
|
||||
FFA_FNUM_MSG_SEND_DIRECT_REQ : FFA_FNUM_MSG_SEND_DIRECT_REQ2;
|
||||
|
||||
/* Check if arg2 has been populated correctly based on message type. */
|
||||
if (!direct_msg_validate_arg2(x2)) {
|
||||
return spmc_ffa_error_return(handle,
|
||||
|
@ -507,6 +544,15 @@ static uint64_t direct_resp_smc_handler(uint32_t smc_fid,
|
|||
return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
|
||||
}
|
||||
|
||||
if (dir_req_funcid != sp->ec[idx].dir_req_funcid) {
|
||||
WARN("Unmatched direct req/resp func id. req:%x, resp:%x on core%u.\n",
|
||||
sp->ec[idx].dir_req_funcid, (smc_fid & FUNCID_NUM_MASK), idx);
|
||||
if (sp->runtime_el == S_EL0) {
|
||||
spin_unlock(&sp->rt_state_lock);
|
||||
}
|
||||
return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
|
||||
}
|
||||
|
||||
if (sp->ec[idx].dir_req_origin_id != dst_id) {
|
||||
WARN("Invalid direct resp partition ID 0x%x != 0x%x on core%u.\n",
|
||||
dst_id, sp->ec[idx].dir_req_origin_id, idx);
|
||||
|
@ -522,6 +568,9 @@ static uint64_t direct_resp_smc_handler(uint32_t smc_fid,
|
|||
/* Clear the ongoing direct request ID. */
|
||||
sp->ec[idx].dir_req_origin_id = INV_SP_ID;
|
||||
|
||||
/* Clear the ongoing direct request message version. */
|
||||
sp->ec[idx].dir_req_funcid = 0U;
|
||||
|
||||
if (sp->runtime_el == S_EL0) {
|
||||
spin_unlock(&sp->rt_state_lock);
|
||||
}
|
||||
|
@ -1267,6 +1316,7 @@ static uint64_t ffa_features_handler(uint32_t smc_fid,
|
|||
case FFA_RX_RELEASE:
|
||||
case FFA_MSG_SEND_DIRECT_REQ_SMC32:
|
||||
case FFA_MSG_SEND_DIRECT_REQ_SMC64:
|
||||
case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
|
||||
case FFA_PARTITION_INFO_GET:
|
||||
case FFA_RXTX_MAP_SMC32:
|
||||
case FFA_RXTX_MAP_SMC64:
|
||||
|
@ -1289,6 +1339,7 @@ static uint64_t ffa_features_handler(uint32_t smc_fid,
|
|||
case FFA_SECONDARY_EP_REGISTER_SMC64:
|
||||
case FFA_MSG_SEND_DIRECT_RESP_SMC32:
|
||||
case FFA_MSG_SEND_DIRECT_RESP_SMC64:
|
||||
case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
|
||||
case FFA_MEM_RELINQUISH:
|
||||
case FFA_MSG_WAIT:
|
||||
case FFA_CONSOLE_LOG_SMC32:
|
||||
|
@ -1909,7 +1960,9 @@ static int sp_manifest_parse(void *sp_manifest, int offset,
|
|||
|
||||
/* Validate this entry, we currently only support direct messaging. */
|
||||
if ((config_32 & ~(FFA_PARTITION_DIRECT_REQ_RECV |
|
||||
FFA_PARTITION_DIRECT_REQ_SEND)) != 0U) {
|
||||
FFA_PARTITION_DIRECT_REQ_SEND |
|
||||
FFA_PARTITION_DIRECT_REQ2_RECV |
|
||||
FFA_PARTITION_DIRECT_REQ2_SEND)) != 0U) {
|
||||
WARN("Invalid Secure Partition messaging method (0x%x)\n",
|
||||
config_32);
|
||||
return -EINVAL;
|
||||
|
@ -2351,11 +2404,13 @@ uint64_t spmc_smc_handler(uint32_t smc_fid,
|
|||
|
||||
case FFA_MSG_SEND_DIRECT_REQ_SMC32:
|
||||
case FFA_MSG_SEND_DIRECT_REQ_SMC64:
|
||||
case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
|
||||
return direct_req_smc_handler(smc_fid, secure_origin, x1, x2,
|
||||
x3, x4, cookie, handle, flags);
|
||||
|
||||
case FFA_MSG_SEND_DIRECT_RESP_SMC32:
|
||||
case FFA_MSG_SEND_DIRECT_RESP_SMC64:
|
||||
case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
|
||||
return direct_resp_smc_handler(smc_fid, secure_origin, x1, x2,
|
||||
x3, x4, cookie, handle, flags);
|
||||
|
||||
|
|
|
@ -147,6 +147,8 @@ static int32_t spmc_send_pm_msg(uint8_t pm_msg_type,
|
|||
ec->rt_model = RT_MODEL_DIR_REQ;
|
||||
ec->rt_state = RT_STATE_RUNNING;
|
||||
ec->dir_req_origin_id = FFA_SPMC_ID;
|
||||
/* Expect a direct message response from the SP. */
|
||||
ec->dir_req_funcid = FFA_FNUM_MSG_SEND_DIRECT_REQ;
|
||||
|
||||
rc = spmc_sp_synchronous_entry(ec);
|
||||
if (rc != 0ULL) {
|
||||
|
|
Loading…
Add table
Reference in a new issue