Merge changes from topic "ffa_el3_spmc" into integration
* changes: feat(spmc): add helper to obtain a partitions FF-A version feat(spmd): enable SPMD to forward FFA_VERSION to EL3 SPMC feat(spmc): enable handling FFA_VERSION ABI feat(spmc): add helper function to obtain endpoint mailbox feat(spmc): add helper function to obtain hyp structure feat(spmc): enable parsing of messaging methods from manifest
This commit is contained in:
commit
3d70568089
|
@ -38,6 +38,7 @@
|
||||||
#define FFA_VERSION_MINOR_SHIFT 0
|
#define FFA_VERSION_MINOR_SHIFT 0
|
||||||
#define FFA_VERSION_MINOR_MASK U(0xFFFF)
|
#define FFA_VERSION_MINOR_MASK U(0xFFFF)
|
||||||
#define FFA_VERSION_BIT31_MASK U(0x1u << 31)
|
#define FFA_VERSION_BIT31_MASK U(0x1u << 31)
|
||||||
|
#define FFA_VERSION_MASK U(0xFFFFFFFF)
|
||||||
|
|
||||||
|
|
||||||
#define MAKE_FFA_VERSION(major, minor) \
|
#define MAKE_FFA_VERSION(major, minor) \
|
||||||
|
|
|
@ -221,4 +221,10 @@ bool is_ffa_secure_id_valid(uint16_t partition_id);
|
||||||
*/
|
*/
|
||||||
struct el3_lp_desc *get_el3_lp_array(void);
|
struct el3_lp_desc *get_el3_lp_array(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to obtain the RX/TX buffer pair descriptor of the Hypervisor
|
||||||
|
* or OS kernel in the normal world or the last SP that was run.
|
||||||
|
*/
|
||||||
|
struct mailbox *spmc_get_mbox_desc(bool secure_origin);
|
||||||
|
|
||||||
#endif /* SPMC_H */
|
#endif /* SPMC_H */
|
||||||
|
|
|
@ -72,7 +72,7 @@ struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp)
|
||||||
/* Helper function to get pointer to SP context from its ID. */
|
/* Helper function to get pointer to SP context from its ID. */
|
||||||
struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id)
|
struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id)
|
||||||
{
|
{
|
||||||
/* Check for SWd Partitions. */
|
/* Check for Secure World Partitions. */
|
||||||
for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) {
|
for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) {
|
||||||
if (sp_desc[i].sp_id == id) {
|
if (sp_desc[i].sp_id == id) {
|
||||||
return &(sp_desc[i]);
|
return &(sp_desc[i]);
|
||||||
|
@ -81,6 +81,29 @@ struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to obtain the descriptor of the Hypervisor or OS kernel.
|
||||||
|
* We assume that the first descriptor is reserved for this entity.
|
||||||
|
*/
|
||||||
|
struct ns_endpoint_desc *spmc_get_hyp_ctx(void)
|
||||||
|
{
|
||||||
|
return &(ns_ep_desc[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to obtain the RX/TX buffer pair descriptor of the Hypervisor
|
||||||
|
* or OS kernel in the normal world or the last SP that was run.
|
||||||
|
*/
|
||||||
|
struct mailbox *spmc_get_mbox_desc(bool secure_origin)
|
||||||
|
{
|
||||||
|
/* Obtain the RX/TX buffer pair descriptor. */
|
||||||
|
if (secure_origin) {
|
||||||
|
return &(spmc_get_current_sp_ctx()->mailbox);
|
||||||
|
} else {
|
||||||
|
return &(spmc_get_hyp_ctx()->mailbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* This function returns to the place where spmc_sp_synchronous_entry() was
|
* This function returns to the place where spmc_sp_synchronous_entry() was
|
||||||
* called originally.
|
* called originally.
|
||||||
|
@ -491,6 +514,59 @@ static uint64_t ffa_error_handler(uint32_t smc_fid,
|
||||||
return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
|
return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t ffa_version_handler(uint32_t smc_fid,
|
||||||
|
bool secure_origin,
|
||||||
|
uint64_t x1,
|
||||||
|
uint64_t x2,
|
||||||
|
uint64_t x3,
|
||||||
|
uint64_t x4,
|
||||||
|
void *cookie,
|
||||||
|
void *handle,
|
||||||
|
uint64_t flags)
|
||||||
|
{
|
||||||
|
uint32_t requested_version = x1 & FFA_VERSION_MASK;
|
||||||
|
|
||||||
|
if (requested_version & FFA_VERSION_BIT31_MASK) {
|
||||||
|
/* Invalid encoding, return an error. */
|
||||||
|
SMC_RET1(handle, FFA_ERROR_NOT_SUPPORTED);
|
||||||
|
/* Execution stops here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine the caller to store the requested version. */
|
||||||
|
if (secure_origin) {
|
||||||
|
/*
|
||||||
|
* Ensure that the SP is reporting the same version as
|
||||||
|
* specified in its manifest. If these do not match there is
|
||||||
|
* something wrong with the SP.
|
||||||
|
* TODO: Should we abort the SP? For now assert this is not
|
||||||
|
* case.
|
||||||
|
*/
|
||||||
|
assert(requested_version ==
|
||||||
|
spmc_get_current_sp_ctx()->ffa_version);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If this is called by the normal world, record this
|
||||||
|
* information in its descriptor.
|
||||||
|
*/
|
||||||
|
spmc_get_hyp_ctx()->ffa_version = requested_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
SMC_RET1(handle, MAKE_FFA_VERSION(FFA_VERSION_MAJOR,
|
||||||
|
FFA_VERSION_MINOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Helper function to obtain the FF-A version of the calling partition.
|
||||||
|
******************************************************************************/
|
||||||
|
uint32_t get_partition_ffa_version(bool secure_origin)
|
||||||
|
{
|
||||||
|
if (secure_origin) {
|
||||||
|
return spmc_get_current_sp_ctx()->ffa_version;
|
||||||
|
} else {
|
||||||
|
return spmc_get_hyp_ctx()->ffa_version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* This function will parse the Secure Partition Manifest. From manifest, it
|
* This function will parse the Secure Partition Manifest. From manifest, it
|
||||||
* will fetch details for preparing Secure partition image context and secure
|
* will fetch details for preparing Secure partition image context and secure
|
||||||
|
@ -544,6 +620,23 @@ static int sp_manifest_parse(void *sp_manifest, int offset,
|
||||||
|
|
||||||
sp->execution_state = config_32;
|
sp->execution_state = config_32;
|
||||||
|
|
||||||
|
ret = fdt_read_uint32(sp_manifest, node,
|
||||||
|
"messaging-method", &config_32);
|
||||||
|
if (ret != 0) {
|
||||||
|
ERROR("Missing Secure Partition messaging method.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate this entry, we currently only support direct messaging. */
|
||||||
|
if ((config_32 & ~(FFA_PARTITION_DIRECT_REQ_RECV |
|
||||||
|
FFA_PARTITION_DIRECT_REQ_SEND)) != 0U) {
|
||||||
|
WARN("Invalid Secure Partition messaging method (0x%x)\n",
|
||||||
|
config_32);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp->properties = config_32;
|
||||||
|
|
||||||
ret = fdt_read_uint32(sp_manifest, node,
|
ret = fdt_read_uint32(sp_manifest, node,
|
||||||
"execution-ctx-count", &config_32);
|
"execution-ctx-count", &config_32);
|
||||||
|
|
||||||
|
@ -866,6 +959,10 @@ uint64_t spmc_smc_handler(uint32_t smc_fid,
|
||||||
{
|
{
|
||||||
switch (smc_fid) {
|
switch (smc_fid) {
|
||||||
|
|
||||||
|
case FFA_VERSION:
|
||||||
|
return ffa_version_handler(smc_fid, secure_origin, x1, x2, x3,
|
||||||
|
x4, cookie, handle, flags);
|
||||||
|
|
||||||
case FFA_MSG_SEND_DIRECT_REQ_SMC32:
|
case FFA_MSG_SEND_DIRECT_REQ_SMC32:
|
||||||
case FFA_MSG_SEND_DIRECT_REQ_SMC64:
|
case FFA_MSG_SEND_DIRECT_REQ_SMC64:
|
||||||
return direct_req_smc_handler(smc_fid, secure_origin, x1, x2,
|
return direct_req_smc_handler(smc_fid, secure_origin, x1, x2,
|
||||||
|
|
|
@ -626,7 +626,8 @@ uint64_t spmd_smc_handler(uint32_t smc_fid,
|
||||||
* If caller is secure and SPMC was initialized,
|
* If caller is secure and SPMC was initialized,
|
||||||
* return FFA_VERSION of SPMD.
|
* return FFA_VERSION of SPMD.
|
||||||
* If caller is non secure and SPMC was initialized,
|
* If caller is non secure and SPMC was initialized,
|
||||||
* return SPMC's version.
|
* forward to the EL3 SPMC if enabled, otherwise return
|
||||||
|
* the SPMC version if implemented at a lower EL.
|
||||||
* Sanity check to "input_version".
|
* Sanity check to "input_version".
|
||||||
* If the EL3 SPMC is enabled, ignore the SPMC state as
|
* If the EL3 SPMC is enabled, ignore the SPMC state as
|
||||||
* this is not used.
|
* this is not used.
|
||||||
|
@ -635,6 +636,17 @@ uint64_t spmd_smc_handler(uint32_t smc_fid,
|
||||||
(!is_spmc_at_el3() && (ctx->state == SPMC_STATE_RESET))) {
|
(!is_spmc_at_el3() && (ctx->state == SPMC_STATE_RESET))) {
|
||||||
ret = FFA_ERROR_NOT_SUPPORTED;
|
ret = FFA_ERROR_NOT_SUPPORTED;
|
||||||
} else if (!secure_origin) {
|
} else if (!secure_origin) {
|
||||||
|
if (is_spmc_at_el3()) {
|
||||||
|
/*
|
||||||
|
* Forward the call directly to the EL3 SPMC, if
|
||||||
|
* enabled, as we don't need to wrap the call in
|
||||||
|
* a direct request.
|
||||||
|
*/
|
||||||
|
return spmd_smc_forward(smc_fid, secure_origin,
|
||||||
|
x1, x2, x3, x4, cookie,
|
||||||
|
handle, flags);
|
||||||
|
}
|
||||||
|
|
||||||
gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
|
gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
|
||||||
uint64_t rc;
|
uint64_t rc;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue