15096aeb2SMarc Bonnici /*
29bfe78c2SLevi Yun * Copyright (c) 2022-2025, ARM Limited and Contributors. All rights reserved.
35096aeb2SMarc Bonnici *
45096aeb2SMarc Bonnici * SPDX-License-Identifier: BSD-3-Clause
55096aeb2SMarc Bonnici */
65096aeb2SMarc Bonnici
75096aeb2SMarc Bonnici #include <assert.h>
85096aeb2SMarc Bonnici #include <errno.h>
9638a6f8eSShruti Gupta #include <stdio.h>
105096aeb2SMarc Bonnici
115096aeb2SMarc Bonnici #include <arch_helpers.h>
125096aeb2SMarc Bonnici #include <bl31/bl31.h>
135096aeb2SMarc Bonnici #include <bl31/ehf.h>
14729d7793SAchin Gupta #include <bl31/interrupt_mgmt.h>
155096aeb2SMarc Bonnici #include <common/debug.h>
165096aeb2SMarc Bonnici #include <common/fdt_wrappers.h>
175096aeb2SMarc Bonnici #include <common/runtime_svc.h>
18f74e2772SMarc Bonnici #include <common/uuid.h>
195096aeb2SMarc Bonnici #include <lib/el3_runtime/context_mgmt.h>
205096aeb2SMarc Bonnici #include <lib/smccc.h>
215096aeb2SMarc Bonnici #include <lib/utils.h>
225096aeb2SMarc Bonnici #include <lib/xlat_tables/xlat_tables_v2.h>
235096aeb2SMarc Bonnici #include <libfdt.h>
245096aeb2SMarc Bonnici #include <plat/common/platform.h>
257affa25cSMarc Bonnici #include <services/el3_spmc_logical_sp.h>
265096aeb2SMarc Bonnici #include <services/ffa_svc.h>
275096aeb2SMarc Bonnici #include <services/spmc_svc.h>
285096aeb2SMarc Bonnici #include <services/spmd_svc.h>
295096aeb2SMarc Bonnici #include "spmc.h"
30e0b1a6d5SMarc Bonnici #include "spmc_shared_mem.h"
31aae2370cSYeoreum Yun #if TRANSFER_LIST
32aae2370cSYeoreum Yun #include <transfer_list.h>
33aae2370cSYeoreum Yun #endif
345096aeb2SMarc Bonnici
355096aeb2SMarc Bonnici #include <platform_def.h>
365096aeb2SMarc Bonnici
371f6b2b26SNishant Sharma /* FFA_MEM_PERM_* helpers */
381f6b2b26SNishant Sharma #define FFA_MEM_PERM_MASK U(7)
391f6b2b26SNishant Sharma #define FFA_MEM_PERM_DATA_MASK U(3)
401f6b2b26SNishant Sharma #define FFA_MEM_PERM_DATA_SHIFT U(0)
411f6b2b26SNishant Sharma #define FFA_MEM_PERM_DATA_NA U(0)
421f6b2b26SNishant Sharma #define FFA_MEM_PERM_DATA_RW U(1)
431f6b2b26SNishant Sharma #define FFA_MEM_PERM_DATA_RES U(2)
441f6b2b26SNishant Sharma #define FFA_MEM_PERM_DATA_RO U(3)
451f6b2b26SNishant Sharma #define FFA_MEM_PERM_INST_EXEC (U(0) << 2)
461f6b2b26SNishant Sharma #define FFA_MEM_PERM_INST_NON_EXEC (U(1) << 2)
471f6b2b26SNishant Sharma
48f74e2772SMarc Bonnici /* Declare the maximum number of SPs and El3 LPs. */
49*0322d7afSJay Monkman #define MAX_SP_LP_PARTITIONS (SECURE_PARTITION_COUNT + MAX_EL3_LP_DESCS_COUNT)
50f74e2772SMarc Bonnici
51dd87b735SJ-Alves #define FFA_VERSION_SPMC_MAJOR U(1)
52dd87b735SJ-Alves #define FFA_VERSION_SPMC_MINOR U(2)
53dd87b735SJ-Alves
545096aeb2SMarc Bonnici /*
555096aeb2SMarc Bonnici * Allocate a secure partition descriptor to describe each SP in the system that
565096aeb2SMarc Bonnici * does not reside at EL3.
575096aeb2SMarc Bonnici */
585096aeb2SMarc Bonnici static struct secure_partition_desc sp_desc[SECURE_PARTITION_COUNT];
595096aeb2SMarc Bonnici
605096aeb2SMarc Bonnici /*
615096aeb2SMarc Bonnici * Allocate an NS endpoint descriptor to describe each VM and the Hypervisor in
625096aeb2SMarc Bonnici * the system that interacts with a SP. It is used to track the Hypervisor
635096aeb2SMarc Bonnici * buffer pair, version and ID for now. It could be extended to track VM
645096aeb2SMarc Bonnici * properties when the SPMC supports indirect messaging.
655096aeb2SMarc Bonnici */
665096aeb2SMarc Bonnici static struct ns_endpoint_desc ns_ep_desc[NS_PARTITION_COUNT];
675096aeb2SMarc Bonnici
68729d7793SAchin Gupta static uint64_t spmc_sp_interrupt_handler(uint32_t id,
69729d7793SAchin Gupta uint32_t flags,
70729d7793SAchin Gupta void *handle,
71729d7793SAchin Gupta void *cookie);
72729d7793SAchin Gupta
735096aeb2SMarc Bonnici /*
747affa25cSMarc Bonnici * Helper function to obtain the array storing the EL3
757affa25cSMarc Bonnici * Logical Partition descriptors.
767affa25cSMarc Bonnici */
get_el3_lp_array(void)777affa25cSMarc Bonnici struct el3_lp_desc *get_el3_lp_array(void)
787affa25cSMarc Bonnici {
797affa25cSMarc Bonnici return (struct el3_lp_desc *) EL3_LP_DESCS_START;
807affa25cSMarc Bonnici }
817affa25cSMarc Bonnici
827affa25cSMarc Bonnici /*
835096aeb2SMarc Bonnici * Helper function to obtain the descriptor of the last SP to whom control was
845096aeb2SMarc Bonnici * handed to on this physical cpu. Currently, we assume there is only one SP.
855096aeb2SMarc Bonnici * TODO: Expand to track multiple partitions when required.
865096aeb2SMarc Bonnici */
spmc_get_current_sp_ctx(void)875096aeb2SMarc Bonnici struct secure_partition_desc *spmc_get_current_sp_ctx(void)
885096aeb2SMarc Bonnici {
895096aeb2SMarc Bonnici return &(sp_desc[ACTIVE_SP_DESC_INDEX]);
905096aeb2SMarc Bonnici }
915096aeb2SMarc Bonnici
925096aeb2SMarc Bonnici /*
935096aeb2SMarc Bonnici * Helper function to obtain the execution context of an SP on the
945096aeb2SMarc Bonnici * current physical cpu.
955096aeb2SMarc Bonnici */
spmc_get_sp_ec(struct secure_partition_desc * sp)965096aeb2SMarc Bonnici struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp)
975096aeb2SMarc Bonnici {
985096aeb2SMarc Bonnici return &(sp->ec[get_ec_index(sp)]);
995096aeb2SMarc Bonnici }
1005096aeb2SMarc Bonnici
1015096aeb2SMarc Bonnici /* Helper function to get pointer to SP context from its ID. */
spmc_get_sp_ctx(uint16_t id)1025096aeb2SMarc Bonnici struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id)
1035096aeb2SMarc Bonnici {
1040c7707fdSMarc Bonnici /* Check for Secure World Partitions. */
1055096aeb2SMarc Bonnici for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) {
1065096aeb2SMarc Bonnici if (sp_desc[i].sp_id == id) {
1075096aeb2SMarc Bonnici return &(sp_desc[i]);
1085096aeb2SMarc Bonnici }
1095096aeb2SMarc Bonnici }
1105096aeb2SMarc Bonnici return NULL;
1115096aeb2SMarc Bonnici }
1125096aeb2SMarc Bonnici
113a7c00505SMarc Bonnici /*
114a7c00505SMarc Bonnici * Helper function to obtain the descriptor of the Hypervisor or OS kernel.
115a7c00505SMarc Bonnici * We assume that the first descriptor is reserved for this entity.
116a7c00505SMarc Bonnici */
spmc_get_hyp_ctx(void)117a7c00505SMarc Bonnici struct ns_endpoint_desc *spmc_get_hyp_ctx(void)
118a7c00505SMarc Bonnici {
119a7c00505SMarc Bonnici return &(ns_ep_desc[0]);
120a7c00505SMarc Bonnici }
121a7c00505SMarc Bonnici
122f16b6ee3SMarc Bonnici /*
123f16b6ee3SMarc Bonnici * Helper function to obtain the RX/TX buffer pair descriptor of the Hypervisor
124f16b6ee3SMarc Bonnici * or OS kernel in the normal world or the last SP that was run.
125f16b6ee3SMarc Bonnici */
spmc_get_mbox_desc(bool secure_origin)126f16b6ee3SMarc Bonnici struct mailbox *spmc_get_mbox_desc(bool secure_origin)
127f16b6ee3SMarc Bonnici {
128f16b6ee3SMarc Bonnici /* Obtain the RX/TX buffer pair descriptor. */
129f16b6ee3SMarc Bonnici if (secure_origin) {
130f16b6ee3SMarc Bonnici return &(spmc_get_current_sp_ctx()->mailbox);
131f16b6ee3SMarc Bonnici } else {
132f16b6ee3SMarc Bonnici return &(spmc_get_hyp_ctx()->mailbox);
133f16b6ee3SMarc Bonnici }
134f16b6ee3SMarc Bonnici }
135f16b6ee3SMarc Bonnici
1365096aeb2SMarc Bonnici /******************************************************************************
1375096aeb2SMarc Bonnici * This function returns to the place where spmc_sp_synchronous_entry() was
1385096aeb2SMarc Bonnici * called originally.
1395096aeb2SMarc Bonnici ******************************************************************************/
spmc_sp_synchronous_exit(struct sp_exec_ctx * ec,uint64_t rc)1405096aeb2SMarc Bonnici __dead2 void spmc_sp_synchronous_exit(struct sp_exec_ctx *ec, uint64_t rc)
1415096aeb2SMarc Bonnici {
1425096aeb2SMarc Bonnici /*
1435096aeb2SMarc Bonnici * The SPM must have initiated the original request through a
1445096aeb2SMarc Bonnici * synchronous entry into the secure partition. Jump back to the
1455096aeb2SMarc Bonnici * original C runtime context with the value of rc in x0;
1465096aeb2SMarc Bonnici */
1475096aeb2SMarc Bonnici spm_secure_partition_exit(ec->c_rt_ctx, rc);
1485096aeb2SMarc Bonnici
1495096aeb2SMarc Bonnici panic();
1505096aeb2SMarc Bonnici }
1515096aeb2SMarc Bonnici
1525096aeb2SMarc Bonnici /*******************************************************************************
1535096aeb2SMarc Bonnici * Return FFA_ERROR with specified error code.
1545096aeb2SMarc Bonnici ******************************************************************************/
spmc_ffa_error_return(void * handle,int error_code)1555096aeb2SMarc Bonnici uint64_t spmc_ffa_error_return(void *handle, int error_code)
1565096aeb2SMarc Bonnici {
1575096aeb2SMarc Bonnici SMC_RET8(handle, FFA_ERROR,
1585096aeb2SMarc Bonnici FFA_TARGET_INFO_MBZ, error_code,
1595096aeb2SMarc Bonnici FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
1605096aeb2SMarc Bonnici FFA_PARAM_MBZ, FFA_PARAM_MBZ);
1615096aeb2SMarc Bonnici }
1625096aeb2SMarc Bonnici
1635096aeb2SMarc Bonnici /******************************************************************************
1645096aeb2SMarc Bonnici * Helper function to validate a secure partition ID to ensure it does not
1655096aeb2SMarc Bonnici * conflict with any other FF-A component and follows the convention to
1665096aeb2SMarc Bonnici * indicate it resides within the secure world.
1675096aeb2SMarc Bonnici ******************************************************************************/
is_ffa_secure_id_valid(uint16_t partition_id)1685096aeb2SMarc Bonnici bool is_ffa_secure_id_valid(uint16_t partition_id)
1695096aeb2SMarc Bonnici {
1707affa25cSMarc Bonnici struct el3_lp_desc *el3_lp_descs = get_el3_lp_array();
1717affa25cSMarc Bonnici
1725096aeb2SMarc Bonnici /* Ensure the ID is not the invalid partition ID. */
1735096aeb2SMarc Bonnici if (partition_id == INV_SP_ID) {
1745096aeb2SMarc Bonnici return false;
1755096aeb2SMarc Bonnici }
1765096aeb2SMarc Bonnici
1775096aeb2SMarc Bonnici /* Ensure the ID is not the SPMD ID. */
1785096aeb2SMarc Bonnici if (partition_id == SPMD_DIRECT_MSG_ENDPOINT_ID) {
1795096aeb2SMarc Bonnici return false;
1805096aeb2SMarc Bonnici }
1815096aeb2SMarc Bonnici
1825096aeb2SMarc Bonnici /*
1835096aeb2SMarc Bonnici * Ensure the ID follows the convention to indicate it resides
1845096aeb2SMarc Bonnici * in the secure world.
1855096aeb2SMarc Bonnici */
1865096aeb2SMarc Bonnici if (!ffa_is_secure_world_id(partition_id)) {
1875096aeb2SMarc Bonnici return false;
1885096aeb2SMarc Bonnici }
1895096aeb2SMarc Bonnici
1905096aeb2SMarc Bonnici /* Ensure we don't conflict with the SPMC partition ID. */
1915096aeb2SMarc Bonnici if (partition_id == FFA_SPMC_ID) {
1925096aeb2SMarc Bonnici return false;
1935096aeb2SMarc Bonnici }
1945096aeb2SMarc Bonnici
1955096aeb2SMarc Bonnici /* Ensure we do not already have an SP context with this ID. */
1965096aeb2SMarc Bonnici if (spmc_get_sp_ctx(partition_id)) {
1975096aeb2SMarc Bonnici return false;
1985096aeb2SMarc Bonnici }
1995096aeb2SMarc Bonnici
2007affa25cSMarc Bonnici /* Ensure we don't clash with any Logical SP's. */
2017affa25cSMarc Bonnici for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) {
2027affa25cSMarc Bonnici if (el3_lp_descs[i].sp_id == partition_id) {
2037affa25cSMarc Bonnici return false;
2047affa25cSMarc Bonnici }
2057affa25cSMarc Bonnici }
2067affa25cSMarc Bonnici
2075096aeb2SMarc Bonnici return true;
2085096aeb2SMarc Bonnici }
2095096aeb2SMarc Bonnici
2105096aeb2SMarc Bonnici /*******************************************************************************
21120fae0a7SMarc Bonnici * This function either forwards the request to the other world or returns
21220fae0a7SMarc Bonnici * with an ERET depending on the source of the call.
2137affa25cSMarc Bonnici * We can assume that the destination is for an entity at a lower exception
2147affa25cSMarc Bonnici * level as any messages destined for a logical SP resident in EL3 will have
2157affa25cSMarc Bonnici * already been taken care of by the SPMC before entering this function.
21620fae0a7SMarc Bonnici ******************************************************************************/
spmc_smc_return(uint32_t smc_fid,bool secure_origin,uint64_t x1,uint64_t x2,uint64_t x3,uint64_t x4,void * handle,void * cookie,uint64_t flags,uint16_t dst_id,uint32_t sp_ffa_version)21720fae0a7SMarc Bonnici static uint64_t spmc_smc_return(uint32_t smc_fid,
21820fae0a7SMarc Bonnici bool secure_origin,
21920fae0a7SMarc Bonnici uint64_t x1,
22020fae0a7SMarc Bonnici uint64_t x2,
22120fae0a7SMarc Bonnici uint64_t x3,
22220fae0a7SMarc Bonnici uint64_t x4,
22320fae0a7SMarc Bonnici void *handle,
22420fae0a7SMarc Bonnici void *cookie,
22520fae0a7SMarc Bonnici uint64_t flags,
226bb9fc8c0SJay Monkman uint16_t dst_id,
227bb9fc8c0SJay Monkman uint32_t sp_ffa_version)
22820fae0a7SMarc Bonnici {
22920fae0a7SMarc Bonnici /* If the destination is in the normal world always go via the SPMD. */
23020fae0a7SMarc Bonnici if (ffa_is_normal_world_id(dst_id)) {
23120fae0a7SMarc Bonnici return spmd_smc_handler(smc_fid, x1, x2, x3, x4,
232bb9fc8c0SJay Monkman cookie, handle, flags, sp_ffa_version);
23320fae0a7SMarc Bonnici }
23420fae0a7SMarc Bonnici /*
23520fae0a7SMarc Bonnici * If the caller is secure and we want to return to the secure world,
23620fae0a7SMarc Bonnici * ERET directly.
23720fae0a7SMarc Bonnici */
23820fae0a7SMarc Bonnici else if (secure_origin && ffa_is_secure_world_id(dst_id)) {
23920fae0a7SMarc Bonnici SMC_RET5(handle, smc_fid, x1, x2, x3, x4);
24020fae0a7SMarc Bonnici }
24120fae0a7SMarc Bonnici /* If we originated in the normal world then switch contexts. */
24220fae0a7SMarc Bonnici else if (!secure_origin && ffa_is_secure_world_id(dst_id)) {
24320fae0a7SMarc Bonnici return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2,
244bb9fc8c0SJay Monkman x3, x4, handle, flags, sp_ffa_version);
24520fae0a7SMarc Bonnici } else {
24620fae0a7SMarc Bonnici /* Unknown State. */
24720fae0a7SMarc Bonnici panic();
24820fae0a7SMarc Bonnici }
24920fae0a7SMarc Bonnici
25020fae0a7SMarc Bonnici /* Shouldn't be Reached. */
25120fae0a7SMarc Bonnici return 0;
25220fae0a7SMarc Bonnici }
25320fae0a7SMarc Bonnici
25420fae0a7SMarc Bonnici /*******************************************************************************
255c4db76f0SMarc Bonnici * FF-A ABI Handlers.
256c4db76f0SMarc Bonnici ******************************************************************************/
2579741327dSMarc Bonnici
2589741327dSMarc Bonnici /*******************************************************************************
2599741327dSMarc Bonnici * Helper function to validate arg2 as part of a direct message.
2609741327dSMarc Bonnici ******************************************************************************/
direct_msg_validate_arg2(uint64_t x2)2619741327dSMarc Bonnici static inline bool direct_msg_validate_arg2(uint64_t x2)
2629741327dSMarc Bonnici {
26359bd2ad8SMarc Bonnici /* Check message type. */
26459bd2ad8SMarc Bonnici if (x2 & FFA_FWK_MSG_BIT) {
26559bd2ad8SMarc Bonnici /* We have a framework message, ensure it is a known message. */
26659bd2ad8SMarc Bonnici if (x2 & ~(FFA_FWK_MSG_MASK | FFA_FWK_MSG_BIT)) {
26759bd2ad8SMarc Bonnici VERBOSE("Invalid message format 0x%lx.\n", x2);
2689741327dSMarc Bonnici return false;
2699741327dSMarc Bonnici }
27059bd2ad8SMarc Bonnici } else {
27159bd2ad8SMarc Bonnici /* We have a partition messages, ensure x2 is not set. */
27259bd2ad8SMarc Bonnici if (x2 != (uint64_t) 0) {
27359bd2ad8SMarc Bonnici VERBOSE("Arg2 MBZ for partition messages. (0x%lx).\n",
27459bd2ad8SMarc Bonnici x2);
27559bd2ad8SMarc Bonnici return false;
27659bd2ad8SMarc Bonnici }
27759bd2ad8SMarc Bonnici }
2789741327dSMarc Bonnici return true;
2799741327dSMarc Bonnici }
2809741327dSMarc Bonnici
2819741327dSMarc Bonnici /*******************************************************************************
28248fe24c5SMarc Bonnici * Helper function to validate the destination ID of a direct response.
28348fe24c5SMarc Bonnici ******************************************************************************/
direct_msg_validate_dst_id(uint16_t dst_id)28448fe24c5SMarc Bonnici static bool direct_msg_validate_dst_id(uint16_t dst_id)
28548fe24c5SMarc Bonnici {
28648fe24c5SMarc Bonnici struct secure_partition_desc *sp;
28748fe24c5SMarc Bonnici
28848fe24c5SMarc Bonnici /* Check if we're targeting a normal world partition. */
28948fe24c5SMarc Bonnici if (ffa_is_normal_world_id(dst_id)) {
29048fe24c5SMarc Bonnici return true;
29148fe24c5SMarc Bonnici }
29248fe24c5SMarc Bonnici
29348fe24c5SMarc Bonnici /* Or directed to the SPMC itself.*/
29448fe24c5SMarc Bonnici if (dst_id == FFA_SPMC_ID) {
29548fe24c5SMarc Bonnici return true;
29648fe24c5SMarc Bonnici }
29748fe24c5SMarc Bonnici
29848fe24c5SMarc Bonnici /* Otherwise ensure the SP exists. */
29948fe24c5SMarc Bonnici sp = spmc_get_sp_ctx(dst_id);
30048fe24c5SMarc Bonnici if (sp != NULL) {
30148fe24c5SMarc Bonnici return true;
30248fe24c5SMarc Bonnici }
30348fe24c5SMarc Bonnici
30448fe24c5SMarc Bonnici return false;
30548fe24c5SMarc Bonnici }
30648fe24c5SMarc Bonnici
30748fe24c5SMarc Bonnici /*******************************************************************************
30848fe24c5SMarc Bonnici * Helper function to validate the response from a Logical Partition.
30948fe24c5SMarc Bonnici ******************************************************************************/
direct_msg_validate_lp_resp(uint16_t origin_id,uint16_t lp_id,void * handle)31048fe24c5SMarc Bonnici static bool direct_msg_validate_lp_resp(uint16_t origin_id, uint16_t lp_id,
31148fe24c5SMarc Bonnici void *handle)
31248fe24c5SMarc Bonnici {
31348fe24c5SMarc Bonnici /* Retrieve populated Direct Response Arguments. */
31409a580b7SLevi Yun uint64_t smc_fid = SMC_GET_GP(handle, CTX_GPREG_X0);
31548fe24c5SMarc Bonnici uint64_t x1 = SMC_GET_GP(handle, CTX_GPREG_X1);
31648fe24c5SMarc Bonnici uint64_t x2 = SMC_GET_GP(handle, CTX_GPREG_X2);
31748fe24c5SMarc Bonnici uint16_t src_id = ffa_endpoint_source(x1);
31848fe24c5SMarc Bonnici uint16_t dst_id = ffa_endpoint_destination(x1);
31948fe24c5SMarc Bonnici
32048fe24c5SMarc Bonnici if (src_id != lp_id) {
32148fe24c5SMarc Bonnici ERROR("Invalid EL3 LP source ID (0x%x).\n", src_id);
32248fe24c5SMarc Bonnici return false;
32348fe24c5SMarc Bonnici }
32448fe24c5SMarc Bonnici
32548fe24c5SMarc Bonnici /*
32648fe24c5SMarc Bonnici * Check the destination ID is valid and ensure the LP is responding to
32748fe24c5SMarc Bonnici * the original request.
32848fe24c5SMarc Bonnici */
32948fe24c5SMarc Bonnici if ((!direct_msg_validate_dst_id(dst_id)) || (dst_id != origin_id)) {
33048fe24c5SMarc Bonnici ERROR("Invalid EL3 LP destination ID (0x%x).\n", dst_id);
33148fe24c5SMarc Bonnici return false;
33248fe24c5SMarc Bonnici }
33348fe24c5SMarc Bonnici
33409a580b7SLevi Yun if ((smc_fid != FFA_MSG_SEND_DIRECT_RESP2_SMC64) &&
33509a580b7SLevi Yun !direct_msg_validate_arg2(x2)) {
33648fe24c5SMarc Bonnici ERROR("Invalid EL3 LP message encoding.\n");
33748fe24c5SMarc Bonnici return false;
33848fe24c5SMarc Bonnici }
33948fe24c5SMarc Bonnici return true;
34048fe24c5SMarc Bonnici }
34148fe24c5SMarc Bonnici
34248fe24c5SMarc Bonnici /*******************************************************************************
34309a580b7SLevi Yun * Helper function to check that partition can receive direct msg or not.
34409a580b7SLevi Yun ******************************************************************************/
direct_msg_receivable(uint32_t properties,uint16_t dir_req_fnum)34509a580b7SLevi Yun static bool direct_msg_receivable(uint32_t properties, uint16_t dir_req_fnum)
34609a580b7SLevi Yun {
34709a580b7SLevi Yun if ((dir_req_fnum == FFA_FNUM_MSG_SEND_DIRECT_REQ &&
34809a580b7SLevi Yun ((properties & FFA_PARTITION_DIRECT_REQ_RECV) == 0U)) ||
34909a580b7SLevi Yun (dir_req_fnum == FFA_FNUM_MSG_SEND_DIRECT_REQ2 &&
35009a580b7SLevi Yun ((properties & FFA_PARTITION_DIRECT_REQ2_RECV) == 0U))) {
35109a580b7SLevi Yun return false;
35209a580b7SLevi Yun }
35309a580b7SLevi Yun
35409a580b7SLevi Yun return true;
35509a580b7SLevi Yun }
35609a580b7SLevi Yun
35709a580b7SLevi Yun /*******************************************************************************
358bb9fc8c0SJay Monkman * Helper function to obtain the FF-A version of the calling partition.
359bb9fc8c0SJay Monkman ******************************************************************************/
get_partition_ffa_version(bool secure_origin)360bb9fc8c0SJay Monkman uint32_t get_partition_ffa_version(bool secure_origin)
361bb9fc8c0SJay Monkman {
362bb9fc8c0SJay Monkman if (secure_origin) {
363bb9fc8c0SJay Monkman return spmc_get_current_sp_ctx()->ffa_version;
364bb9fc8c0SJay Monkman } else {
365bb9fc8c0SJay Monkman return spmc_get_hyp_ctx()->ffa_version;
366bb9fc8c0SJay Monkman }
367bb9fc8c0SJay Monkman }
368bb9fc8c0SJay Monkman
369bb9fc8c0SJay Monkman /*******************************************************************************
3709741327dSMarc Bonnici * Handle direct request messages and route to the appropriate destination.
3719741327dSMarc Bonnici ******************************************************************************/
direct_req_smc_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)3729741327dSMarc Bonnici static uint64_t direct_req_smc_handler(uint32_t smc_fid,
3739741327dSMarc Bonnici bool secure_origin,
3749741327dSMarc Bonnici uint64_t x1,
3759741327dSMarc Bonnici uint64_t x2,
3769741327dSMarc Bonnici uint64_t x3,
3779741327dSMarc Bonnici uint64_t x4,
3789741327dSMarc Bonnici void *cookie,
3799741327dSMarc Bonnici void *handle,
3809741327dSMarc Bonnici uint64_t flags)
3819741327dSMarc Bonnici {
38248fe24c5SMarc Bonnici uint16_t src_id = ffa_endpoint_source(x1);
3839741327dSMarc Bonnici uint16_t dst_id = ffa_endpoint_destination(x1);
38409a580b7SLevi Yun uint16_t dir_req_funcid;
3857affa25cSMarc Bonnici struct el3_lp_desc *el3_lp_descs;
3869741327dSMarc Bonnici struct secure_partition_desc *sp;
3879741327dSMarc Bonnici unsigned int idx;
388bb9fc8c0SJay Monkman uint32_t ffa_version = get_partition_ffa_version(secure_origin);
3899741327dSMarc Bonnici
39009a580b7SLevi Yun dir_req_funcid = (smc_fid != FFA_MSG_SEND_DIRECT_REQ2_SMC64) ?
39109a580b7SLevi Yun FFA_FNUM_MSG_SEND_DIRECT_REQ : FFA_FNUM_MSG_SEND_DIRECT_REQ2;
39209a580b7SLevi Yun
393bb9fc8c0SJay Monkman if ((dir_req_funcid == FFA_FNUM_MSG_SEND_DIRECT_REQ2) &&
394bb9fc8c0SJay Monkman ffa_version < MAKE_FFA_VERSION(U(1), U(2))) {
395bb9fc8c0SJay Monkman return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
396bb9fc8c0SJay Monkman }
397bb9fc8c0SJay Monkman
39809a580b7SLevi Yun /*
39909a580b7SLevi Yun * Sanity check for DIRECT_REQ:
40009a580b7SLevi Yun * Check if arg2 has been populated correctly based on message type
40109a580b7SLevi Yun */
40209a580b7SLevi Yun if ((dir_req_funcid == FFA_FNUM_MSG_SEND_DIRECT_REQ) &&
40309a580b7SLevi Yun !direct_msg_validate_arg2(x2)) {
40409a580b7SLevi Yun return spmc_ffa_error_return(handle, FFA_ERROR_INVALID_PARAMETER);
4059741327dSMarc Bonnici }
4069741327dSMarc Bonnici
40748fe24c5SMarc Bonnici /* Validate Sender is either the current SP or from the normal world. */
40848fe24c5SMarc Bonnici if ((secure_origin && src_id != spmc_get_current_sp_ctx()->sp_id) ||
40948fe24c5SMarc Bonnici (!secure_origin && !ffa_is_normal_world_id(src_id))) {
41048fe24c5SMarc Bonnici ERROR("Invalid direct request source ID (0x%x).\n", src_id);
41148fe24c5SMarc Bonnici return spmc_ffa_error_return(handle,
41248fe24c5SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
41348fe24c5SMarc Bonnici }
41448fe24c5SMarc Bonnici
4157affa25cSMarc Bonnici el3_lp_descs = get_el3_lp_array();
4167affa25cSMarc Bonnici
4177affa25cSMarc Bonnici /* Check if the request is destined for a Logical Partition. */
4187affa25cSMarc Bonnici for (unsigned int i = 0U; i < MAX_EL3_LP_DESCS_COUNT; i++) {
4197affa25cSMarc Bonnici if (el3_lp_descs[i].sp_id == dst_id) {
42009a580b7SLevi Yun if (!direct_msg_receivable(el3_lp_descs[i].properties, dir_req_funcid)) {
42109a580b7SLevi Yun return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
42209a580b7SLevi Yun }
42309a580b7SLevi Yun
42448fe24c5SMarc Bonnici uint64_t ret = el3_lp_descs[i].direct_req(
42548fe24c5SMarc Bonnici smc_fid, secure_origin, x1, x2,
42648fe24c5SMarc Bonnici x3, x4, cookie, handle, flags);
42748fe24c5SMarc Bonnici if (!direct_msg_validate_lp_resp(src_id, dst_id,
42848fe24c5SMarc Bonnici handle)) {
42948fe24c5SMarc Bonnici panic();
43048fe24c5SMarc Bonnici }
43148fe24c5SMarc Bonnici
43248fe24c5SMarc Bonnici /* Message checks out. */
43348fe24c5SMarc Bonnici return ret;
4347affa25cSMarc Bonnici }
4357affa25cSMarc Bonnici }
4367affa25cSMarc Bonnici
4379741327dSMarc Bonnici /*
4387affa25cSMarc Bonnici * If the request was not targeted to a LSP and from the secure world
4397affa25cSMarc Bonnici * then it is invalid since a SP cannot call into the Normal world and
4407affa25cSMarc Bonnici * there is no other SP to call into. If there are other SPs in future
4417affa25cSMarc Bonnici * then the partition runtime model would need to be validated as well.
4429741327dSMarc Bonnici */
4439741327dSMarc Bonnici if (secure_origin) {
4449741327dSMarc Bonnici VERBOSE("Direct request not supported to the Normal World.\n");
4459741327dSMarc Bonnici return spmc_ffa_error_return(handle,
4469741327dSMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
4479741327dSMarc Bonnici }
4489741327dSMarc Bonnici
4499741327dSMarc Bonnici /* Check if the SP ID is valid. */
4509741327dSMarc Bonnici sp = spmc_get_sp_ctx(dst_id);
4519741327dSMarc Bonnici if (sp == NULL) {
4529741327dSMarc Bonnici VERBOSE("Direct request to unknown partition ID (0x%x).\n",
4539741327dSMarc Bonnici dst_id);
4549741327dSMarc Bonnici return spmc_ffa_error_return(handle,
4559741327dSMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
4569741327dSMarc Bonnici }
4579741327dSMarc Bonnici
45809a580b7SLevi Yun if (!direct_msg_receivable(sp->properties, dir_req_funcid)) {
45909a580b7SLevi Yun return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
46009a580b7SLevi Yun }
46109a580b7SLevi Yun
4625ed8e255SNishant Sharma /* Protect the runtime state of a UP S-EL0 SP with a lock. */
4635ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
4645ed8e255SNishant Sharma spin_lock(&sp->rt_state_lock);
4655ed8e255SNishant Sharma }
4665ed8e255SNishant Sharma
4679741327dSMarc Bonnici /*
4689741327dSMarc Bonnici * Check that the target execution context is in a waiting state before
4699741327dSMarc Bonnici * forwarding the direct request to it.
4709741327dSMarc Bonnici */
4719741327dSMarc Bonnici idx = get_ec_index(sp);
4729741327dSMarc Bonnici if (sp->ec[idx].rt_state != RT_STATE_WAITING) {
4739741327dSMarc Bonnici VERBOSE("SP context on core%u is not waiting (%u).\n",
4749741327dSMarc Bonnici idx, sp->ec[idx].rt_model);
4755ed8e255SNishant Sharma
4765ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
4775ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
4785ed8e255SNishant Sharma }
4795ed8e255SNishant Sharma
4809741327dSMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_BUSY);
4819741327dSMarc Bonnici }
4829741327dSMarc Bonnici
4839741327dSMarc Bonnici /*
4849741327dSMarc Bonnici * Everything checks out so forward the request to the SP after updating
4859741327dSMarc Bonnici * its state and runtime model.
4869741327dSMarc Bonnici */
4879741327dSMarc Bonnici sp->ec[idx].rt_state = RT_STATE_RUNNING;
4889741327dSMarc Bonnici sp->ec[idx].rt_model = RT_MODEL_DIR_REQ;
48948fe24c5SMarc Bonnici sp->ec[idx].dir_req_origin_id = src_id;
49009a580b7SLevi Yun sp->ec[idx].dir_req_funcid = dir_req_funcid;
4915ed8e255SNishant Sharma
4925ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
4935ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
4945ed8e255SNishant Sharma }
4955ed8e255SNishant Sharma
4969741327dSMarc Bonnici return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
497bb9fc8c0SJay Monkman handle, cookie, flags, dst_id, sp->ffa_version);
4989741327dSMarc Bonnici }
4999741327dSMarc Bonnici
5009741327dSMarc Bonnici /*******************************************************************************
5019741327dSMarc Bonnici * Handle direct response messages and route to the appropriate destination.
5029741327dSMarc Bonnici ******************************************************************************/
direct_resp_smc_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)5039741327dSMarc Bonnici static uint64_t direct_resp_smc_handler(uint32_t smc_fid,
5049741327dSMarc Bonnici bool secure_origin,
5059741327dSMarc Bonnici uint64_t x1,
5069741327dSMarc Bonnici uint64_t x2,
5079741327dSMarc Bonnici uint64_t x3,
5089741327dSMarc Bonnici uint64_t x4,
5099741327dSMarc Bonnici void *cookie,
5109741327dSMarc Bonnici void *handle,
5119741327dSMarc Bonnici uint64_t flags)
5129741327dSMarc Bonnici {
5139741327dSMarc Bonnici uint16_t dst_id = ffa_endpoint_destination(x1);
51409a580b7SLevi Yun uint16_t dir_req_funcid;
5159741327dSMarc Bonnici struct secure_partition_desc *sp;
5169741327dSMarc Bonnici unsigned int idx;
5179741327dSMarc Bonnici
51809a580b7SLevi Yun dir_req_funcid = (smc_fid != FFA_MSG_SEND_DIRECT_RESP2_SMC64) ?
51909a580b7SLevi Yun FFA_FNUM_MSG_SEND_DIRECT_REQ : FFA_FNUM_MSG_SEND_DIRECT_REQ2;
52009a580b7SLevi Yun
5219741327dSMarc Bonnici /* Check if arg2 has been populated correctly based on message type. */
5229741327dSMarc Bonnici if (!direct_msg_validate_arg2(x2)) {
5239741327dSMarc Bonnici return spmc_ffa_error_return(handle,
5249741327dSMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
5259741327dSMarc Bonnici }
5269741327dSMarc Bonnici
5279741327dSMarc Bonnici /* Check that the response did not originate from the Normal world. */
5289741327dSMarc Bonnici if (!secure_origin) {
5299741327dSMarc Bonnici VERBOSE("Direct Response not supported from Normal World.\n");
5309741327dSMarc Bonnici return spmc_ffa_error_return(handle,
5319741327dSMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
5329741327dSMarc Bonnici }
5339741327dSMarc Bonnici
5349741327dSMarc Bonnici /*
5359741327dSMarc Bonnici * Check that the response is either targeted to the Normal world or the
5369741327dSMarc Bonnici * SPMC e.g. a PM response.
5379741327dSMarc Bonnici */
53848fe24c5SMarc Bonnici if (!direct_msg_validate_dst_id(dst_id)) {
5399741327dSMarc Bonnici VERBOSE("Direct response to invalid partition ID (0x%x).\n",
5409741327dSMarc Bonnici dst_id);
5419741327dSMarc Bonnici return spmc_ffa_error_return(handle,
5429741327dSMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
5439741327dSMarc Bonnici }
5449741327dSMarc Bonnici
5459741327dSMarc Bonnici /* Obtain the SP descriptor and update its runtime state. */
5469741327dSMarc Bonnici sp = spmc_get_sp_ctx(ffa_endpoint_source(x1));
5479741327dSMarc Bonnici if (sp == NULL) {
5489741327dSMarc Bonnici VERBOSE("Direct response to unknown partition ID (0x%x).\n",
5499741327dSMarc Bonnici dst_id);
5509741327dSMarc Bonnici return spmc_ffa_error_return(handle,
5519741327dSMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
5529741327dSMarc Bonnici }
5539741327dSMarc Bonnici
5545ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
5555ed8e255SNishant Sharma spin_lock(&sp->rt_state_lock);
5565ed8e255SNishant Sharma }
5575ed8e255SNishant Sharma
5589741327dSMarc Bonnici /* Sanity check state is being tracked correctly in the SPMC. */
5599741327dSMarc Bonnici idx = get_ec_index(sp);
5609741327dSMarc Bonnici assert(sp->ec[idx].rt_state == RT_STATE_RUNNING);
5619741327dSMarc Bonnici
5629741327dSMarc Bonnici /* Ensure SP execution context was in the right runtime model. */
5639741327dSMarc Bonnici if (sp->ec[idx].rt_model != RT_MODEL_DIR_REQ) {
5649741327dSMarc Bonnici VERBOSE("SP context on core%u not handling direct req (%u).\n",
5659741327dSMarc Bonnici idx, sp->ec[idx].rt_model);
5665ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
5675ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
5685ed8e255SNishant Sharma }
5699741327dSMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
5709741327dSMarc Bonnici }
5719741327dSMarc Bonnici
57209a580b7SLevi Yun if (dir_req_funcid != sp->ec[idx].dir_req_funcid) {
57309a580b7SLevi Yun WARN("Unmatched direct req/resp func id. req:%x, resp:%x on core%u.\n",
57409a580b7SLevi Yun sp->ec[idx].dir_req_funcid, (smc_fid & FUNCID_NUM_MASK), idx);
57509a580b7SLevi Yun if (sp->runtime_el == S_EL0) {
57609a580b7SLevi Yun spin_unlock(&sp->rt_state_lock);
57709a580b7SLevi Yun }
57809a580b7SLevi Yun return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
57909a580b7SLevi Yun }
58009a580b7SLevi Yun
58148fe24c5SMarc Bonnici if (sp->ec[idx].dir_req_origin_id != dst_id) {
58248fe24c5SMarc Bonnici WARN("Invalid direct resp partition ID 0x%x != 0x%x on core%u.\n",
58348fe24c5SMarc Bonnici dst_id, sp->ec[idx].dir_req_origin_id, idx);
5845ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
5855ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
5865ed8e255SNishant Sharma }
58748fe24c5SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
58848fe24c5SMarc Bonnici }
58948fe24c5SMarc Bonnici
5909741327dSMarc Bonnici /* Update the state of the SP execution context. */
5919741327dSMarc Bonnici sp->ec[idx].rt_state = RT_STATE_WAITING;
5929741327dSMarc Bonnici
59348fe24c5SMarc Bonnici /* Clear the ongoing direct request ID. */
59448fe24c5SMarc Bonnici sp->ec[idx].dir_req_origin_id = INV_SP_ID;
59548fe24c5SMarc Bonnici
59609a580b7SLevi Yun /* Clear the ongoing direct request message version. */
59709a580b7SLevi Yun sp->ec[idx].dir_req_funcid = 0U;
59809a580b7SLevi Yun
5995ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
6005ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
6015ed8e255SNishant Sharma }
6025ed8e255SNishant Sharma
6039741327dSMarc Bonnici /*
6049741327dSMarc Bonnici * If the receiver is not the SPMC then forward the response to the
6059741327dSMarc Bonnici * Normal world.
6069741327dSMarc Bonnici */
6079741327dSMarc Bonnici if (dst_id == FFA_SPMC_ID) {
6089741327dSMarc Bonnici spmc_sp_synchronous_exit(&sp->ec[idx], x4);
6099741327dSMarc Bonnici /* Should not get here. */
6109741327dSMarc Bonnici panic();
6119741327dSMarc Bonnici }
6129741327dSMarc Bonnici
6139741327dSMarc Bonnici return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
614bb9fc8c0SJay Monkman handle, cookie, flags, dst_id, sp->ffa_version);
6159741327dSMarc Bonnici }
6169741327dSMarc Bonnici
617c4db76f0SMarc Bonnici /*******************************************************************************
618c4db76f0SMarc Bonnici * This function handles the FFA_MSG_WAIT SMC to allow an SP to relinquish its
619c4db76f0SMarc Bonnici * cycles.
620c4db76f0SMarc Bonnici ******************************************************************************/
msg_wait_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)621c4db76f0SMarc Bonnici static uint64_t msg_wait_handler(uint32_t smc_fid,
622c4db76f0SMarc Bonnici bool secure_origin,
623c4db76f0SMarc Bonnici uint64_t x1,
624c4db76f0SMarc Bonnici uint64_t x2,
625c4db76f0SMarc Bonnici uint64_t x3,
626c4db76f0SMarc Bonnici uint64_t x4,
627c4db76f0SMarc Bonnici void *cookie,
628c4db76f0SMarc Bonnici void *handle,
629c4db76f0SMarc Bonnici uint64_t flags)
630c4db76f0SMarc Bonnici {
631c4db76f0SMarc Bonnici struct secure_partition_desc *sp;
632c4db76f0SMarc Bonnici unsigned int idx;
633c4db76f0SMarc Bonnici
634c4db76f0SMarc Bonnici /*
635c4db76f0SMarc Bonnici * Check that the response did not originate from the Normal world as
636c4db76f0SMarc Bonnici * only the secure world can call this ABI.
637c4db76f0SMarc Bonnici */
638c4db76f0SMarc Bonnici if (!secure_origin) {
639c4db76f0SMarc Bonnici VERBOSE("Normal world cannot call FFA_MSG_WAIT.\n");
640c4db76f0SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
641c4db76f0SMarc Bonnici }
642c4db76f0SMarc Bonnici
643c4db76f0SMarc Bonnici /* Get the descriptor of the SP that invoked FFA_MSG_WAIT. */
644c4db76f0SMarc Bonnici sp = spmc_get_current_sp_ctx();
645c4db76f0SMarc Bonnici if (sp == NULL) {
646c4db76f0SMarc Bonnici return spmc_ffa_error_return(handle,
647c4db76f0SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
648c4db76f0SMarc Bonnici }
649c4db76f0SMarc Bonnici
650c4db76f0SMarc Bonnici /*
651c4db76f0SMarc Bonnici * Get the execution context of the SP that invoked FFA_MSG_WAIT.
652c4db76f0SMarc Bonnici */
653c4db76f0SMarc Bonnici idx = get_ec_index(sp);
6545ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
6555ed8e255SNishant Sharma spin_lock(&sp->rt_state_lock);
6565ed8e255SNishant Sharma }
657c4db76f0SMarc Bonnici
658c4db76f0SMarc Bonnici /* Ensure SP execution context was in the right runtime model. */
659c4db76f0SMarc Bonnici if (sp->ec[idx].rt_model == RT_MODEL_DIR_REQ) {
6605ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
6615ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
6625ed8e255SNishant Sharma }
663c4db76f0SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
664c4db76f0SMarc Bonnici }
665c4db76f0SMarc Bonnici
666c4db76f0SMarc Bonnici /* Sanity check the state is being tracked correctly in the SPMC. */
667c4db76f0SMarc Bonnici assert(sp->ec[idx].rt_state == RT_STATE_RUNNING);
668c4db76f0SMarc Bonnici
669c4db76f0SMarc Bonnici /*
670c4db76f0SMarc Bonnici * Perform a synchronous exit if the partition was initialising. The
671c4db76f0SMarc Bonnici * state is updated after the exit.
672c4db76f0SMarc Bonnici */
673c4db76f0SMarc Bonnici if (sp->ec[idx].rt_model == RT_MODEL_INIT) {
6745ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
6755ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
6765ed8e255SNishant Sharma }
677c4db76f0SMarc Bonnici spmc_sp_synchronous_exit(&sp->ec[idx], x4);
678c4db76f0SMarc Bonnici /* Should not get here */
679c4db76f0SMarc Bonnici panic();
680c4db76f0SMarc Bonnici }
681c4db76f0SMarc Bonnici
682c4db76f0SMarc Bonnici /* Update the state of the SP execution context. */
683c4db76f0SMarc Bonnici sp->ec[idx].rt_state = RT_STATE_WAITING;
684c4db76f0SMarc Bonnici
685c4db76f0SMarc Bonnici /* Resume normal world if a secure interrupt was handled. */
686c4db76f0SMarc Bonnici if (sp->ec[idx].rt_model == RT_MODEL_INTR) {
6875ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
6885ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
6895ed8e255SNishant Sharma }
6905ed8e255SNishant Sharma
691a0a7f158SAndrei Homescu return spmd_smc_switch_state(FFA_NORMAL_WORLD_RESUME, secure_origin,
692a0a7f158SAndrei Homescu FFA_PARAM_MBZ, FFA_PARAM_MBZ,
693a0a7f158SAndrei Homescu FFA_PARAM_MBZ, FFA_PARAM_MBZ,
694bb9fc8c0SJay Monkman handle, flags, sp->ffa_version);
695c4db76f0SMarc Bonnici }
696c4db76f0SMarc Bonnici
6975ed8e255SNishant Sharma /* Protect the runtime state of a S-EL0 SP with a lock. */
6985ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
6995ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
7005ed8e255SNishant Sharma }
7015ed8e255SNishant Sharma
702c4db76f0SMarc Bonnici /* Forward the response to the Normal world. */
703c4db76f0SMarc Bonnici return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
704bb9fc8c0SJay Monkman handle, cookie, flags, FFA_NWD_ID, sp->ffa_version);
705c4db76f0SMarc Bonnici }
706c4db76f0SMarc Bonnici
ffa_error_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)707d663fe7aSMarc Bonnici static uint64_t ffa_error_handler(uint32_t smc_fid,
708d663fe7aSMarc Bonnici bool secure_origin,
709d663fe7aSMarc Bonnici uint64_t x1,
710d663fe7aSMarc Bonnici uint64_t x2,
711d663fe7aSMarc Bonnici uint64_t x3,
712d663fe7aSMarc Bonnici uint64_t x4,
713d663fe7aSMarc Bonnici void *cookie,
714d663fe7aSMarc Bonnici void *handle,
715d663fe7aSMarc Bonnici uint64_t flags)
716d663fe7aSMarc Bonnici {
717d663fe7aSMarc Bonnici struct secure_partition_desc *sp;
718d663fe7aSMarc Bonnici unsigned int idx;
719e1168bc3SLevi Yun uint16_t dst_id = ffa_endpoint_destination(x1);
720e1168bc3SLevi Yun bool cancel_dir_req = false;
721d663fe7aSMarc Bonnici
722d663fe7aSMarc Bonnici /* Check that the response did not originate from the Normal world. */
723d663fe7aSMarc Bonnici if (!secure_origin) {
724d663fe7aSMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
725d663fe7aSMarc Bonnici }
726d663fe7aSMarc Bonnici
727d663fe7aSMarc Bonnici /* Get the descriptor of the SP that invoked FFA_ERROR. */
728d663fe7aSMarc Bonnici sp = spmc_get_current_sp_ctx();
729d663fe7aSMarc Bonnici if (sp == NULL) {
730d663fe7aSMarc Bonnici return spmc_ffa_error_return(handle,
731d663fe7aSMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
732d663fe7aSMarc Bonnici }
733d663fe7aSMarc Bonnici
734d663fe7aSMarc Bonnici /* Get the execution context of the SP that invoked FFA_ERROR. */
735d663fe7aSMarc Bonnici idx = get_ec_index(sp);
736d663fe7aSMarc Bonnici
737d663fe7aSMarc Bonnici /*
738d663fe7aSMarc Bonnici * We only expect FFA_ERROR to be received during SP initialisation
739d663fe7aSMarc Bonnici * otherwise this is an invalid call.
740d663fe7aSMarc Bonnici */
741d663fe7aSMarc Bonnici if (sp->ec[idx].rt_model == RT_MODEL_INIT) {
742d663fe7aSMarc Bonnici ERROR("SP 0x%x failed to initialize.\n", sp->sp_id);
743d663fe7aSMarc Bonnici spmc_sp_synchronous_exit(&sp->ec[idx], x2);
744d663fe7aSMarc Bonnici /* Should not get here. */
745d663fe7aSMarc Bonnici panic();
746d663fe7aSMarc Bonnici }
747d663fe7aSMarc Bonnici
748e1168bc3SLevi Yun if (sp->runtime_el == S_EL0) {
749e1168bc3SLevi Yun spin_lock(&sp->rt_state_lock);
750e1168bc3SLevi Yun }
751e1168bc3SLevi Yun
752e1168bc3SLevi Yun if (sp->ec[idx].rt_state == RT_STATE_RUNNING &&
753e1168bc3SLevi Yun sp->ec[idx].rt_model == RT_MODEL_DIR_REQ) {
754e1168bc3SLevi Yun sp->ec[idx].rt_state = RT_STATE_WAITING;
755e1168bc3SLevi Yun sp->ec[idx].dir_req_origin_id = INV_SP_ID;
756e1168bc3SLevi Yun sp->ec[idx].dir_req_funcid = 0x00;
757e1168bc3SLevi Yun cancel_dir_req = true;
758e1168bc3SLevi Yun }
759e1168bc3SLevi Yun
760e1168bc3SLevi Yun if (sp->runtime_el == S_EL0) {
761e1168bc3SLevi Yun spin_unlock(&sp->rt_state_lock);
762e1168bc3SLevi Yun }
763e1168bc3SLevi Yun
764e1168bc3SLevi Yun if (cancel_dir_req) {
765e1168bc3SLevi Yun if (dst_id == FFA_SPMC_ID) {
766e1168bc3SLevi Yun spmc_sp_synchronous_exit(&sp->ec[idx], x4);
767e1168bc3SLevi Yun /* Should not get here. */
768e1168bc3SLevi Yun panic();
769e1168bc3SLevi Yun } else
770e1168bc3SLevi Yun return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
771bb9fc8c0SJay Monkman handle, cookie, flags, dst_id, sp->ffa_version);
772e1168bc3SLevi Yun }
773e1168bc3SLevi Yun
774d663fe7aSMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
775d663fe7aSMarc Bonnici }
776d663fe7aSMarc Bonnici
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)7770c7707fdSMarc Bonnici static uint64_t ffa_version_handler(uint32_t smc_fid,
7780c7707fdSMarc Bonnici bool secure_origin,
7790c7707fdSMarc Bonnici uint64_t x1,
7800c7707fdSMarc Bonnici uint64_t x2,
7810c7707fdSMarc Bonnici uint64_t x3,
7820c7707fdSMarc Bonnici uint64_t x4,
7830c7707fdSMarc Bonnici void *cookie,
7840c7707fdSMarc Bonnici void *handle,
7850c7707fdSMarc Bonnici uint64_t flags)
7860c7707fdSMarc Bonnici {
7870c7707fdSMarc Bonnici uint32_t requested_version = x1 & FFA_VERSION_MASK;
7880c7707fdSMarc Bonnici
7890c7707fdSMarc Bonnici if (requested_version & FFA_VERSION_BIT31_MASK) {
7900c7707fdSMarc Bonnici /* Invalid encoding, return an error. */
7910c7707fdSMarc Bonnici SMC_RET1(handle, FFA_ERROR_NOT_SUPPORTED);
7920c7707fdSMarc Bonnici /* Execution stops here. */
7930c7707fdSMarc Bonnici }
7940c7707fdSMarc Bonnici
7950c7707fdSMarc Bonnici /* Determine the caller to store the requested version. */
7960c7707fdSMarc Bonnici if (secure_origin) {
7970c7707fdSMarc Bonnici /*
7980c7707fdSMarc Bonnici * Ensure that the SP is reporting the same version as
7990c7707fdSMarc Bonnici * specified in its manifest. If these do not match there is
8000c7707fdSMarc Bonnici * something wrong with the SP.
8010c7707fdSMarc Bonnici * TODO: Should we abort the SP? For now assert this is not
8020c7707fdSMarc Bonnici * case.
8030c7707fdSMarc Bonnici */
8040c7707fdSMarc Bonnici assert(requested_version ==
8050c7707fdSMarc Bonnici spmc_get_current_sp_ctx()->ffa_version);
8060c7707fdSMarc Bonnici } else {
8070c7707fdSMarc Bonnici /*
8080c7707fdSMarc Bonnici * If this is called by the normal world, record this
8090c7707fdSMarc Bonnici * information in its descriptor.
8100c7707fdSMarc Bonnici */
8110c7707fdSMarc Bonnici spmc_get_hyp_ctx()->ffa_version = requested_version;
8120c7707fdSMarc Bonnici }
8130c7707fdSMarc Bonnici
814dd87b735SJ-Alves SMC_RET1(handle, MAKE_FFA_VERSION(FFA_VERSION_SPMC_MAJOR,
815dd87b735SJ-Alves FFA_VERSION_SPMC_MINOR));
8160c7707fdSMarc Bonnici }
8170c7707fdSMarc Bonnici
rxtx_map_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)8181a752245SMarc Bonnici static uint64_t rxtx_map_handler(uint32_t smc_fid,
8191a752245SMarc Bonnici bool secure_origin,
8201a752245SMarc Bonnici uint64_t x1,
8211a752245SMarc Bonnici uint64_t x2,
8221a752245SMarc Bonnici uint64_t x3,
8231a752245SMarc Bonnici uint64_t x4,
8241a752245SMarc Bonnici void *cookie,
8251a752245SMarc Bonnici void *handle,
8261a752245SMarc Bonnici uint64_t flags)
8271a752245SMarc Bonnici {
8281a752245SMarc Bonnici int ret;
8291a752245SMarc Bonnici uint32_t error_code;
8301a752245SMarc Bonnici uint32_t mem_atts = secure_origin ? MT_SECURE : MT_NS;
8311a752245SMarc Bonnici struct mailbox *mbox;
8321a752245SMarc Bonnici uintptr_t tx_address = x1;
8331a752245SMarc Bonnici uintptr_t rx_address = x2;
8341a752245SMarc Bonnici uint32_t page_count = x3 & FFA_RXTX_PAGE_COUNT_MASK; /* Bits [5:0] */
8351a752245SMarc Bonnici uint32_t buf_size = page_count * FFA_PAGE_SIZE;
8361a752245SMarc Bonnici
8371a752245SMarc Bonnici /*
8381a752245SMarc Bonnici * The SPMC does not support mapping of VM RX/TX pairs to facilitate
8391a752245SMarc Bonnici * indirect messaging with SPs. Check if the Hypervisor has invoked this
8401a752245SMarc Bonnici * ABI on behalf of a VM and reject it if this is the case.
8411a752245SMarc Bonnici */
8421a752245SMarc Bonnici if (tx_address == 0 || rx_address == 0) {
8431a752245SMarc Bonnici WARN("Mapping RX/TX Buffers on behalf of VM not supported.\n");
8441a752245SMarc Bonnici return spmc_ffa_error_return(handle,
8451a752245SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
8461a752245SMarc Bonnici }
8471a752245SMarc Bonnici
8481a752245SMarc Bonnici /* Ensure the specified buffers are not the same. */
8491a752245SMarc Bonnici if (tx_address == rx_address) {
8501a752245SMarc Bonnici WARN("TX Buffer must not be the same as RX Buffer.\n");
8511a752245SMarc Bonnici return spmc_ffa_error_return(handle,
8521a752245SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
8531a752245SMarc Bonnici }
8541a752245SMarc Bonnici
8551a752245SMarc Bonnici /* Ensure the buffer size is not 0. */
8561a752245SMarc Bonnici if (buf_size == 0U) {
8571a752245SMarc Bonnici WARN("Buffer size must not be 0\n");
8581a752245SMarc Bonnici return spmc_ffa_error_return(handle,
8591a752245SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
8601a752245SMarc Bonnici }
8611a752245SMarc Bonnici
8621a752245SMarc Bonnici /*
8631a752245SMarc Bonnici * Ensure the buffer size is a multiple of the translation granule size
8641a752245SMarc Bonnici * in TF-A.
8651a752245SMarc Bonnici */
8661a752245SMarc Bonnici if (buf_size % PAGE_SIZE != 0U) {
8671a752245SMarc Bonnici WARN("Buffer size must be aligned to translation granule.\n");
8681a752245SMarc Bonnici return spmc_ffa_error_return(handle,
8691a752245SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
8701a752245SMarc Bonnici }
8711a752245SMarc Bonnici
8721a752245SMarc Bonnici /* Obtain the RX/TX buffer pair descriptor. */
8731a752245SMarc Bonnici mbox = spmc_get_mbox_desc(secure_origin);
8741a752245SMarc Bonnici
8751a752245SMarc Bonnici spin_lock(&mbox->lock);
8761a752245SMarc Bonnici
8771a752245SMarc Bonnici /* Check if buffers have already been mapped. */
8781a752245SMarc Bonnici if (mbox->rx_buffer != 0 || mbox->tx_buffer != 0) {
8791a752245SMarc Bonnici WARN("RX/TX Buffers already mapped (%p/%p)\n",
8801a752245SMarc Bonnici (void *) mbox->rx_buffer, (void *)mbox->tx_buffer);
8811a752245SMarc Bonnici error_code = FFA_ERROR_DENIED;
8821a752245SMarc Bonnici goto err;
8831a752245SMarc Bonnici }
8841a752245SMarc Bonnici
8851a752245SMarc Bonnici /* memmap the TX buffer as read only. */
8861a752245SMarc Bonnici ret = mmap_add_dynamic_region(tx_address, /* PA */
8871a752245SMarc Bonnici tx_address, /* VA */
8881a752245SMarc Bonnici buf_size, /* size */
8891a752245SMarc Bonnici mem_atts | MT_RO_DATA); /* attrs */
8901a752245SMarc Bonnici if (ret != 0) {
8911a752245SMarc Bonnici /* Return the correct error code. */
8921a752245SMarc Bonnici error_code = (ret == -ENOMEM) ? FFA_ERROR_NO_MEMORY :
8931a752245SMarc Bonnici FFA_ERROR_INVALID_PARAMETER;
8941a752245SMarc Bonnici WARN("Unable to map TX buffer: %d\n", error_code);
8951a752245SMarc Bonnici goto err;
8961a752245SMarc Bonnici }
8971a752245SMarc Bonnici
8981a752245SMarc Bonnici /* memmap the RX buffer as read write. */
8991a752245SMarc Bonnici ret = mmap_add_dynamic_region(rx_address, /* PA */
9001a752245SMarc Bonnici rx_address, /* VA */
9011a752245SMarc Bonnici buf_size, /* size */
9021a752245SMarc Bonnici mem_atts | MT_RW_DATA); /* attrs */
9031a752245SMarc Bonnici
9041a752245SMarc Bonnici if (ret != 0) {
9051a752245SMarc Bonnici error_code = (ret == -ENOMEM) ? FFA_ERROR_NO_MEMORY :
9061a752245SMarc Bonnici FFA_ERROR_INVALID_PARAMETER;
9071a752245SMarc Bonnici WARN("Unable to map RX buffer: %d\n", error_code);
9081a752245SMarc Bonnici /* Unmap the TX buffer again. */
9091a752245SMarc Bonnici mmap_remove_dynamic_region(tx_address, buf_size);
9101a752245SMarc Bonnici goto err;
9111a752245SMarc Bonnici }
9121a752245SMarc Bonnici
9131a752245SMarc Bonnici mbox->tx_buffer = (void *) tx_address;
9141a752245SMarc Bonnici mbox->rx_buffer = (void *) rx_address;
9151a752245SMarc Bonnici mbox->rxtx_page_count = page_count;
9161a752245SMarc Bonnici spin_unlock(&mbox->lock);
9171a752245SMarc Bonnici
9181a752245SMarc Bonnici SMC_RET1(handle, FFA_SUCCESS_SMC32);
9191a752245SMarc Bonnici /* Execution stops here. */
9201a752245SMarc Bonnici err:
9211a752245SMarc Bonnici spin_unlock(&mbox->lock);
9221a752245SMarc Bonnici return spmc_ffa_error_return(handle, error_code);
9231a752245SMarc Bonnici }
9241a752245SMarc Bonnici
rxtx_unmap_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)9251a752245SMarc Bonnici static uint64_t rxtx_unmap_handler(uint32_t smc_fid,
9261a752245SMarc Bonnici bool secure_origin,
9271a752245SMarc Bonnici uint64_t x1,
9281a752245SMarc Bonnici uint64_t x2,
9291a752245SMarc Bonnici uint64_t x3,
9301a752245SMarc Bonnici uint64_t x4,
9311a752245SMarc Bonnici void *cookie,
9321a752245SMarc Bonnici void *handle,
9331a752245SMarc Bonnici uint64_t flags)
9341a752245SMarc Bonnici {
9351a752245SMarc Bonnici struct mailbox *mbox = spmc_get_mbox_desc(secure_origin);
9361a752245SMarc Bonnici uint32_t buf_size = mbox->rxtx_page_count * FFA_PAGE_SIZE;
9371a752245SMarc Bonnici
9381a752245SMarc Bonnici /*
9391a752245SMarc Bonnici * The SPMC does not support mapping of VM RX/TX pairs to facilitate
9401a752245SMarc Bonnici * indirect messaging with SPs. Check if the Hypervisor has invoked this
9411a752245SMarc Bonnici * ABI on behalf of a VM and reject it if this is the case.
9421a752245SMarc Bonnici */
9431a752245SMarc Bonnici if (x1 != 0UL) {
9441a752245SMarc Bonnici return spmc_ffa_error_return(handle,
9451a752245SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
9461a752245SMarc Bonnici }
9471a752245SMarc Bonnici
9481a752245SMarc Bonnici spin_lock(&mbox->lock);
9491a752245SMarc Bonnici
9501a752245SMarc Bonnici /* Check if buffers are currently mapped. */
9511a752245SMarc Bonnici if (mbox->rx_buffer == 0 || mbox->tx_buffer == 0) {
9521a752245SMarc Bonnici spin_unlock(&mbox->lock);
9531a752245SMarc Bonnici return spmc_ffa_error_return(handle,
9541a752245SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
9551a752245SMarc Bonnici }
9561a752245SMarc Bonnici
9571a752245SMarc Bonnici /* Unmap RX Buffer */
9581a752245SMarc Bonnici if (mmap_remove_dynamic_region((uintptr_t) mbox->rx_buffer,
9591a752245SMarc Bonnici buf_size) != 0) {
9601a752245SMarc Bonnici WARN("Unable to unmap RX buffer!\n");
9611a752245SMarc Bonnici }
9621a752245SMarc Bonnici
9631a752245SMarc Bonnici mbox->rx_buffer = 0;
9641a752245SMarc Bonnici
9651a752245SMarc Bonnici /* Unmap TX Buffer */
9661a752245SMarc Bonnici if (mmap_remove_dynamic_region((uintptr_t) mbox->tx_buffer,
9671a752245SMarc Bonnici buf_size) != 0) {
9681a752245SMarc Bonnici WARN("Unable to unmap TX buffer!\n");
9691a752245SMarc Bonnici }
9701a752245SMarc Bonnici
9711a752245SMarc Bonnici mbox->tx_buffer = 0;
9721a752245SMarc Bonnici mbox->rxtx_page_count = 0;
9731a752245SMarc Bonnici
9741a752245SMarc Bonnici spin_unlock(&mbox->lock);
9751a752245SMarc Bonnici SMC_RET1(handle, FFA_SUCCESS_SMC32);
9761a752245SMarc Bonnici }
9771a752245SMarc Bonnici
978f74e2772SMarc Bonnici /*
97962cd8f31SMarc Bonnici * Helper function to populate the properties field of a Partition Info Get
98062cd8f31SMarc Bonnici * descriptor.
98162cd8f31SMarc Bonnici */
98262cd8f31SMarc Bonnici static uint32_t
partition_info_get_populate_properties(uint32_t sp_properties,enum sp_execution_state sp_ec_state)98362cd8f31SMarc Bonnici partition_info_get_populate_properties(uint32_t sp_properties,
98462cd8f31SMarc Bonnici enum sp_execution_state sp_ec_state)
98562cd8f31SMarc Bonnici {
98662cd8f31SMarc Bonnici uint32_t properties = sp_properties;
98762cd8f31SMarc Bonnici uint32_t ec_state;
98862cd8f31SMarc Bonnici
98962cd8f31SMarc Bonnici /* Determine the execution state of the SP. */
99062cd8f31SMarc Bonnici ec_state = sp_ec_state == SP_STATE_AARCH64 ?
99162cd8f31SMarc Bonnici FFA_PARTITION_INFO_GET_AARCH64_STATE :
99262cd8f31SMarc Bonnici FFA_PARTITION_INFO_GET_AARCH32_STATE;
99362cd8f31SMarc Bonnici
99462cd8f31SMarc Bonnici properties |= ec_state << FFA_PARTITION_INFO_GET_EXEC_STATE_SHIFT;
99562cd8f31SMarc Bonnici
99662cd8f31SMarc Bonnici return properties;
99762cd8f31SMarc Bonnici }
99862cd8f31SMarc Bonnici
99962cd8f31SMarc Bonnici /*
1000f74e2772SMarc Bonnici * Collate the partition information in a v1.1 partition information
1001f74e2772SMarc Bonnici * descriptor format, this will be converter later if required.
1002f74e2772SMarc Bonnici */
partition_info_get_handler_v1_1(uint32_t * uuid,struct ffa_partition_info_v1_1 * partitions,uint32_t max_partitions,uint32_t * partition_count)1003f74e2772SMarc Bonnici static int partition_info_get_handler_v1_1(uint32_t *uuid,
1004f74e2772SMarc Bonnici struct ffa_partition_info_v1_1
1005f74e2772SMarc Bonnici *partitions,
1006f74e2772SMarc Bonnici uint32_t max_partitions,
1007f74e2772SMarc Bonnici uint32_t *partition_count)
1008f74e2772SMarc Bonnici {
1009f74e2772SMarc Bonnici uint32_t index;
1010f74e2772SMarc Bonnici struct ffa_partition_info_v1_1 *desc;
1011f74e2772SMarc Bonnici bool null_uuid = is_null_uuid(uuid);
1012f74e2772SMarc Bonnici struct el3_lp_desc *el3_lp_descs = get_el3_lp_array();
1013f74e2772SMarc Bonnici
1014f74e2772SMarc Bonnici /* Deal with Logical Partitions. */
1015f74e2772SMarc Bonnici for (index = 0U; index < EL3_LP_DESCS_COUNT; index++) {
1016f74e2772SMarc Bonnici if (null_uuid || uuid_match(uuid, el3_lp_descs[index].uuid)) {
1017f74e2772SMarc Bonnici /* Found a matching UUID, populate appropriately. */
1018f74e2772SMarc Bonnici if (*partition_count >= max_partitions) {
1019f74e2772SMarc Bonnici return FFA_ERROR_NO_MEMORY;
1020f74e2772SMarc Bonnici }
1021f74e2772SMarc Bonnici
1022f74e2772SMarc Bonnici desc = &partitions[*partition_count];
1023f74e2772SMarc Bonnici desc->ep_id = el3_lp_descs[index].sp_id;
1024f74e2772SMarc Bonnici desc->execution_ctx_count = PLATFORM_CORE_COUNT;
102562cd8f31SMarc Bonnici /* LSPs must be AArch64. */
102662cd8f31SMarc Bonnici desc->properties =
102762cd8f31SMarc Bonnici partition_info_get_populate_properties(
102862cd8f31SMarc Bonnici el3_lp_descs[index].properties,
102962cd8f31SMarc Bonnici SP_STATE_AARCH64);
103062cd8f31SMarc Bonnici
1031f74e2772SMarc Bonnici if (null_uuid) {
1032f74e2772SMarc Bonnici copy_uuid(desc->uuid, el3_lp_descs[index].uuid);
1033f74e2772SMarc Bonnici }
1034f74e2772SMarc Bonnici (*partition_count)++;
1035f74e2772SMarc Bonnici }
1036f74e2772SMarc Bonnici }
1037f74e2772SMarc Bonnici
1038f74e2772SMarc Bonnici /* Deal with physical SP's. */
1039f74e2772SMarc Bonnici for (index = 0U; index < SECURE_PARTITION_COUNT; index++) {
1040*0322d7afSJay Monkman uint32_t uuid_index;
1041*0322d7afSJay Monkman uint32_t *sp_uuid;
1042*0322d7afSJay Monkman
1043*0322d7afSJay Monkman for (uuid_index = 0; uuid_index < sp_desc[index].num_uuids;
1044*0322d7afSJay Monkman uuid_index++) {
1045*0322d7afSJay Monkman sp_uuid = sp_desc[index].uuid_array[uuid_index].uuid;
1046*0322d7afSJay Monkman
1047*0322d7afSJay Monkman if (null_uuid || uuid_match(uuid, sp_uuid)) {
1048f74e2772SMarc Bonnici /* Found a matching UUID, populate appropriately. */
1049*0322d7afSJay Monkman
1050f74e2772SMarc Bonnici if (*partition_count >= max_partitions) {
1051f74e2772SMarc Bonnici return FFA_ERROR_NO_MEMORY;
1052f74e2772SMarc Bonnici }
1053f74e2772SMarc Bonnici
1054f74e2772SMarc Bonnici desc = &partitions[*partition_count];
1055f74e2772SMarc Bonnici desc->ep_id = sp_desc[index].sp_id;
1056f74e2772SMarc Bonnici /*
1057f74e2772SMarc Bonnici * Execution context count must match No. cores for
1058f74e2772SMarc Bonnici * S-EL1 SPs.
1059f74e2772SMarc Bonnici */
1060f74e2772SMarc Bonnici desc->execution_ctx_count = PLATFORM_CORE_COUNT;
106162cd8f31SMarc Bonnici desc->properties =
106262cd8f31SMarc Bonnici partition_info_get_populate_properties(
106362cd8f31SMarc Bonnici sp_desc[index].properties,
106462cd8f31SMarc Bonnici sp_desc[index].execution_state);
106562cd8f31SMarc Bonnici
1066f74e2772SMarc Bonnici (*partition_count)++;
1067*0322d7afSJay Monkman if (null_uuid) {
1068*0322d7afSJay Monkman copy_uuid(desc->uuid, sp_uuid);
1069*0322d7afSJay Monkman } else {
1070*0322d7afSJay Monkman /* Found UUID in this SP, go to next SP */
1071*0322d7afSJay Monkman break;
1072*0322d7afSJay Monkman }
1073*0322d7afSJay Monkman }
1074f74e2772SMarc Bonnici }
1075f74e2772SMarc Bonnici }
1076f74e2772SMarc Bonnici return 0;
1077f74e2772SMarc Bonnici }
1078f74e2772SMarc Bonnici
1079f74e2772SMarc Bonnici /*
1080f74e2772SMarc Bonnici * Handle the case where that caller only wants the count of partitions
1081f74e2772SMarc Bonnici * matching a given UUID and does not want the corresponding descriptors
1082f74e2772SMarc Bonnici * populated.
1083f74e2772SMarc Bonnici */
partition_info_get_handler_count_only(uint32_t * uuid)1084f74e2772SMarc Bonnici static uint32_t partition_info_get_handler_count_only(uint32_t *uuid)
1085f74e2772SMarc Bonnici {
1086f74e2772SMarc Bonnici uint32_t index = 0;
1087f74e2772SMarc Bonnici uint32_t partition_count = 0;
1088f74e2772SMarc Bonnici bool null_uuid = is_null_uuid(uuid);
1089f74e2772SMarc Bonnici struct el3_lp_desc *el3_lp_descs = get_el3_lp_array();
1090f74e2772SMarc Bonnici
1091f74e2772SMarc Bonnici /* Deal with Logical Partitions. */
1092f74e2772SMarc Bonnici for (index = 0U; index < EL3_LP_DESCS_COUNT; index++) {
1093f74e2772SMarc Bonnici if (null_uuid ||
1094f74e2772SMarc Bonnici uuid_match(uuid, el3_lp_descs[index].uuid)) {
1095f74e2772SMarc Bonnici (partition_count)++;
1096f74e2772SMarc Bonnici }
1097f74e2772SMarc Bonnici }
1098f74e2772SMarc Bonnici
1099f74e2772SMarc Bonnici /* Deal with physical SP's. */
1100f74e2772SMarc Bonnici for (index = 0U; index < SECURE_PARTITION_COUNT; index++) {
1101*0322d7afSJay Monkman uint32_t uuid_index;
1102*0322d7afSJay Monkman
1103*0322d7afSJay Monkman for (uuid_index = 0; uuid_index < sp_desc[index].num_uuids;
1104*0322d7afSJay Monkman uuid_index++) {
1105*0322d7afSJay Monkman uint32_t *sp_uuid =
1106*0322d7afSJay Monkman sp_desc[index].uuid_array[uuid_index].uuid;
1107*0322d7afSJay Monkman
1108*0322d7afSJay Monkman if (null_uuid) {
1109f74e2772SMarc Bonnici (partition_count)++;
1110*0322d7afSJay Monkman } else if (uuid_match(uuid, sp_uuid)) {
1111*0322d7afSJay Monkman (partition_count)++;
1112*0322d7afSJay Monkman /* Found a match, go to next SP */
1113*0322d7afSJay Monkman break;
1114*0322d7afSJay Monkman }
1115f74e2772SMarc Bonnici }
1116f74e2772SMarc Bonnici }
1117f74e2772SMarc Bonnici return partition_count;
1118f74e2772SMarc Bonnici }
1119f74e2772SMarc Bonnici
1120f74e2772SMarc Bonnici /*
1121f74e2772SMarc Bonnici * If the caller of the PARTITION_INFO_GET ABI was a v1.0 caller, populate
112262cd8f31SMarc Bonnici * the corresponding descriptor format from the v1.1 descriptor array.
1123f74e2772SMarc Bonnici */
partition_info_populate_v1_0(struct ffa_partition_info_v1_1 * partitions,struct mailbox * mbox,int partition_count)1124f74e2772SMarc Bonnici static uint64_t partition_info_populate_v1_0(struct ffa_partition_info_v1_1
1125f74e2772SMarc Bonnici *partitions,
1126f74e2772SMarc Bonnici struct mailbox *mbox,
1127f74e2772SMarc Bonnici int partition_count)
1128f74e2772SMarc Bonnici {
1129f74e2772SMarc Bonnici uint32_t index;
1130f74e2772SMarc Bonnici uint32_t buf_size;
1131f74e2772SMarc Bonnici uint32_t descriptor_size;
1132f74e2772SMarc Bonnici struct ffa_partition_info_v1_0 *v1_0_partitions =
1133f74e2772SMarc Bonnici (struct ffa_partition_info_v1_0 *) mbox->rx_buffer;
1134f74e2772SMarc Bonnici
1135f74e2772SMarc Bonnici buf_size = mbox->rxtx_page_count * FFA_PAGE_SIZE;
1136f74e2772SMarc Bonnici descriptor_size = partition_count *
1137f74e2772SMarc Bonnici sizeof(struct ffa_partition_info_v1_0);
1138f74e2772SMarc Bonnici
1139f74e2772SMarc Bonnici if (descriptor_size > buf_size) {
1140f74e2772SMarc Bonnici return FFA_ERROR_NO_MEMORY;
1141f74e2772SMarc Bonnici }
1142f74e2772SMarc Bonnici
1143f74e2772SMarc Bonnici for (index = 0U; index < partition_count; index++) {
1144f74e2772SMarc Bonnici v1_0_partitions[index].ep_id = partitions[index].ep_id;
1145f74e2772SMarc Bonnici v1_0_partitions[index].execution_ctx_count =
1146f74e2772SMarc Bonnici partitions[index].execution_ctx_count;
114762cd8f31SMarc Bonnici /* Only report v1.0 properties. */
1148f74e2772SMarc Bonnici v1_0_partitions[index].properties =
114962cd8f31SMarc Bonnici (partitions[index].properties &
115062cd8f31SMarc Bonnici FFA_PARTITION_INFO_GET_PROPERTIES_V1_0_MASK);
1151f74e2772SMarc Bonnici }
1152f74e2772SMarc Bonnici return 0;
1153f74e2772SMarc Bonnici }
1154f74e2772SMarc Bonnici
1155f74e2772SMarc Bonnici /*
1156f74e2772SMarc Bonnici * Main handler for FFA_PARTITION_INFO_GET which supports both FF-A v1.1 and
1157f74e2772SMarc Bonnici * v1.0 implementations.
1158f74e2772SMarc Bonnici */
partition_info_get_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)1159f74e2772SMarc Bonnici static uint64_t partition_info_get_handler(uint32_t smc_fid,
1160f74e2772SMarc Bonnici bool secure_origin,
1161f74e2772SMarc Bonnici uint64_t x1,
1162f74e2772SMarc Bonnici uint64_t x2,
1163f74e2772SMarc Bonnici uint64_t x3,
1164f74e2772SMarc Bonnici uint64_t x4,
1165f74e2772SMarc Bonnici void *cookie,
1166f74e2772SMarc Bonnici void *handle,
1167f74e2772SMarc Bonnici uint64_t flags)
1168f74e2772SMarc Bonnici {
1169f74e2772SMarc Bonnici int ret;
1170f74e2772SMarc Bonnici uint32_t partition_count = 0;
1171f74e2772SMarc Bonnici uint32_t size = 0;
1172f74e2772SMarc Bonnici uint32_t ffa_version = get_partition_ffa_version(secure_origin);
1173f74e2772SMarc Bonnici struct mailbox *mbox;
1174f74e2772SMarc Bonnici uint64_t info_get_flags;
1175f74e2772SMarc Bonnici bool count_only;
1176f74e2772SMarc Bonnici uint32_t uuid[4];
1177f74e2772SMarc Bonnici
1178f74e2772SMarc Bonnici uuid[0] = x1;
1179f74e2772SMarc Bonnici uuid[1] = x2;
1180f74e2772SMarc Bonnici uuid[2] = x3;
1181f74e2772SMarc Bonnici uuid[3] = x4;
1182f74e2772SMarc Bonnici
1183f74e2772SMarc Bonnici /* Determine if the Partition descriptors should be populated. */
1184f74e2772SMarc Bonnici info_get_flags = SMC_GET_GP(handle, CTX_GPREG_X5);
1185f74e2772SMarc Bonnici count_only = (info_get_flags & FFA_PARTITION_INFO_GET_COUNT_FLAG_MASK);
1186f74e2772SMarc Bonnici
1187f74e2772SMarc Bonnici /* Handle the case where we don't need to populate the descriptors. */
1188f74e2772SMarc Bonnici if (count_only) {
1189f74e2772SMarc Bonnici partition_count = partition_info_get_handler_count_only(uuid);
1190f74e2772SMarc Bonnici if (partition_count == 0) {
1191f74e2772SMarc Bonnici return spmc_ffa_error_return(handle,
1192f74e2772SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
1193f74e2772SMarc Bonnici }
1194f74e2772SMarc Bonnici } else {
1195*0322d7afSJay Monkman struct ffa_partition_info_v1_1
1196*0322d7afSJay Monkman partitions[MAX_SP_LP_PARTITIONS *
1197*0322d7afSJay Monkman SPMC_AT_EL3_PARTITION_MAX_UUIDS];
1198f74e2772SMarc Bonnici /*
1199f74e2772SMarc Bonnici * Handle the case where the partition descriptors are required,
1200f74e2772SMarc Bonnici * check we have the buffers available and populate the
1201f74e2772SMarc Bonnici * appropriate structure version.
1202f74e2772SMarc Bonnici */
1203f74e2772SMarc Bonnici
1204f74e2772SMarc Bonnici /* Obtain the v1.1 format of the descriptors. */
1205*0322d7afSJay Monkman ret = partition_info_get_handler_v1_1(
1206*0322d7afSJay Monkman uuid, partitions,
1207*0322d7afSJay Monkman (MAX_SP_LP_PARTITIONS *
1208*0322d7afSJay Monkman SPMC_AT_EL3_PARTITION_MAX_UUIDS),
1209f74e2772SMarc Bonnici &partition_count);
1210f74e2772SMarc Bonnici
1211f74e2772SMarc Bonnici /* Check if an error occurred during discovery. */
1212f74e2772SMarc Bonnici if (ret != 0) {
1213f74e2772SMarc Bonnici goto err;
1214f74e2772SMarc Bonnici }
1215f74e2772SMarc Bonnici
1216f74e2772SMarc Bonnici /* If we didn't find any matches the UUID is unknown. */
1217f74e2772SMarc Bonnici if (partition_count == 0) {
1218f74e2772SMarc Bonnici ret = FFA_ERROR_INVALID_PARAMETER;
1219f74e2772SMarc Bonnici goto err;
1220f74e2772SMarc Bonnici }
1221f74e2772SMarc Bonnici
1222f74e2772SMarc Bonnici /* Obtain the partition mailbox RX/TX buffer pair descriptor. */
1223f74e2772SMarc Bonnici mbox = spmc_get_mbox_desc(secure_origin);
1224f74e2772SMarc Bonnici
1225f74e2772SMarc Bonnici /*
1226f74e2772SMarc Bonnici * If the caller has not bothered registering its RX/TX pair
1227f74e2772SMarc Bonnici * then return an error code.
1228f74e2772SMarc Bonnici */
1229f74e2772SMarc Bonnici spin_lock(&mbox->lock);
1230f74e2772SMarc Bonnici if (mbox->rx_buffer == NULL) {
1231f74e2772SMarc Bonnici ret = FFA_ERROR_BUSY;
1232f74e2772SMarc Bonnici goto err_unlock;
1233f74e2772SMarc Bonnici }
1234f74e2772SMarc Bonnici
1235f74e2772SMarc Bonnici /* Ensure the RX buffer is currently free. */
1236f74e2772SMarc Bonnici if (mbox->state != MAILBOX_STATE_EMPTY) {
1237f74e2772SMarc Bonnici ret = FFA_ERROR_BUSY;
1238f74e2772SMarc Bonnici goto err_unlock;
1239f74e2772SMarc Bonnici }
1240f74e2772SMarc Bonnici
1241f74e2772SMarc Bonnici /* Zero the RX buffer before populating. */
1242f74e2772SMarc Bonnici (void)memset(mbox->rx_buffer, 0,
1243f74e2772SMarc Bonnici mbox->rxtx_page_count * FFA_PAGE_SIZE);
1244f74e2772SMarc Bonnici
1245f74e2772SMarc Bonnici /*
1246f74e2772SMarc Bonnici * Depending on the FF-A version of the requesting partition
1247f74e2772SMarc Bonnici * we may need to convert to a v1.0 format otherwise we can copy
1248f74e2772SMarc Bonnici * directly.
1249f74e2772SMarc Bonnici */
1250f74e2772SMarc Bonnici if (ffa_version == MAKE_FFA_VERSION(U(1), U(0))) {
1251f74e2772SMarc Bonnici ret = partition_info_populate_v1_0(partitions,
1252f74e2772SMarc Bonnici mbox,
1253f74e2772SMarc Bonnici partition_count);
1254f74e2772SMarc Bonnici if (ret != 0) {
1255f74e2772SMarc Bonnici goto err_unlock;
1256f74e2772SMarc Bonnici }
1257f74e2772SMarc Bonnici } else {
1258f74e2772SMarc Bonnici uint32_t buf_size = mbox->rxtx_page_count *
1259f74e2772SMarc Bonnici FFA_PAGE_SIZE;
1260f74e2772SMarc Bonnici
1261f74e2772SMarc Bonnici /* Ensure the descriptor will fit in the buffer. */
1262f74e2772SMarc Bonnici size = sizeof(struct ffa_partition_info_v1_1);
1263f74e2772SMarc Bonnici if (partition_count * size > buf_size) {
1264f74e2772SMarc Bonnici ret = FFA_ERROR_NO_MEMORY;
1265f74e2772SMarc Bonnici goto err_unlock;
1266f74e2772SMarc Bonnici }
1267f74e2772SMarc Bonnici memcpy(mbox->rx_buffer, partitions,
1268f74e2772SMarc Bonnici partition_count * size);
1269f74e2772SMarc Bonnici }
1270f74e2772SMarc Bonnici
1271f74e2772SMarc Bonnici mbox->state = MAILBOX_STATE_FULL;
1272f74e2772SMarc Bonnici spin_unlock(&mbox->lock);
1273f74e2772SMarc Bonnici }
1274f74e2772SMarc Bonnici SMC_RET4(handle, FFA_SUCCESS_SMC32, 0, partition_count, size);
1275f74e2772SMarc Bonnici
1276f74e2772SMarc Bonnici err_unlock:
1277f74e2772SMarc Bonnici spin_unlock(&mbox->lock);
1278f74e2772SMarc Bonnici err:
1279f74e2772SMarc Bonnici return spmc_ffa_error_return(handle, ret);
1280f74e2772SMarc Bonnici }
1281f74e2772SMarc Bonnici
ffa_feature_success(void * handle,uint32_t arg2)12820560b53eSMarc Bonnici static uint64_t ffa_feature_success(void *handle, uint32_t arg2)
12830560b53eSMarc Bonnici {
12840560b53eSMarc Bonnici SMC_RET3(handle, FFA_SUCCESS_SMC32, 0, arg2);
12850560b53eSMarc Bonnici }
12860560b53eSMarc Bonnici
ffa_features_retrieve_request(bool secure_origin,uint32_t input_properties,void * handle)12870560b53eSMarc Bonnici static uint64_t ffa_features_retrieve_request(bool secure_origin,
12880560b53eSMarc Bonnici uint32_t input_properties,
12890560b53eSMarc Bonnici void *handle)
12900560b53eSMarc Bonnici {
12910560b53eSMarc Bonnici /*
12920560b53eSMarc Bonnici * If we're called by the normal world we don't support any
12930560b53eSMarc Bonnici * additional features.
12940560b53eSMarc Bonnici */
12950560b53eSMarc Bonnici if (!secure_origin) {
12960560b53eSMarc Bonnici if ((input_properties & FFA_FEATURES_RET_REQ_NS_BIT) != 0U) {
12970560b53eSMarc Bonnici return spmc_ffa_error_return(handle,
12980560b53eSMarc Bonnici FFA_ERROR_NOT_SUPPORTED);
12990560b53eSMarc Bonnici }
13000560b53eSMarc Bonnici
13010560b53eSMarc Bonnici } else {
13020560b53eSMarc Bonnici struct secure_partition_desc *sp = spmc_get_current_sp_ctx();
13030560b53eSMarc Bonnici /*
13043f1c63ddSJay Monkman * If v1.1 or higher the NS bit must be set otherwise it is
13053f1c63ddSJay Monkman * an invalid call. If v1.0 check and store whether the SP
13063f1c63ddSJay Monkman * has requested the use of the NS bit.
13070560b53eSMarc Bonnici */
13083f1c63ddSJay Monkman if (spmc_compatible_version(sp->ffa_version, 1, 1)) {
13090560b53eSMarc Bonnici if ((input_properties &
13100560b53eSMarc Bonnici FFA_FEATURES_RET_REQ_NS_BIT) == 0U) {
13110560b53eSMarc Bonnici return spmc_ffa_error_return(handle,
13120560b53eSMarc Bonnici FFA_ERROR_NOT_SUPPORTED);
13130560b53eSMarc Bonnici }
13140560b53eSMarc Bonnici return ffa_feature_success(handle,
13150560b53eSMarc Bonnici FFA_FEATURES_RET_REQ_NS_BIT);
13160560b53eSMarc Bonnici } else {
13170560b53eSMarc Bonnici sp->ns_bit_requested = (input_properties &
13180560b53eSMarc Bonnici FFA_FEATURES_RET_REQ_NS_BIT) !=
13190560b53eSMarc Bonnici 0U;
13200560b53eSMarc Bonnici }
13210560b53eSMarc Bonnici if (sp->ns_bit_requested) {
13220560b53eSMarc Bonnici return ffa_feature_success(handle,
13230560b53eSMarc Bonnici FFA_FEATURES_RET_REQ_NS_BIT);
13240560b53eSMarc Bonnici }
13250560b53eSMarc Bonnici }
13260560b53eSMarc Bonnici SMC_RET1(handle, FFA_SUCCESS_SMC32);
13270560b53eSMarc Bonnici }
13280560b53eSMarc Bonnici
ffa_features_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)132955a29638SMarc Bonnici static uint64_t ffa_features_handler(uint32_t smc_fid,
133055a29638SMarc Bonnici bool secure_origin,
133155a29638SMarc Bonnici uint64_t x1,
133255a29638SMarc Bonnici uint64_t x2,
133355a29638SMarc Bonnici uint64_t x3,
133455a29638SMarc Bonnici uint64_t x4,
133555a29638SMarc Bonnici void *cookie,
133655a29638SMarc Bonnici void *handle,
133755a29638SMarc Bonnici uint64_t flags)
133855a29638SMarc Bonnici {
133955a29638SMarc Bonnici uint32_t function_id = (uint32_t) x1;
134055a29638SMarc Bonnici uint32_t input_properties = (uint32_t) x2;
134155a29638SMarc Bonnici
134255a29638SMarc Bonnici /* Check if a Feature ID was requested. */
134355a29638SMarc Bonnici if ((function_id & FFA_FEATURES_BIT31_MASK) == 0U) {
134455a29638SMarc Bonnici /* We currently don't support any additional features. */
134555a29638SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
134655a29638SMarc Bonnici }
134755a29638SMarc Bonnici
13480560b53eSMarc Bonnici /*
13490560b53eSMarc Bonnici * Handle the cases where we have separate handlers due to additional
13500560b53eSMarc Bonnici * properties.
13510560b53eSMarc Bonnici */
13520560b53eSMarc Bonnici switch (function_id) {
13530560b53eSMarc Bonnici case FFA_MEM_RETRIEVE_REQ_SMC32:
13540560b53eSMarc Bonnici case FFA_MEM_RETRIEVE_REQ_SMC64:
13550560b53eSMarc Bonnici return ffa_features_retrieve_request(secure_origin,
13560560b53eSMarc Bonnici input_properties,
13570560b53eSMarc Bonnici handle);
13580560b53eSMarc Bonnici }
13590560b53eSMarc Bonnici
13600560b53eSMarc Bonnici /*
13610560b53eSMarc Bonnici * We don't currently support additional input properties for these
13620560b53eSMarc Bonnici * other ABIs therefore ensure this value is set to 0.
13630560b53eSMarc Bonnici */
13640560b53eSMarc Bonnici if (input_properties != 0U) {
13650560b53eSMarc Bonnici return spmc_ffa_error_return(handle,
13660560b53eSMarc Bonnici FFA_ERROR_NOT_SUPPORTED);
13670560b53eSMarc Bonnici }
13680560b53eSMarc Bonnici
13690560b53eSMarc Bonnici /* Report if any other FF-A ABI is supported. */
137055a29638SMarc Bonnici switch (function_id) {
137155a29638SMarc Bonnici /* Supported features from both worlds. */
137255a29638SMarc Bonnici case FFA_ERROR:
137355a29638SMarc Bonnici case FFA_SUCCESS_SMC32:
1374729d7793SAchin Gupta case FFA_INTERRUPT:
137546872e01SMarc Bonnici case FFA_SPM_ID_GET:
1376d5fe9235SMarc Bonnici case FFA_ID_GET:
137755a29638SMarc Bonnici case FFA_FEATURES:
137855a29638SMarc Bonnici case FFA_VERSION:
1379f0c25a08SMarc Bonnici case FFA_RX_RELEASE:
138055a29638SMarc Bonnici case FFA_MSG_SEND_DIRECT_REQ_SMC32:
138155a29638SMarc Bonnici case FFA_MSG_SEND_DIRECT_REQ_SMC64:
138209a580b7SLevi Yun case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
138355a29638SMarc Bonnici case FFA_PARTITION_INFO_GET:
138455a29638SMarc Bonnici case FFA_RXTX_MAP_SMC32:
138555a29638SMarc Bonnici case FFA_RXTX_MAP_SMC64:
138655a29638SMarc Bonnici case FFA_RXTX_UNMAP:
1387e0b1a6d5SMarc Bonnici case FFA_MEM_FRAG_TX:
1388aad20c85SMarc Bonnici case FFA_MSG_RUN:
138955a29638SMarc Bonnici
139055a29638SMarc Bonnici /*
139155a29638SMarc Bonnici * We are relying on the fact that the other registers
139255a29638SMarc Bonnici * will be set to 0 as these values align with the
139355a29638SMarc Bonnici * currently implemented features of the SPMC. If this
139455a29638SMarc Bonnici * changes this function must be extended to handle
139555a29638SMarc Bonnici * reporting the additional functionality.
139655a29638SMarc Bonnici */
139755a29638SMarc Bonnici
139855a29638SMarc Bonnici SMC_RET1(handle, FFA_SUCCESS_SMC32);
139955a29638SMarc Bonnici /* Execution stops here. */
140055a29638SMarc Bonnici
140155a29638SMarc Bonnici /* Supported ABIs only from the secure world. */
1402d0ee0ec1SKarl Meakin case FFA_MEM_PERM_GET_SMC32:
1403d0ee0ec1SKarl Meakin case FFA_MEM_PERM_GET_SMC64:
1404d0ee0ec1SKarl Meakin case FFA_MEM_PERM_SET_SMC32:
1405d0ee0ec1SKarl Meakin case FFA_MEM_PERM_SET_SMC64:
1406d0ee0ec1SKarl Meakin /* these ABIs are only supported from S-EL0 SPs */
1407d0ee0ec1SKarl Meakin #if !(SPMC_AT_EL3_SEL0_SP)
1408d0ee0ec1SKarl Meakin return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
1409d0ee0ec1SKarl Meakin #endif
1410d0ee0ec1SKarl Meakin /* fall through */
1411d0ee0ec1SKarl Meakin
141259bd2ad8SMarc Bonnici case FFA_SECONDARY_EP_REGISTER_SMC64:
141355a29638SMarc Bonnici case FFA_MSG_SEND_DIRECT_RESP_SMC32:
141455a29638SMarc Bonnici case FFA_MSG_SEND_DIRECT_RESP_SMC64:
141509a580b7SLevi Yun case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
1416e0b1a6d5SMarc Bonnici case FFA_MEM_RELINQUISH:
141755a29638SMarc Bonnici case FFA_MSG_WAIT:
1418638a6f8eSShruti Gupta case FFA_CONSOLE_LOG_SMC32:
1419638a6f8eSShruti Gupta case FFA_CONSOLE_LOG_SMC64:
142055a29638SMarc Bonnici if (!secure_origin) {
142155a29638SMarc Bonnici return spmc_ffa_error_return(handle,
142255a29638SMarc Bonnici FFA_ERROR_NOT_SUPPORTED);
142355a29638SMarc Bonnici }
142455a29638SMarc Bonnici SMC_RET1(handle, FFA_SUCCESS_SMC32);
142555a29638SMarc Bonnici /* Execution stops here. */
142655a29638SMarc Bonnici
1427e0b1a6d5SMarc Bonnici /* Supported features only from the normal world. */
1428e0b1a6d5SMarc Bonnici case FFA_MEM_SHARE_SMC32:
1429e0b1a6d5SMarc Bonnici case FFA_MEM_SHARE_SMC64:
1430e0b1a6d5SMarc Bonnici case FFA_MEM_LEND_SMC32:
1431e0b1a6d5SMarc Bonnici case FFA_MEM_LEND_SMC64:
1432e0b1a6d5SMarc Bonnici case FFA_MEM_RECLAIM:
1433e0b1a6d5SMarc Bonnici case FFA_MEM_FRAG_RX:
1434e0b1a6d5SMarc Bonnici
1435e0b1a6d5SMarc Bonnici if (secure_origin) {
1436e0b1a6d5SMarc Bonnici return spmc_ffa_error_return(handle,
1437e0b1a6d5SMarc Bonnici FFA_ERROR_NOT_SUPPORTED);
1438e0b1a6d5SMarc Bonnici }
1439e0b1a6d5SMarc Bonnici SMC_RET1(handle, FFA_SUCCESS_SMC32);
1440e0b1a6d5SMarc Bonnici /* Execution stops here. */
1441e0b1a6d5SMarc Bonnici
144255a29638SMarc Bonnici default:
144355a29638SMarc Bonnici return spmc_ffa_error_return(handle,
144455a29638SMarc Bonnici FFA_ERROR_NOT_SUPPORTED);
144555a29638SMarc Bonnici }
144655a29638SMarc Bonnici }
144755a29638SMarc Bonnici
ffa_id_get_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)1448d5fe9235SMarc Bonnici static uint64_t ffa_id_get_handler(uint32_t smc_fid,
1449d5fe9235SMarc Bonnici bool secure_origin,
1450d5fe9235SMarc Bonnici uint64_t x1,
1451d5fe9235SMarc Bonnici uint64_t x2,
1452d5fe9235SMarc Bonnici uint64_t x3,
1453d5fe9235SMarc Bonnici uint64_t x4,
1454d5fe9235SMarc Bonnici void *cookie,
1455d5fe9235SMarc Bonnici void *handle,
1456d5fe9235SMarc Bonnici uint64_t flags)
1457d5fe9235SMarc Bonnici {
1458d5fe9235SMarc Bonnici if (secure_origin) {
1459d5fe9235SMarc Bonnici SMC_RET3(handle, FFA_SUCCESS_SMC32, 0x0,
1460d5fe9235SMarc Bonnici spmc_get_current_sp_ctx()->sp_id);
1461d5fe9235SMarc Bonnici } else {
1462d5fe9235SMarc Bonnici SMC_RET3(handle, FFA_SUCCESS_SMC32, 0x0,
1463d5fe9235SMarc Bonnici spmc_get_hyp_ctx()->ns_ep_id);
1464d5fe9235SMarc Bonnici }
1465d5fe9235SMarc Bonnici }
1466d5fe9235SMarc Bonnici
146746872e01SMarc Bonnici /*
146846872e01SMarc Bonnici * Enable an SP to query the ID assigned to the SPMC.
146946872e01SMarc Bonnici */
ffa_spm_id_get_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)147046872e01SMarc Bonnici static uint64_t ffa_spm_id_get_handler(uint32_t smc_fid,
147146872e01SMarc Bonnici bool secure_origin,
147246872e01SMarc Bonnici uint64_t x1,
147346872e01SMarc Bonnici uint64_t x2,
147446872e01SMarc Bonnici uint64_t x3,
147546872e01SMarc Bonnici uint64_t x4,
147646872e01SMarc Bonnici void *cookie,
147746872e01SMarc Bonnici void *handle,
147846872e01SMarc Bonnici uint64_t flags)
147946872e01SMarc Bonnici {
148046872e01SMarc Bonnici assert(x1 == 0UL);
148146872e01SMarc Bonnici assert(x2 == 0UL);
148246872e01SMarc Bonnici assert(x3 == 0UL);
148346872e01SMarc Bonnici assert(x4 == 0UL);
148446872e01SMarc Bonnici assert(SMC_GET_GP(handle, CTX_GPREG_X5) == 0UL);
148546872e01SMarc Bonnici assert(SMC_GET_GP(handle, CTX_GPREG_X6) == 0UL);
148646872e01SMarc Bonnici assert(SMC_GET_GP(handle, CTX_GPREG_X7) == 0UL);
148746872e01SMarc Bonnici
148846872e01SMarc Bonnici SMC_RET3(handle, FFA_SUCCESS_SMC32, 0x0, FFA_SPMC_ID);
148946872e01SMarc Bonnici }
149046872e01SMarc Bonnici
ffa_run_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)1491aad20c85SMarc Bonnici static uint64_t ffa_run_handler(uint32_t smc_fid,
1492aad20c85SMarc Bonnici bool secure_origin,
1493aad20c85SMarc Bonnici uint64_t x1,
1494aad20c85SMarc Bonnici uint64_t x2,
1495aad20c85SMarc Bonnici uint64_t x3,
1496aad20c85SMarc Bonnici uint64_t x4,
1497aad20c85SMarc Bonnici void *cookie,
1498aad20c85SMarc Bonnici void *handle,
1499aad20c85SMarc Bonnici uint64_t flags)
1500aad20c85SMarc Bonnici {
1501aad20c85SMarc Bonnici struct secure_partition_desc *sp;
1502aad20c85SMarc Bonnici uint16_t target_id = FFA_RUN_EP_ID(x1);
1503aad20c85SMarc Bonnici uint16_t vcpu_id = FFA_RUN_VCPU_ID(x1);
1504aad20c85SMarc Bonnici unsigned int idx;
1505aad20c85SMarc Bonnici unsigned int *rt_state;
1506aad20c85SMarc Bonnici unsigned int *rt_model;
1507aad20c85SMarc Bonnici
1508aad20c85SMarc Bonnici /* Can only be called from the normal world. */
1509aad20c85SMarc Bonnici if (secure_origin) {
1510aad20c85SMarc Bonnici ERROR("FFA_RUN can only be called from NWd.\n");
1511aad20c85SMarc Bonnici return spmc_ffa_error_return(handle,
1512aad20c85SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
1513aad20c85SMarc Bonnici }
1514aad20c85SMarc Bonnici
1515aad20c85SMarc Bonnici /* Cannot run a Normal world partition. */
1516aad20c85SMarc Bonnici if (ffa_is_normal_world_id(target_id)) {
1517aad20c85SMarc Bonnici ERROR("Cannot run a NWd partition (0x%x).\n", target_id);
1518aad20c85SMarc Bonnici return spmc_ffa_error_return(handle,
1519aad20c85SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
1520aad20c85SMarc Bonnici }
1521aad20c85SMarc Bonnici
1522aad20c85SMarc Bonnici /* Check that the target SP exists. */
1523aad20c85SMarc Bonnici sp = spmc_get_sp_ctx(target_id);
1524aad20c85SMarc Bonnici if (sp == NULL) {
1525bbf28dc3SAndrei Homescu ERROR("Unknown partition ID (0x%x).\n", target_id);
1526aad20c85SMarc Bonnici return spmc_ffa_error_return(handle,
1527aad20c85SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
1528aad20c85SMarc Bonnici }
1529aad20c85SMarc Bonnici
1530aad20c85SMarc Bonnici idx = get_ec_index(sp);
15315ed8e255SNishant Sharma
1532aad20c85SMarc Bonnici if (idx != vcpu_id) {
1533aad20c85SMarc Bonnici ERROR("Cannot run vcpu %d != %d.\n", idx, vcpu_id);
1534aad20c85SMarc Bonnici return spmc_ffa_error_return(handle,
1535aad20c85SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
1536aad20c85SMarc Bonnici }
15375ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
15385ed8e255SNishant Sharma spin_lock(&sp->rt_state_lock);
15395ed8e255SNishant Sharma }
1540aad20c85SMarc Bonnici rt_state = &((sp->ec[idx]).rt_state);
1541aad20c85SMarc Bonnici rt_model = &((sp->ec[idx]).rt_model);
1542aad20c85SMarc Bonnici if (*rt_state == RT_STATE_RUNNING) {
15435ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
15445ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
15455ed8e255SNishant Sharma }
1546aad20c85SMarc Bonnici ERROR("Partition (0x%x) is already running.\n", target_id);
1547aad20c85SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_BUSY);
1548aad20c85SMarc Bonnici }
1549aad20c85SMarc Bonnici
1550aad20c85SMarc Bonnici /*
1551aad20c85SMarc Bonnici * Sanity check that if the execution context was not waiting then it
1552aad20c85SMarc Bonnici * was either in the direct request or the run partition runtime model.
1553aad20c85SMarc Bonnici */
1554aad20c85SMarc Bonnici if (*rt_state == RT_STATE_PREEMPTED || *rt_state == RT_STATE_BLOCKED) {
1555aad20c85SMarc Bonnici assert(*rt_model == RT_MODEL_RUN ||
1556aad20c85SMarc Bonnici *rt_model == RT_MODEL_DIR_REQ);
1557aad20c85SMarc Bonnici }
1558aad20c85SMarc Bonnici
1559aad20c85SMarc Bonnici /*
1560aad20c85SMarc Bonnici * If the context was waiting then update the partition runtime model.
1561aad20c85SMarc Bonnici */
1562aad20c85SMarc Bonnici if (*rt_state == RT_STATE_WAITING) {
1563aad20c85SMarc Bonnici *rt_model = RT_MODEL_RUN;
1564aad20c85SMarc Bonnici }
1565aad20c85SMarc Bonnici
1566aad20c85SMarc Bonnici /*
1567aad20c85SMarc Bonnici * Forward the request to the correct SP vCPU after updating
1568aad20c85SMarc Bonnici * its state.
1569aad20c85SMarc Bonnici */
1570aad20c85SMarc Bonnici *rt_state = RT_STATE_RUNNING;
1571aad20c85SMarc Bonnici
15725ed8e255SNishant Sharma if (sp->runtime_el == S_EL0) {
15735ed8e255SNishant Sharma spin_unlock(&sp->rt_state_lock);
15745ed8e255SNishant Sharma }
15755ed8e255SNishant Sharma
1576aad20c85SMarc Bonnici return spmc_smc_return(smc_fid, secure_origin, x1, 0, 0, 0,
1577bb9fc8c0SJay Monkman handle, cookie, flags, target_id, sp->ffa_version);
1578aad20c85SMarc Bonnici }
1579aad20c85SMarc Bonnici
rx_release_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)1580f0c25a08SMarc Bonnici static uint64_t rx_release_handler(uint32_t smc_fid,
1581f0c25a08SMarc Bonnici bool secure_origin,
1582f0c25a08SMarc Bonnici uint64_t x1,
1583f0c25a08SMarc Bonnici uint64_t x2,
1584f0c25a08SMarc Bonnici uint64_t x3,
1585f0c25a08SMarc Bonnici uint64_t x4,
1586f0c25a08SMarc Bonnici void *cookie,
1587f0c25a08SMarc Bonnici void *handle,
1588f0c25a08SMarc Bonnici uint64_t flags)
1589f0c25a08SMarc Bonnici {
1590f0c25a08SMarc Bonnici struct mailbox *mbox = spmc_get_mbox_desc(secure_origin);
1591f0c25a08SMarc Bonnici
1592f0c25a08SMarc Bonnici spin_lock(&mbox->lock);
1593f0c25a08SMarc Bonnici
1594f0c25a08SMarc Bonnici if (mbox->state != MAILBOX_STATE_FULL) {
1595f0c25a08SMarc Bonnici spin_unlock(&mbox->lock);
1596f0c25a08SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
1597f0c25a08SMarc Bonnici }
1598f0c25a08SMarc Bonnici
1599f0c25a08SMarc Bonnici mbox->state = MAILBOX_STATE_EMPTY;
1600f0c25a08SMarc Bonnici spin_unlock(&mbox->lock);
1601f0c25a08SMarc Bonnici
1602f0c25a08SMarc Bonnici SMC_RET1(handle, FFA_SUCCESS_SMC32);
1603f0c25a08SMarc Bonnici }
1604f0c25a08SMarc Bonnici
spmc_ffa_console_log(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)1605638a6f8eSShruti Gupta static uint64_t spmc_ffa_console_log(uint32_t smc_fid,
1606638a6f8eSShruti Gupta bool secure_origin,
1607638a6f8eSShruti Gupta uint64_t x1,
1608638a6f8eSShruti Gupta uint64_t x2,
1609638a6f8eSShruti Gupta uint64_t x3,
1610638a6f8eSShruti Gupta uint64_t x4,
1611638a6f8eSShruti Gupta void *cookie,
1612638a6f8eSShruti Gupta void *handle,
1613638a6f8eSShruti Gupta uint64_t flags)
1614638a6f8eSShruti Gupta {
161583129bcdSKarl Meakin /* Maximum number of characters is 48: 6 registers of 8 bytes each. */
161683129bcdSKarl Meakin char chars[48] = {0};
1617638a6f8eSShruti Gupta size_t chars_max;
1618638a6f8eSShruti Gupta size_t chars_count = x1;
1619638a6f8eSShruti Gupta
1620638a6f8eSShruti Gupta /* Does not support request from Nwd. */
1621638a6f8eSShruti Gupta if (!secure_origin) {
1622638a6f8eSShruti Gupta return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
1623638a6f8eSShruti Gupta }
1624638a6f8eSShruti Gupta
1625638a6f8eSShruti Gupta assert(smc_fid == FFA_CONSOLE_LOG_SMC32 || smc_fid == FFA_CONSOLE_LOG_SMC64);
1626638a6f8eSShruti Gupta if (smc_fid == FFA_CONSOLE_LOG_SMC32) {
162783129bcdSKarl Meakin uint32_t *registers = (uint32_t *)chars;
162883129bcdSKarl Meakin registers[0] = (uint32_t)x2;
162983129bcdSKarl Meakin registers[1] = (uint32_t)x3;
163083129bcdSKarl Meakin registers[2] = (uint32_t)x4;
163183129bcdSKarl Meakin registers[3] = (uint32_t)SMC_GET_GP(handle, CTX_GPREG_X5);
163283129bcdSKarl Meakin registers[4] = (uint32_t)SMC_GET_GP(handle, CTX_GPREG_X6);
163383129bcdSKarl Meakin registers[5] = (uint32_t)SMC_GET_GP(handle, CTX_GPREG_X7);
163483129bcdSKarl Meakin chars_max = 6 * sizeof(uint32_t);
1635638a6f8eSShruti Gupta } else {
163683129bcdSKarl Meakin uint64_t *registers = (uint64_t *)chars;
163783129bcdSKarl Meakin registers[0] = x2;
163883129bcdSKarl Meakin registers[1] = x3;
163983129bcdSKarl Meakin registers[2] = x4;
164083129bcdSKarl Meakin registers[3] = SMC_GET_GP(handle, CTX_GPREG_X5);
164183129bcdSKarl Meakin registers[4] = SMC_GET_GP(handle, CTX_GPREG_X6);
164283129bcdSKarl Meakin registers[5] = SMC_GET_GP(handle, CTX_GPREG_X7);
164383129bcdSKarl Meakin chars_max = 6 * sizeof(uint64_t);
1644638a6f8eSShruti Gupta }
1645638a6f8eSShruti Gupta
1646638a6f8eSShruti Gupta if ((chars_count == 0) || (chars_count > chars_max)) {
1647638a6f8eSShruti Gupta return spmc_ffa_error_return(handle, FFA_ERROR_INVALID_PARAMETER);
1648638a6f8eSShruti Gupta }
1649638a6f8eSShruti Gupta
1650638a6f8eSShruti Gupta for (size_t i = 0; (i < chars_count) && (chars[i] != '\0'); i++) {
1651638a6f8eSShruti Gupta putchar(chars[i]);
1652638a6f8eSShruti Gupta }
1653638a6f8eSShruti Gupta
1654638a6f8eSShruti Gupta SMC_RET1(handle, FFA_SUCCESS_SMC32);
1655638a6f8eSShruti Gupta }
1656638a6f8eSShruti Gupta
165759bd2ad8SMarc Bonnici /*
165859bd2ad8SMarc Bonnici * Perform initial validation on the provided secondary entry point.
165959bd2ad8SMarc Bonnici * For now ensure it does not lie within the BL31 Image or the SP's
166059bd2ad8SMarc Bonnici * RX/TX buffers as these are mapped within EL3.
166159bd2ad8SMarc Bonnici * TODO: perform validation for additional invalid memory regions.
166259bd2ad8SMarc Bonnici */
validate_secondary_ep(uintptr_t ep,struct secure_partition_desc * sp)166359bd2ad8SMarc Bonnici static int validate_secondary_ep(uintptr_t ep, struct secure_partition_desc *sp)
166459bd2ad8SMarc Bonnici {
166559bd2ad8SMarc Bonnici struct mailbox *mb;
166659bd2ad8SMarc Bonnici uintptr_t buffer_size;
166759bd2ad8SMarc Bonnici uintptr_t sp_rx_buffer;
166859bd2ad8SMarc Bonnici uintptr_t sp_tx_buffer;
166959bd2ad8SMarc Bonnici uintptr_t sp_rx_buffer_limit;
167059bd2ad8SMarc Bonnici uintptr_t sp_tx_buffer_limit;
167159bd2ad8SMarc Bonnici
167259bd2ad8SMarc Bonnici mb = &sp->mailbox;
167359bd2ad8SMarc Bonnici buffer_size = (uintptr_t) (mb->rxtx_page_count * FFA_PAGE_SIZE);
167459bd2ad8SMarc Bonnici sp_rx_buffer = (uintptr_t) mb->rx_buffer;
167559bd2ad8SMarc Bonnici sp_tx_buffer = (uintptr_t) mb->tx_buffer;
167659bd2ad8SMarc Bonnici sp_rx_buffer_limit = sp_rx_buffer + buffer_size;
167759bd2ad8SMarc Bonnici sp_tx_buffer_limit = sp_tx_buffer + buffer_size;
167859bd2ad8SMarc Bonnici
167959bd2ad8SMarc Bonnici /*
168059bd2ad8SMarc Bonnici * Check if the entry point lies within BL31, or the
168159bd2ad8SMarc Bonnici * SP's RX or TX buffer.
168259bd2ad8SMarc Bonnici */
168359bd2ad8SMarc Bonnici if ((ep >= BL31_BASE && ep < BL31_LIMIT) ||
168459bd2ad8SMarc Bonnici (ep >= sp_rx_buffer && ep < sp_rx_buffer_limit) ||
168559bd2ad8SMarc Bonnici (ep >= sp_tx_buffer && ep < sp_tx_buffer_limit)) {
168659bd2ad8SMarc Bonnici return -EINVAL;
168759bd2ad8SMarc Bonnici }
168859bd2ad8SMarc Bonnici return 0;
168959bd2ad8SMarc Bonnici }
169059bd2ad8SMarc Bonnici
169159bd2ad8SMarc Bonnici /*******************************************************************************
169259bd2ad8SMarc Bonnici * This function handles the FFA_SECONDARY_EP_REGISTER SMC to allow an SP to
169359bd2ad8SMarc Bonnici * register an entry point for initialization during a secondary cold boot.
169459bd2ad8SMarc Bonnici ******************************************************************************/
ffa_sec_ep_register_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)169559bd2ad8SMarc Bonnici static uint64_t ffa_sec_ep_register_handler(uint32_t smc_fid,
169659bd2ad8SMarc Bonnici bool secure_origin,
169759bd2ad8SMarc Bonnici uint64_t x1,
169859bd2ad8SMarc Bonnici uint64_t x2,
169959bd2ad8SMarc Bonnici uint64_t x3,
170059bd2ad8SMarc Bonnici uint64_t x4,
170159bd2ad8SMarc Bonnici void *cookie,
170259bd2ad8SMarc Bonnici void *handle,
170359bd2ad8SMarc Bonnici uint64_t flags)
170459bd2ad8SMarc Bonnici {
170559bd2ad8SMarc Bonnici struct secure_partition_desc *sp;
170659bd2ad8SMarc Bonnici struct sp_exec_ctx *sp_ctx;
170759bd2ad8SMarc Bonnici
170859bd2ad8SMarc Bonnici /* This request cannot originate from the Normal world. */
170959bd2ad8SMarc Bonnici if (!secure_origin) {
171059bd2ad8SMarc Bonnici WARN("%s: Can only be called from SWd.\n", __func__);
171159bd2ad8SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
171259bd2ad8SMarc Bonnici }
171359bd2ad8SMarc Bonnici
171459bd2ad8SMarc Bonnici /* Get the context of the current SP. */
171559bd2ad8SMarc Bonnici sp = spmc_get_current_sp_ctx();
171659bd2ad8SMarc Bonnici if (sp == NULL) {
171759bd2ad8SMarc Bonnici WARN("%s: Cannot find SP context.\n", __func__);
171859bd2ad8SMarc Bonnici return spmc_ffa_error_return(handle,
171959bd2ad8SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
172059bd2ad8SMarc Bonnici }
172159bd2ad8SMarc Bonnici
172259bd2ad8SMarc Bonnici /* Only an S-EL1 SP should be invoking this ABI. */
172359bd2ad8SMarc Bonnici if (sp->runtime_el != S_EL1) {
172459bd2ad8SMarc Bonnici WARN("%s: Can only be called for a S-EL1 SP.\n", __func__);
172559bd2ad8SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
172659bd2ad8SMarc Bonnici }
172759bd2ad8SMarc Bonnici
172859bd2ad8SMarc Bonnici /* Ensure the SP is in its initialization state. */
172959bd2ad8SMarc Bonnici sp_ctx = spmc_get_sp_ec(sp);
173059bd2ad8SMarc Bonnici if (sp_ctx->rt_model != RT_MODEL_INIT) {
173159bd2ad8SMarc Bonnici WARN("%s: Can only be called during SP initialization.\n",
173259bd2ad8SMarc Bonnici __func__);
173359bd2ad8SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
173459bd2ad8SMarc Bonnici }
173559bd2ad8SMarc Bonnici
173659bd2ad8SMarc Bonnici /* Perform initial validation of the secondary entry point. */
173759bd2ad8SMarc Bonnici if (validate_secondary_ep(x1, sp)) {
173859bd2ad8SMarc Bonnici WARN("%s: Invalid entry point provided (0x%lx).\n",
173959bd2ad8SMarc Bonnici __func__, x1);
174059bd2ad8SMarc Bonnici return spmc_ffa_error_return(handle,
174159bd2ad8SMarc Bonnici FFA_ERROR_INVALID_PARAMETER);
174259bd2ad8SMarc Bonnici }
174359bd2ad8SMarc Bonnici
174459bd2ad8SMarc Bonnici /*
174559bd2ad8SMarc Bonnici * Update the secondary entrypoint in SP context.
174659bd2ad8SMarc Bonnici * We don't need a lock here as during partition initialization there
174759bd2ad8SMarc Bonnici * will only be a single core online.
174859bd2ad8SMarc Bonnici */
174959bd2ad8SMarc Bonnici sp->secondary_ep = x1;
175059bd2ad8SMarc Bonnici VERBOSE("%s: 0x%lx\n", __func__, sp->secondary_ep);
175159bd2ad8SMarc Bonnici
175259bd2ad8SMarc Bonnici SMC_RET1(handle, FFA_SUCCESS_SMC32);
175359bd2ad8SMarc Bonnici }
175459bd2ad8SMarc Bonnici
1755c2b14343SMarc Bonnici /*******************************************************************************
17561f6b2b26SNishant Sharma * Permissions are encoded using a different format in the FFA_MEM_PERM_* ABIs
17571f6b2b26SNishant Sharma * than in the Trusted Firmware, where the mmap_attr_t enum type is used. This
17581f6b2b26SNishant Sharma * function converts a permission value from the FF-A format to the mmap_attr_t
17591f6b2b26SNishant Sharma * format by setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and
17601f6b2b26SNishant Sharma * MT_EXECUTE/MT_EXECUTE_NEVER. The other fields are left as 0 because they are
17611f6b2b26SNishant Sharma * ignored by the function xlat_change_mem_attributes_ctx().
17621f6b2b26SNishant Sharma ******************************************************************************/
ffa_perm_to_mmap_perm(unsigned int perms)17631f6b2b26SNishant Sharma static unsigned int ffa_perm_to_mmap_perm(unsigned int perms)
17641f6b2b26SNishant Sharma {
17651f6b2b26SNishant Sharma unsigned int tf_attr = 0U;
17661f6b2b26SNishant Sharma unsigned int access;
17671f6b2b26SNishant Sharma
17681f6b2b26SNishant Sharma /* Deal with data access permissions first. */
17691f6b2b26SNishant Sharma access = (perms & FFA_MEM_PERM_DATA_MASK) >> FFA_MEM_PERM_DATA_SHIFT;
17701f6b2b26SNishant Sharma
17711f6b2b26SNishant Sharma switch (access) {
17721f6b2b26SNishant Sharma case FFA_MEM_PERM_DATA_RW:
17731f6b2b26SNishant Sharma /* Return 0 if the execute is set with RW. */
17741f6b2b26SNishant Sharma if ((perms & FFA_MEM_PERM_INST_NON_EXEC) != 0) {
17751f6b2b26SNishant Sharma tf_attr |= MT_RW | MT_USER | MT_EXECUTE_NEVER;
17761f6b2b26SNishant Sharma }
17771f6b2b26SNishant Sharma break;
17781f6b2b26SNishant Sharma
17791f6b2b26SNishant Sharma case FFA_MEM_PERM_DATA_RO:
17801f6b2b26SNishant Sharma tf_attr |= MT_RO | MT_USER;
17811f6b2b26SNishant Sharma /* Deal with the instruction access permissions next. */
17821f6b2b26SNishant Sharma if ((perms & FFA_MEM_PERM_INST_NON_EXEC) == 0) {
17831f6b2b26SNishant Sharma tf_attr |= MT_EXECUTE;
17841f6b2b26SNishant Sharma } else {
17851f6b2b26SNishant Sharma tf_attr |= MT_EXECUTE_NEVER;
17861f6b2b26SNishant Sharma }
17871f6b2b26SNishant Sharma break;
17881f6b2b26SNishant Sharma
17891f6b2b26SNishant Sharma case FFA_MEM_PERM_DATA_NA:
17901f6b2b26SNishant Sharma default:
17911f6b2b26SNishant Sharma return tf_attr;
17921f6b2b26SNishant Sharma }
17931f6b2b26SNishant Sharma
17941f6b2b26SNishant Sharma return tf_attr;
17951f6b2b26SNishant Sharma }
17961f6b2b26SNishant Sharma
17971f6b2b26SNishant Sharma /*******************************************************************************
17981f6b2b26SNishant Sharma * Handler to set the permissions of a set of contiguous pages of a S-EL0 SP
17991f6b2b26SNishant Sharma ******************************************************************************/
ffa_mem_perm_set_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)18001f6b2b26SNishant Sharma static uint64_t ffa_mem_perm_set_handler(uint32_t smc_fid,
18011f6b2b26SNishant Sharma bool secure_origin,
18021f6b2b26SNishant Sharma uint64_t x1,
18031f6b2b26SNishant Sharma uint64_t x2,
18041f6b2b26SNishant Sharma uint64_t x3,
18051f6b2b26SNishant Sharma uint64_t x4,
18061f6b2b26SNishant Sharma void *cookie,
18071f6b2b26SNishant Sharma void *handle,
18081f6b2b26SNishant Sharma uint64_t flags)
18091f6b2b26SNishant Sharma {
18101f6b2b26SNishant Sharma struct secure_partition_desc *sp;
18111f6b2b26SNishant Sharma unsigned int idx;
18121f6b2b26SNishant Sharma uintptr_t base_va = (uintptr_t) x1;
18131f6b2b26SNishant Sharma size_t size = (size_t)(x2 * PAGE_SIZE);
18141f6b2b26SNishant Sharma uint32_t tf_attr;
18151f6b2b26SNishant Sharma int ret;
18161f6b2b26SNishant Sharma
18171f6b2b26SNishant Sharma /* This request cannot originate from the Normal world. */
18181f6b2b26SNishant Sharma if (!secure_origin) {
18191f6b2b26SNishant Sharma return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
18201f6b2b26SNishant Sharma }
18211f6b2b26SNishant Sharma
18221f6b2b26SNishant Sharma if (size == 0) {
18231f6b2b26SNishant Sharma return spmc_ffa_error_return(handle,
18241f6b2b26SNishant Sharma FFA_ERROR_INVALID_PARAMETER);
18251f6b2b26SNishant Sharma }
18261f6b2b26SNishant Sharma
18271f6b2b26SNishant Sharma /* Get the context of the current SP. */
18281f6b2b26SNishant Sharma sp = spmc_get_current_sp_ctx();
18291f6b2b26SNishant Sharma if (sp == NULL) {
18301f6b2b26SNishant Sharma return spmc_ffa_error_return(handle,
18311f6b2b26SNishant Sharma FFA_ERROR_INVALID_PARAMETER);
18321f6b2b26SNishant Sharma }
18331f6b2b26SNishant Sharma
18341f6b2b26SNishant Sharma /* A S-EL1 SP has no business invoking this ABI. */
18351f6b2b26SNishant Sharma if (sp->runtime_el == S_EL1) {
18361f6b2b26SNishant Sharma return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
18371f6b2b26SNishant Sharma }
18381f6b2b26SNishant Sharma
18391f6b2b26SNishant Sharma if ((x3 & ~((uint64_t)FFA_MEM_PERM_MASK)) != 0) {
18401f6b2b26SNishant Sharma return spmc_ffa_error_return(handle,
18411f6b2b26SNishant Sharma FFA_ERROR_INVALID_PARAMETER);
18421f6b2b26SNishant Sharma }
18431f6b2b26SNishant Sharma
18441f6b2b26SNishant Sharma /* Get the execution context of the calling SP. */
18451f6b2b26SNishant Sharma idx = get_ec_index(sp);
18461f6b2b26SNishant Sharma
18471f6b2b26SNishant Sharma /*
18481f6b2b26SNishant Sharma * Ensure that the S-EL0 SP is initialising itself. We do not need to
18491f6b2b26SNishant Sharma * synchronise this operation through a spinlock since a S-EL0 SP is UP
18501f6b2b26SNishant Sharma * and can only be initialising on this cpu.
18511f6b2b26SNishant Sharma */
18521f6b2b26SNishant Sharma if (sp->ec[idx].rt_model != RT_MODEL_INIT) {
18531f6b2b26SNishant Sharma return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
18541f6b2b26SNishant Sharma }
18551f6b2b26SNishant Sharma
18561f6b2b26SNishant Sharma VERBOSE("Setting memory permissions:\n");
18571f6b2b26SNishant Sharma VERBOSE(" Start address : 0x%lx\n", base_va);
18581f6b2b26SNishant Sharma VERBOSE(" Number of pages: %lu (%zu bytes)\n", x2, size);
18591f6b2b26SNishant Sharma VERBOSE(" Attributes : 0x%x\n", (uint32_t)x3);
18601f6b2b26SNishant Sharma
18611f6b2b26SNishant Sharma /* Convert inbound permissions to TF-A permission attributes */
18621f6b2b26SNishant Sharma tf_attr = ffa_perm_to_mmap_perm((unsigned int)x3);
18631f6b2b26SNishant Sharma if (tf_attr == 0U) {
18641f6b2b26SNishant Sharma return spmc_ffa_error_return(handle,
18651f6b2b26SNishant Sharma FFA_ERROR_INVALID_PARAMETER);
18661f6b2b26SNishant Sharma }
18671f6b2b26SNishant Sharma
18681f6b2b26SNishant Sharma /* Request the change in permissions */
18691f6b2b26SNishant Sharma ret = xlat_change_mem_attributes_ctx(sp->xlat_ctx_handle,
18701f6b2b26SNishant Sharma base_va, size, tf_attr);
18711f6b2b26SNishant Sharma if (ret != 0) {
18721f6b2b26SNishant Sharma return spmc_ffa_error_return(handle,
18731f6b2b26SNishant Sharma FFA_ERROR_INVALID_PARAMETER);
18741f6b2b26SNishant Sharma }
18751f6b2b26SNishant Sharma
18761f6b2b26SNishant Sharma SMC_RET1(handle, FFA_SUCCESS_SMC32);
18771f6b2b26SNishant Sharma }
18781f6b2b26SNishant Sharma
18791f6b2b26SNishant Sharma /*******************************************************************************
18801f6b2b26SNishant Sharma * Permissions are encoded using a different format in the FFA_MEM_PERM_* ABIs
18811f6b2b26SNishant Sharma * than in the Trusted Firmware, where the mmap_attr_t enum type is used. This
18821f6b2b26SNishant Sharma * function converts a permission value from the mmap_attr_t format to the FF-A
18831f6b2b26SNishant Sharma * format.
18841f6b2b26SNishant Sharma ******************************************************************************/
mmap_perm_to_ffa_perm(unsigned int attr)18851f6b2b26SNishant Sharma static unsigned int mmap_perm_to_ffa_perm(unsigned int attr)
18861f6b2b26SNishant Sharma {
18871f6b2b26SNishant Sharma unsigned int perms = 0U;
18881f6b2b26SNishant Sharma unsigned int data_access;
18891f6b2b26SNishant Sharma
18901f6b2b26SNishant Sharma if ((attr & MT_USER) == 0) {
18911f6b2b26SNishant Sharma /* No access from EL0. */
18921f6b2b26SNishant Sharma data_access = FFA_MEM_PERM_DATA_NA;
18931f6b2b26SNishant Sharma } else {
18941f6b2b26SNishant Sharma if ((attr & MT_RW) != 0) {
18951f6b2b26SNishant Sharma data_access = FFA_MEM_PERM_DATA_RW;
18961f6b2b26SNishant Sharma } else {
18971f6b2b26SNishant Sharma data_access = FFA_MEM_PERM_DATA_RO;
18981f6b2b26SNishant Sharma }
18991f6b2b26SNishant Sharma }
19001f6b2b26SNishant Sharma
19011f6b2b26SNishant Sharma perms |= (data_access & FFA_MEM_PERM_DATA_MASK)
19021f6b2b26SNishant Sharma << FFA_MEM_PERM_DATA_SHIFT;
19031f6b2b26SNishant Sharma
19041f6b2b26SNishant Sharma if ((attr & MT_EXECUTE_NEVER) != 0U) {
19051f6b2b26SNishant Sharma perms |= FFA_MEM_PERM_INST_NON_EXEC;
19061f6b2b26SNishant Sharma }
19071f6b2b26SNishant Sharma
19081f6b2b26SNishant Sharma return perms;
19091f6b2b26SNishant Sharma }
19101f6b2b26SNishant Sharma
19111f6b2b26SNishant Sharma /*******************************************************************************
19121f6b2b26SNishant Sharma * Handler to get the permissions of a set of contiguous pages of a S-EL0 SP
19131f6b2b26SNishant Sharma ******************************************************************************/
ffa_mem_perm_get_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)19141f6b2b26SNishant Sharma static uint64_t ffa_mem_perm_get_handler(uint32_t smc_fid,
19151f6b2b26SNishant Sharma bool secure_origin,
19161f6b2b26SNishant Sharma uint64_t x1,
19171f6b2b26SNishant Sharma uint64_t x2,
19181f6b2b26SNishant Sharma uint64_t x3,
19191f6b2b26SNishant Sharma uint64_t x4,
19201f6b2b26SNishant Sharma void *cookie,
19211f6b2b26SNishant Sharma void *handle,
19221f6b2b26SNishant Sharma uint64_t flags)
19231f6b2b26SNishant Sharma {
19241f6b2b26SNishant Sharma struct secure_partition_desc *sp;
19251f6b2b26SNishant Sharma unsigned int idx;
19261f6b2b26SNishant Sharma uintptr_t base_va = (uintptr_t)x1;
19279bfe78c2SLevi Yun uint64_t max_page_count = x2 + 1;
19289bfe78c2SLevi Yun uint64_t page_count = 0;
19299bfe78c2SLevi Yun uint32_t base_page_attr = 0;
19309bfe78c2SLevi Yun uint32_t page_attr = 0;
19319bfe78c2SLevi Yun unsigned int table_level;
19321f6b2b26SNishant Sharma int ret;
19331f6b2b26SNishant Sharma
19341f6b2b26SNishant Sharma /* This request cannot originate from the Normal world. */
19351f6b2b26SNishant Sharma if (!secure_origin) {
19361f6b2b26SNishant Sharma return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
19371f6b2b26SNishant Sharma }
19381f6b2b26SNishant Sharma
19391f6b2b26SNishant Sharma /* Get the context of the current SP. */
19401f6b2b26SNishant Sharma sp = spmc_get_current_sp_ctx();
19411f6b2b26SNishant Sharma if (sp == NULL) {
19421f6b2b26SNishant Sharma return spmc_ffa_error_return(handle,
19431f6b2b26SNishant Sharma FFA_ERROR_INVALID_PARAMETER);
19441f6b2b26SNishant Sharma }
19451f6b2b26SNishant Sharma
19461f6b2b26SNishant Sharma /* A S-EL1 SP has no business invoking this ABI. */
19471f6b2b26SNishant Sharma if (sp->runtime_el == S_EL1) {
19481f6b2b26SNishant Sharma return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
19491f6b2b26SNishant Sharma }
19501f6b2b26SNishant Sharma
19511f6b2b26SNishant Sharma /* Get the execution context of the calling SP. */
19521f6b2b26SNishant Sharma idx = get_ec_index(sp);
19531f6b2b26SNishant Sharma
19541f6b2b26SNishant Sharma /*
19551f6b2b26SNishant Sharma * Ensure that the S-EL0 SP is initialising itself. We do not need to
19561f6b2b26SNishant Sharma * synchronise this operation through a spinlock since a S-EL0 SP is UP
19571f6b2b26SNishant Sharma * and can only be initialising on this cpu.
19581f6b2b26SNishant Sharma */
19591f6b2b26SNishant Sharma if (sp->ec[idx].rt_model != RT_MODEL_INIT) {
19601f6b2b26SNishant Sharma return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
19611f6b2b26SNishant Sharma }
19621f6b2b26SNishant Sharma
19639bfe78c2SLevi Yun base_va &= ~(PAGE_SIZE_MASK);
19649bfe78c2SLevi Yun
19651f6b2b26SNishant Sharma /* Request the permissions */
19669bfe78c2SLevi Yun ret = xlat_get_mem_attributes_ctx(sp->xlat_ctx_handle, base_va,
19679bfe78c2SLevi Yun &base_page_attr, &table_level);
19681f6b2b26SNishant Sharma if (ret != 0) {
19691f6b2b26SNishant Sharma return spmc_ffa_error_return(handle,
19701f6b2b26SNishant Sharma FFA_ERROR_INVALID_PARAMETER);
19711f6b2b26SNishant Sharma }
19721f6b2b26SNishant Sharma
19739bfe78c2SLevi Yun /*
19749bfe78c2SLevi Yun * Caculate how many pages in this block entry from base_va including
19759bfe78c2SLevi Yun * its page.
19769bfe78c2SLevi Yun */
19779bfe78c2SLevi Yun page_count = ((XLAT_BLOCK_SIZE(table_level) -
19789bfe78c2SLevi Yun (base_va & XLAT_BLOCK_MASK(table_level))) >> PAGE_SIZE_SHIFT);
19799bfe78c2SLevi Yun base_va += XLAT_BLOCK_SIZE(table_level);
19801f6b2b26SNishant Sharma
19819bfe78c2SLevi Yun while ((page_count < max_page_count) && (base_va != 0x00)) {
19829bfe78c2SLevi Yun ret = xlat_get_mem_attributes_ctx(sp->xlat_ctx_handle, base_va,
19839bfe78c2SLevi Yun &page_attr, &table_level);
19849bfe78c2SLevi Yun if (ret != 0) {
19859bfe78c2SLevi Yun return spmc_ffa_error_return(handle,
19869bfe78c2SLevi Yun FFA_ERROR_INVALID_PARAMETER);
19879bfe78c2SLevi Yun }
19889bfe78c2SLevi Yun
19899bfe78c2SLevi Yun if (page_attr != base_page_attr) {
19909bfe78c2SLevi Yun break;
19919bfe78c2SLevi Yun }
19929bfe78c2SLevi Yun
19939bfe78c2SLevi Yun base_va += XLAT_BLOCK_SIZE(table_level);
19949bfe78c2SLevi Yun page_count += (XLAT_BLOCK_SIZE(table_level) >> PAGE_SIZE_SHIFT);
19959bfe78c2SLevi Yun }
19969bfe78c2SLevi Yun
19979bfe78c2SLevi Yun if (page_count > max_page_count) {
19989bfe78c2SLevi Yun page_count = max_page_count;
19999bfe78c2SLevi Yun }
20009bfe78c2SLevi Yun
20019bfe78c2SLevi Yun /* Convert TF-A permission to FF-A permissions attributes. */
20029bfe78c2SLevi Yun x2 = mmap_perm_to_ffa_perm(base_page_attr);
20039bfe78c2SLevi Yun
20049bfe78c2SLevi Yun /* x3 should be page count - 1 */
20059bfe78c2SLevi Yun SMC_RET4(handle, FFA_SUCCESS_SMC32, 0, x2, --page_count);
20061f6b2b26SNishant Sharma }
20071f6b2b26SNishant Sharma
20081f6b2b26SNishant Sharma /*******************************************************************************
20095096aeb2SMarc Bonnici * This function will parse the Secure Partition Manifest. From manifest, it
20105096aeb2SMarc Bonnici * will fetch details for preparing Secure partition image context and secure
20115096aeb2SMarc Bonnici * partition image boot arguments if any.
20125096aeb2SMarc Bonnici ******************************************************************************/
sp_manifest_parse(void * sp_manifest,int offset,struct secure_partition_desc * sp,entry_point_info_t * ep_info,int32_t * boot_info_reg)20135096aeb2SMarc Bonnici static int sp_manifest_parse(void *sp_manifest, int offset,
20145096aeb2SMarc Bonnici struct secure_partition_desc *sp,
20152e219215SAchin Gupta entry_point_info_t *ep_info,
20162e219215SAchin Gupta int32_t *boot_info_reg)
20175096aeb2SMarc Bonnici {
20185096aeb2SMarc Bonnici int32_t ret, node;
20195096aeb2SMarc Bonnici uint32_t config_32;
2020*0322d7afSJay Monkman int uuid_size;
2021*0322d7afSJay Monkman const fdt32_t *prop;
20225096aeb2SMarc Bonnici
20235096aeb2SMarc Bonnici /*
20245096aeb2SMarc Bonnici * Look for the mandatory fields that are expected to be present in
20255096aeb2SMarc Bonnici * the SP manifests.
20265096aeb2SMarc Bonnici */
20275096aeb2SMarc Bonnici node = fdt_path_offset(sp_manifest, "/");
20285096aeb2SMarc Bonnici if (node < 0) {
20295096aeb2SMarc Bonnici ERROR("Did not find root node.\n");
20305096aeb2SMarc Bonnici return node;
20315096aeb2SMarc Bonnici }
20325096aeb2SMarc Bonnici
2033*0322d7afSJay Monkman prop = fdt_getprop(sp_manifest, node, "uuid", &uuid_size);
2034*0322d7afSJay Monkman if (prop == NULL) {
2035*0322d7afSJay Monkman ERROR("Couldn't find property uuid in manifest\n");
2036*0322d7afSJay Monkman return -FDT_ERR_NOTFOUND;
2037*0322d7afSJay Monkman }
2038*0322d7afSJay Monkman
2039*0322d7afSJay Monkman sp->num_uuids = (uint32_t)uuid_size / sizeof(struct ffa_uuid);
2040*0322d7afSJay Monkman if (sp->num_uuids > ARRAY_SIZE(sp->uuid_array)) {
2041*0322d7afSJay Monkman ERROR("Too many UUIDs (%d) in manifest, maximum is %zd\n",
2042*0322d7afSJay Monkman sp->num_uuids, ARRAY_SIZE(sp->uuid_array));
2043*0322d7afSJay Monkman return -FDT_ERR_BADVALUE;
2044*0322d7afSJay Monkman }
2045*0322d7afSJay Monkman
2046857f5790SMarc Bonnici ret = fdt_read_uint32_array(sp_manifest, node, "uuid",
2047*0322d7afSJay Monkman (uuid_size / sizeof(uint32_t)),
2048*0322d7afSJay Monkman sp->uuid_array[0].uuid);
2049857f5790SMarc Bonnici if (ret != 0) {
2050857f5790SMarc Bonnici ERROR("Missing Secure Partition UUID.\n");
2051857f5790SMarc Bonnici return ret;
2052857f5790SMarc Bonnici }
2053857f5790SMarc Bonnici
2054*0322d7afSJay Monkman for (uint32_t i = 0; i < sp->num_uuids; i++) {
2055*0322d7afSJay Monkman for (uint32_t j = 0; j < i; j++) {
2056*0322d7afSJay Monkman if (memcmp(&sp->uuid_array[i], &sp->uuid_array[j],
2057*0322d7afSJay Monkman sizeof(struct ffa_uuid)) == 0) {
2058*0322d7afSJay Monkman ERROR("Duplicate UUIDs in manifest: 0x%x 0x%x 0x%x 0x%x\n",
2059*0322d7afSJay Monkman sp->uuid_array[i].uuid[0],
2060*0322d7afSJay Monkman sp->uuid_array[i].uuid[1],
2061*0322d7afSJay Monkman sp->uuid_array[i].uuid[2],
2062*0322d7afSJay Monkman sp->uuid_array[i].uuid[3]);
2063*0322d7afSJay Monkman return -FDT_ERR_BADVALUE;
2064*0322d7afSJay Monkman }
2065*0322d7afSJay Monkman }
2066*0322d7afSJay Monkman }
2067*0322d7afSJay Monkman
20685096aeb2SMarc Bonnici ret = fdt_read_uint32(sp_manifest, node, "exception-level", &config_32);
20695096aeb2SMarc Bonnici if (ret != 0) {
20705096aeb2SMarc Bonnici ERROR("Missing SP Exception Level information.\n");
20715096aeb2SMarc Bonnici return ret;
20725096aeb2SMarc Bonnici }
20735096aeb2SMarc Bonnici
20745096aeb2SMarc Bonnici sp->runtime_el = config_32;
20755096aeb2SMarc Bonnici
20765096aeb2SMarc Bonnici ret = fdt_read_uint32(sp_manifest, node, "ffa-version", &config_32);
20775096aeb2SMarc Bonnici if (ret != 0) {
20785096aeb2SMarc Bonnici ERROR("Missing Secure Partition FF-A Version.\n");
20795096aeb2SMarc Bonnici return ret;
20805096aeb2SMarc Bonnici }
20815096aeb2SMarc Bonnici
20825096aeb2SMarc Bonnici sp->ffa_version = config_32;
20835096aeb2SMarc Bonnici
20845096aeb2SMarc Bonnici ret = fdt_read_uint32(sp_manifest, node, "execution-state", &config_32);
20855096aeb2SMarc Bonnici if (ret != 0) {
20865096aeb2SMarc Bonnici ERROR("Missing Secure Partition Execution State.\n");
20875096aeb2SMarc Bonnici return ret;
20885096aeb2SMarc Bonnici }
20895096aeb2SMarc Bonnici
20905096aeb2SMarc Bonnici sp->execution_state = config_32;
20915096aeb2SMarc Bonnici
20925b0219ddSMarc Bonnici ret = fdt_read_uint32(sp_manifest, node,
20933de378ffSMarc Bonnici "messaging-method", &config_32);
20943de378ffSMarc Bonnici if (ret != 0) {
20953de378ffSMarc Bonnici ERROR("Missing Secure Partition messaging method.\n");
20963de378ffSMarc Bonnici return ret;
20973de378ffSMarc Bonnici }
20983de378ffSMarc Bonnici
20993de378ffSMarc Bonnici /* Validate this entry, we currently only support direct messaging. */
21003de378ffSMarc Bonnici if ((config_32 & ~(FFA_PARTITION_DIRECT_REQ_RECV |
210109a580b7SLevi Yun FFA_PARTITION_DIRECT_REQ_SEND |
210209a580b7SLevi Yun FFA_PARTITION_DIRECT_REQ2_RECV |
210309a580b7SLevi Yun FFA_PARTITION_DIRECT_REQ2_SEND)) != 0U) {
21043de378ffSMarc Bonnici WARN("Invalid Secure Partition messaging method (0x%x)\n",
21053de378ffSMarc Bonnici config_32);
21063de378ffSMarc Bonnici return -EINVAL;
21073de378ffSMarc Bonnici }
21083de378ffSMarc Bonnici
21093de378ffSMarc Bonnici sp->properties = config_32;
21103de378ffSMarc Bonnici
21113de378ffSMarc Bonnici ret = fdt_read_uint32(sp_manifest, node,
21125b0219ddSMarc Bonnici "execution-ctx-count", &config_32);
21135b0219ddSMarc Bonnici
21145b0219ddSMarc Bonnici if (ret != 0) {
21155b0219ddSMarc Bonnici ERROR("Missing SP Execution Context Count.\n");
21165b0219ddSMarc Bonnici return ret;
21175b0219ddSMarc Bonnici }
21185b0219ddSMarc Bonnici
21195b0219ddSMarc Bonnici /*
21205b0219ddSMarc Bonnici * Ensure this field is set correctly in the manifest however
21215b0219ddSMarc Bonnici * since this is currently a hardcoded value for S-EL1 partitions
21225b0219ddSMarc Bonnici * we don't need to save it here, just validate.
21235b0219ddSMarc Bonnici */
212448db2b01SNishant Sharma if ((sp->runtime_el == S_EL1) && (config_32 != PLATFORM_CORE_COUNT)) {
21255b0219ddSMarc Bonnici ERROR("SP Execution Context Count (%u) must be %u.\n",
21265b0219ddSMarc Bonnici config_32, PLATFORM_CORE_COUNT);
21275b0219ddSMarc Bonnici return -EINVAL;
21285b0219ddSMarc Bonnici }
21295b0219ddSMarc Bonnici
21305096aeb2SMarc Bonnici /*
21315096aeb2SMarc Bonnici * Look for the optional fields that are expected to be present in
21325096aeb2SMarc Bonnici * an SP manifest.
21335096aeb2SMarc Bonnici */
21345096aeb2SMarc Bonnici ret = fdt_read_uint32(sp_manifest, node, "id", &config_32);
21355096aeb2SMarc Bonnici if (ret != 0) {
21365096aeb2SMarc Bonnici WARN("Missing Secure Partition ID.\n");
21375096aeb2SMarc Bonnici } else {
21385096aeb2SMarc Bonnici if (!is_ffa_secure_id_valid(config_32)) {
21395096aeb2SMarc Bonnici ERROR("Invalid Secure Partition ID (0x%x).\n",
21405096aeb2SMarc Bonnici config_32);
21415096aeb2SMarc Bonnici return -EINVAL;
21425096aeb2SMarc Bonnici }
21435096aeb2SMarc Bonnici sp->sp_id = config_32;
21445096aeb2SMarc Bonnici }
21455096aeb2SMarc Bonnici
214659bd2ad8SMarc Bonnici ret = fdt_read_uint32(sp_manifest, node,
214759bd2ad8SMarc Bonnici "power-management-messages", &config_32);
214859bd2ad8SMarc Bonnici if (ret != 0) {
214959bd2ad8SMarc Bonnici WARN("Missing Power Management Messages entry.\n");
215059bd2ad8SMarc Bonnici } else {
215159173793SNishant Sharma if ((sp->runtime_el == S_EL0) && (config_32 != 0)) {
215259173793SNishant Sharma ERROR("Power messages not supported for S-EL0 SP\n");
215359173793SNishant Sharma return -EINVAL;
215459173793SNishant Sharma }
215559173793SNishant Sharma
215659bd2ad8SMarc Bonnici /*
215759bd2ad8SMarc Bonnici * Ensure only the currently supported power messages have
215859bd2ad8SMarc Bonnici * been requested.
215959bd2ad8SMarc Bonnici */
216059bd2ad8SMarc Bonnici if (config_32 & ~(FFA_PM_MSG_SUB_CPU_OFF |
216159bd2ad8SMarc Bonnici FFA_PM_MSG_SUB_CPU_SUSPEND |
216259bd2ad8SMarc Bonnici FFA_PM_MSG_SUB_CPU_SUSPEND_RESUME)) {
216359bd2ad8SMarc Bonnici ERROR("Requested unsupported PM messages (%x)\n",
216459bd2ad8SMarc Bonnici config_32);
216559bd2ad8SMarc Bonnici return -EINVAL;
216659bd2ad8SMarc Bonnici }
216759bd2ad8SMarc Bonnici sp->pwr_mgmt_msgs = config_32;
216859bd2ad8SMarc Bonnici }
216959bd2ad8SMarc Bonnici
21702e219215SAchin Gupta ret = fdt_read_uint32(sp_manifest, node,
21712e219215SAchin Gupta "gp-register-num", &config_32);
21722e219215SAchin Gupta if (ret != 0) {
21732e219215SAchin Gupta WARN("Missing boot information register.\n");
21742e219215SAchin Gupta } else {
21752e219215SAchin Gupta /* Check if a register number between 0-3 is specified. */
21762e219215SAchin Gupta if (config_32 < 4) {
21772e219215SAchin Gupta *boot_info_reg = config_32;
21782e219215SAchin Gupta } else {
21792e219215SAchin Gupta WARN("Incorrect boot information register (%u).\n",
21802e219215SAchin Gupta config_32);
21812e219215SAchin Gupta }
21822e219215SAchin Gupta }
21832e219215SAchin Gupta
2184ce299f95SAndrei Homescu ret = fdt_read_uint32(sp_manifest, node,
2185ce299f95SAndrei Homescu "vm-availability-messages", &config_32);
2186ce299f95SAndrei Homescu if (ret != 0) {
2187ce299f95SAndrei Homescu WARN("Missing VM availability messaging.\n");
2188ce299f95SAndrei Homescu } else if ((sp->properties & FFA_PARTITION_DIRECT_REQ_RECV) == 0) {
2189ce299f95SAndrei Homescu ERROR("VM availability messaging requested without "
2190ce299f95SAndrei Homescu "direct message receive support.\n");
2191ce299f95SAndrei Homescu return -EINVAL;
2192ce299f95SAndrei Homescu } else {
2193ce299f95SAndrei Homescu /* Validate this entry. */
2194ce299f95SAndrei Homescu if ((config_32 & ~(FFA_VM_AVAILABILITY_CREATED |
2195ce299f95SAndrei Homescu FFA_VM_AVAILABILITY_DESTROYED)) != 0U) {
2196ce299f95SAndrei Homescu WARN("Invalid VM availability messaging (0x%x)\n",
2197ce299f95SAndrei Homescu config_32);
2198ce299f95SAndrei Homescu return -EINVAL;
2199ce299f95SAndrei Homescu }
2200ce299f95SAndrei Homescu
2201ce299f95SAndrei Homescu if ((config_32 & FFA_VM_AVAILABILITY_CREATED) != 0U) {
2202ce299f95SAndrei Homescu sp->properties |= FFA_PARTITION_VM_CREATED;
2203ce299f95SAndrei Homescu }
2204ce299f95SAndrei Homescu if ((config_32 & FFA_VM_AVAILABILITY_DESTROYED) != 0U) {
2205ce299f95SAndrei Homescu sp->properties |= FFA_PARTITION_VM_DESTROYED;
2206ce299f95SAndrei Homescu }
2207ce299f95SAndrei Homescu }
2208ce299f95SAndrei Homescu
22095096aeb2SMarc Bonnici return 0;
22105096aeb2SMarc Bonnici }
22115096aeb2SMarc Bonnici
22125096aeb2SMarc Bonnici /*******************************************************************************
22135096aeb2SMarc Bonnici * This function gets the Secure Partition Manifest base and maps the manifest
22145096aeb2SMarc Bonnici * region.
22155096aeb2SMarc Bonnici * Currently only one Secure Partition manifest is considered which is used to
22165096aeb2SMarc Bonnici * prepare the context for the single Secure Partition.
22175096aeb2SMarc Bonnici ******************************************************************************/
find_and_prepare_sp_context(void)22185096aeb2SMarc Bonnici static int find_and_prepare_sp_context(void)
22195096aeb2SMarc Bonnici {
22205096aeb2SMarc Bonnici void *sp_manifest;
22215096aeb2SMarc Bonnici uintptr_t manifest_base;
2222aae2370cSYeoreum Yun uintptr_t manifest_base_align __maybe_unused;
22235096aeb2SMarc Bonnici entry_point_info_t *next_image_ep_info;
22242e219215SAchin Gupta int32_t ret, boot_info_reg = -1;
22255096aeb2SMarc Bonnici struct secure_partition_desc *sp;
2226aae2370cSYeoreum Yun struct transfer_list_header *tl __maybe_unused;
2227aae2370cSYeoreum Yun struct transfer_list_entry *te __maybe_unused;
22285096aeb2SMarc Bonnici
22295096aeb2SMarc Bonnici next_image_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
22305096aeb2SMarc Bonnici if (next_image_ep_info == NULL) {
22315096aeb2SMarc Bonnici WARN("No Secure Partition image provided by BL2.\n");
22325096aeb2SMarc Bonnici return -ENOENT;
22335096aeb2SMarc Bonnici }
22345096aeb2SMarc Bonnici
2235aae2370cSYeoreum Yun
2236aae2370cSYeoreum Yun #if TRANSFER_LIST && !RESET_TO_BL31
2237aae2370cSYeoreum Yun tl = (struct transfer_list_header *)next_image_ep_info->args.arg3;
2238aae2370cSYeoreum Yun te = transfer_list_find(tl, TL_TAG_DT_FFA_MANIFEST);
2239aae2370cSYeoreum Yun if (te == NULL) {
2240aae2370cSYeoreum Yun WARN("Secure Partition manifest absent.\n");
2241aae2370cSYeoreum Yun return -ENOENT;
2242aae2370cSYeoreum Yun }
2243aae2370cSYeoreum Yun
2244aae2370cSYeoreum Yun sp_manifest = (void *)transfer_list_entry_data(te);
2245aae2370cSYeoreum Yun manifest_base = (uintptr_t)sp_manifest;
2246aae2370cSYeoreum Yun #else
22475096aeb2SMarc Bonnici sp_manifest = (void *)next_image_ep_info->args.arg0;
22485096aeb2SMarc Bonnici if (sp_manifest == NULL) {
22495096aeb2SMarc Bonnici WARN("Secure Partition manifest absent.\n");
22505096aeb2SMarc Bonnici return -ENOENT;
22515096aeb2SMarc Bonnici }
22525096aeb2SMarc Bonnici
22535096aeb2SMarc Bonnici manifest_base = (uintptr_t)sp_manifest;
22545096aeb2SMarc Bonnici manifest_base_align = page_align(manifest_base, DOWN);
22555096aeb2SMarc Bonnici
22565096aeb2SMarc Bonnici /*
22575096aeb2SMarc Bonnici * Map the secure partition manifest region in the EL3 translation
22585096aeb2SMarc Bonnici * regime.
22595096aeb2SMarc Bonnici * Map an area equal to (2 * PAGE_SIZE) for now. During manifest base
22605096aeb2SMarc Bonnici * alignment the region of 1 PAGE_SIZE from manifest align base may
22615096aeb2SMarc Bonnici * not completely accommodate the secure partition manifest region.
22625096aeb2SMarc Bonnici */
22635096aeb2SMarc Bonnici ret = mmap_add_dynamic_region((unsigned long long)manifest_base_align,
22645096aeb2SMarc Bonnici manifest_base_align,
22655096aeb2SMarc Bonnici PAGE_SIZE * 2,
22665096aeb2SMarc Bonnici MT_RO_DATA);
22675096aeb2SMarc Bonnici if (ret != 0) {
22685096aeb2SMarc Bonnici ERROR("Error while mapping SP manifest (%d).\n", ret);
22695096aeb2SMarc Bonnici return ret;
22705096aeb2SMarc Bonnici }
2271aae2370cSYeoreum Yun #endif
22725096aeb2SMarc Bonnici
22735096aeb2SMarc Bonnici ret = fdt_node_offset_by_compatible(sp_manifest, -1,
22745096aeb2SMarc Bonnici "arm,ffa-manifest-1.0");
22755096aeb2SMarc Bonnici if (ret < 0) {
22765096aeb2SMarc Bonnici ERROR("Error happened in SP manifest reading.\n");
22775096aeb2SMarc Bonnici return -EINVAL;
22785096aeb2SMarc Bonnici }
22795096aeb2SMarc Bonnici
22805096aeb2SMarc Bonnici /*
22815096aeb2SMarc Bonnici * Store the size of the manifest so that it can be used later to pass
22825096aeb2SMarc Bonnici * the manifest as boot information later.
22835096aeb2SMarc Bonnici */
22845096aeb2SMarc Bonnici next_image_ep_info->args.arg1 = fdt_totalsize(sp_manifest);
228548db2b01SNishant Sharma INFO("Manifest adr = %lx , size = %lu bytes\n", manifest_base,
228648db2b01SNishant Sharma next_image_ep_info->args.arg1);
22875096aeb2SMarc Bonnici
22885096aeb2SMarc Bonnici /*
22895096aeb2SMarc Bonnici * Select an SP descriptor for initialising the partition's execution
22905096aeb2SMarc Bonnici * context on the primary CPU.
22915096aeb2SMarc Bonnici */
22925096aeb2SMarc Bonnici sp = spmc_get_current_sp_ctx();
22935096aeb2SMarc Bonnici
229448db2b01SNishant Sharma #if SPMC_AT_EL3_SEL0_SP
229548db2b01SNishant Sharma /* Assign translation tables context. */
229648db2b01SNishant Sharma sp_desc->xlat_ctx_handle = spm_get_sp_xlat_context();
229748db2b01SNishant Sharma
229848db2b01SNishant Sharma #endif /* SPMC_AT_EL3_SEL0_SP */
22995096aeb2SMarc Bonnici /* Initialize entry point information for the SP */
23005096aeb2SMarc Bonnici SET_PARAM_HEAD(next_image_ep_info, PARAM_EP, VERSION_1,
23015096aeb2SMarc Bonnici SECURE | EP_ST_ENABLE);
23025096aeb2SMarc Bonnici
23035096aeb2SMarc Bonnici /* Parse the SP manifest. */
23042e219215SAchin Gupta ret = sp_manifest_parse(sp_manifest, ret, sp, next_image_ep_info,
23052e219215SAchin Gupta &boot_info_reg);
23065096aeb2SMarc Bonnici if (ret != 0) {
23075096aeb2SMarc Bonnici ERROR("Error in Secure Partition manifest parsing.\n");
23085096aeb2SMarc Bonnici return ret;
23095096aeb2SMarc Bonnici }
23105096aeb2SMarc Bonnici
23115096aeb2SMarc Bonnici /* Perform any common initialisation. */
23122e219215SAchin Gupta spmc_sp_common_setup(sp, next_image_ep_info, boot_info_reg);
23135096aeb2SMarc Bonnici
23145096aeb2SMarc Bonnici /* Perform any initialisation specific to S-EL1 SPs. */
231548db2b01SNishant Sharma if (sp->runtime_el == S_EL1) {
23165096aeb2SMarc Bonnici spmc_el1_sp_setup(sp, next_image_ep_info);
23174053a647SLevi Yun spmc_sp_common_ep_commit(sp, next_image_ep_info);
231848db2b01SNishant Sharma }
231948db2b01SNishant Sharma #if SPMC_AT_EL3_SEL0_SP
23204053a647SLevi Yun /* Perform any initialisation specific to S-EL0 SPs. */
23214053a647SLevi Yun else if (sp->runtime_el == S_EL0) {
232248db2b01SNishant Sharma /* Setup spsr in endpoint info for common context management routine. */
232348db2b01SNishant Sharma spmc_el0_sp_spsr_setup(next_image_ep_info);
23245096aeb2SMarc Bonnici
23255096aeb2SMarc Bonnici spmc_sp_common_ep_commit(sp, next_image_ep_info);
23265096aeb2SMarc Bonnici
232748db2b01SNishant Sharma /*
232848db2b01SNishant Sharma * Perform any initialisation specific to S-EL0 not set by common
232948db2b01SNishant Sharma * context management routine.
233048db2b01SNishant Sharma */
233183c3da77SNishant Sharma spmc_el0_sp_setup(sp, boot_info_reg, sp_manifest);
233248db2b01SNishant Sharma }
233348db2b01SNishant Sharma #endif /* SPMC_AT_EL3_SEL0_SP */
23344053a647SLevi Yun else {
23354053a647SLevi Yun ERROR("Unexpected runtime EL: %u\n", sp->runtime_el);
23364053a647SLevi Yun return -EINVAL;
23374053a647SLevi Yun }
23384053a647SLevi Yun
23395096aeb2SMarc Bonnici return 0;
23405096aeb2SMarc Bonnici }
23415096aeb2SMarc Bonnici
23425096aeb2SMarc Bonnici /*******************************************************************************
23435096aeb2SMarc Bonnici * This function takes an SP context pointer and performs a synchronous entry
23445096aeb2SMarc Bonnici * into it.
23455096aeb2SMarc Bonnici ******************************************************************************/
logical_sp_init(void)23467affa25cSMarc Bonnici static int32_t logical_sp_init(void)
23477affa25cSMarc Bonnici {
23487affa25cSMarc Bonnici int32_t rc = 0;
23497affa25cSMarc Bonnici struct el3_lp_desc *el3_lp_descs;
23507affa25cSMarc Bonnici
23517affa25cSMarc Bonnici /* Perform initial validation of the Logical Partitions. */
23527affa25cSMarc Bonnici rc = el3_sp_desc_validate();
23537affa25cSMarc Bonnici if (rc != 0) {
23547affa25cSMarc Bonnici ERROR("Logical Partition validation failed!\n");
23557affa25cSMarc Bonnici return rc;
23567affa25cSMarc Bonnici }
23577affa25cSMarc Bonnici
23587affa25cSMarc Bonnici el3_lp_descs = get_el3_lp_array();
23597affa25cSMarc Bonnici
23607affa25cSMarc Bonnici INFO("Logical Secure Partition init start.\n");
23617affa25cSMarc Bonnici for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) {
23627affa25cSMarc Bonnici rc = el3_lp_descs[i].init();
23637affa25cSMarc Bonnici if (rc != 0) {
23647affa25cSMarc Bonnici ERROR("Logical SP (0x%x) Failed to Initialize\n",
23657affa25cSMarc Bonnici el3_lp_descs[i].sp_id);
23667affa25cSMarc Bonnici return rc;
23677affa25cSMarc Bonnici }
23687affa25cSMarc Bonnici VERBOSE("Logical SP (0x%x) Initialized\n",
23697affa25cSMarc Bonnici el3_lp_descs[i].sp_id);
23707affa25cSMarc Bonnici }
23717affa25cSMarc Bonnici
23727affa25cSMarc Bonnici INFO("Logical Secure Partition init completed.\n");
23737affa25cSMarc Bonnici
23747affa25cSMarc Bonnici return rc;
23757affa25cSMarc Bonnici }
23767affa25cSMarc Bonnici
spmc_sp_synchronous_entry(struct sp_exec_ctx * ec)23775096aeb2SMarc Bonnici uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec)
23785096aeb2SMarc Bonnici {
23795096aeb2SMarc Bonnici uint64_t rc;
23805096aeb2SMarc Bonnici
23815096aeb2SMarc Bonnici assert(ec != NULL);
23825096aeb2SMarc Bonnici
23835096aeb2SMarc Bonnici /* Assign the context of the SP to this CPU */
23845096aeb2SMarc Bonnici cm_set_context(&(ec->cpu_ctx), SECURE);
23855096aeb2SMarc Bonnici
23865096aeb2SMarc Bonnici /* Restore the context assigned above */
23875096aeb2SMarc Bonnici cm_el1_sysregs_context_restore(SECURE);
23885096aeb2SMarc Bonnici cm_set_next_eret_context(SECURE);
23895096aeb2SMarc Bonnici
23905096aeb2SMarc Bonnici /* Invalidate TLBs at EL1. */
23915096aeb2SMarc Bonnici tlbivmalle1();
23925096aeb2SMarc Bonnici dsbish();
23935096aeb2SMarc Bonnici
23945096aeb2SMarc Bonnici /* Enter Secure Partition */
23955096aeb2SMarc Bonnici rc = spm_secure_partition_enter(&ec->c_rt_ctx);
23965096aeb2SMarc Bonnici
23975096aeb2SMarc Bonnici /* Save secure state */
23985096aeb2SMarc Bonnici cm_el1_sysregs_context_save(SECURE);
23995096aeb2SMarc Bonnici
24005096aeb2SMarc Bonnici return rc;
24015096aeb2SMarc Bonnici }
24025096aeb2SMarc Bonnici
24035096aeb2SMarc Bonnici /*******************************************************************************
24045096aeb2SMarc Bonnici * SPMC Helper Functions.
24055096aeb2SMarc Bonnici ******************************************************************************/
sp_init(void)24065096aeb2SMarc Bonnici static int32_t sp_init(void)
24075096aeb2SMarc Bonnici {
24085096aeb2SMarc Bonnici uint64_t rc;
24095096aeb2SMarc Bonnici struct secure_partition_desc *sp;
24105096aeb2SMarc Bonnici struct sp_exec_ctx *ec;
24115096aeb2SMarc Bonnici
24125096aeb2SMarc Bonnici sp = spmc_get_current_sp_ctx();
24135096aeb2SMarc Bonnici ec = spmc_get_sp_ec(sp);
24145096aeb2SMarc Bonnici ec->rt_model = RT_MODEL_INIT;
24155096aeb2SMarc Bonnici ec->rt_state = RT_STATE_RUNNING;
24165096aeb2SMarc Bonnici
24175096aeb2SMarc Bonnici INFO("Secure Partition (0x%x) init start.\n", sp->sp_id);
24185096aeb2SMarc Bonnici
24195096aeb2SMarc Bonnici rc = spmc_sp_synchronous_entry(ec);
24205096aeb2SMarc Bonnici if (rc != 0) {
24215096aeb2SMarc Bonnici /* Indicate SP init was not successful. */
24225096aeb2SMarc Bonnici ERROR("SP (0x%x) failed to initialize (%lu).\n",
24235096aeb2SMarc Bonnici sp->sp_id, rc);
24245096aeb2SMarc Bonnici return 0;
24255096aeb2SMarc Bonnici }
24265096aeb2SMarc Bonnici
24275096aeb2SMarc Bonnici ec->rt_state = RT_STATE_WAITING;
24285096aeb2SMarc Bonnici INFO("Secure Partition initialized.\n");
24295096aeb2SMarc Bonnici
24305096aeb2SMarc Bonnici return 1;
24315096aeb2SMarc Bonnici }
24325096aeb2SMarc Bonnici
initalize_sp_descs(void)24335096aeb2SMarc Bonnici static void initalize_sp_descs(void)
24345096aeb2SMarc Bonnici {
24355096aeb2SMarc Bonnici struct secure_partition_desc *sp;
24365096aeb2SMarc Bonnici
24375096aeb2SMarc Bonnici for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) {
24385096aeb2SMarc Bonnici sp = &sp_desc[i];
24395096aeb2SMarc Bonnici sp->sp_id = INV_SP_ID;
2440e1df6008SMarc Bonnici sp->mailbox.rx_buffer = NULL;
2441e1df6008SMarc Bonnici sp->mailbox.tx_buffer = NULL;
2442e1df6008SMarc Bonnici sp->mailbox.state = MAILBOX_STATE_EMPTY;
24435096aeb2SMarc Bonnici sp->secondary_ep = 0;
24445096aeb2SMarc Bonnici }
24455096aeb2SMarc Bonnici }
24465096aeb2SMarc Bonnici
initalize_ns_ep_descs(void)24475096aeb2SMarc Bonnici static void initalize_ns_ep_descs(void)
24485096aeb2SMarc Bonnici {
24495096aeb2SMarc Bonnici struct ns_endpoint_desc *ns_ep;
24505096aeb2SMarc Bonnici
24515096aeb2SMarc Bonnici for (unsigned int i = 0U; i < NS_PARTITION_COUNT; i++) {
24525096aeb2SMarc Bonnici ns_ep = &ns_ep_desc[i];
24535096aeb2SMarc Bonnici /*
24545096aeb2SMarc Bonnici * Clashes with the Hypervisor ID but will not be a
24555096aeb2SMarc Bonnici * problem in practice.
24565096aeb2SMarc Bonnici */
24575096aeb2SMarc Bonnici ns_ep->ns_ep_id = 0;
24585096aeb2SMarc Bonnici ns_ep->ffa_version = 0;
2459e1df6008SMarc Bonnici ns_ep->mailbox.rx_buffer = NULL;
2460e1df6008SMarc Bonnici ns_ep->mailbox.tx_buffer = NULL;
2461e1df6008SMarc Bonnici ns_ep->mailbox.state = MAILBOX_STATE_EMPTY;
24625096aeb2SMarc Bonnici }
24635096aeb2SMarc Bonnici }
24645096aeb2SMarc Bonnici
24655096aeb2SMarc Bonnici /*******************************************************************************
24666da76075SMarc Bonnici * Initialize SPMC attributes for the SPMD.
24676da76075SMarc Bonnici ******************************************************************************/
spmc_populate_attrs(spmc_manifest_attribute_t * spmc_attrs)24686da76075SMarc Bonnici void spmc_populate_attrs(spmc_manifest_attribute_t *spmc_attrs)
24696da76075SMarc Bonnici {
2470dd87b735SJ-Alves spmc_attrs->major_version = FFA_VERSION_SPMC_MAJOR;
2471dd87b735SJ-Alves spmc_attrs->minor_version = FFA_VERSION_SPMC_MINOR;
24726da76075SMarc Bonnici spmc_attrs->exec_state = MODE_RW_64;
24736da76075SMarc Bonnici spmc_attrs->spmc_id = FFA_SPMC_ID;
24746da76075SMarc Bonnici }
24756da76075SMarc Bonnici
24766da76075SMarc Bonnici /*******************************************************************************
24775096aeb2SMarc Bonnici * Initialize contexts of all Secure Partitions.
24785096aeb2SMarc Bonnici ******************************************************************************/
spmc_setup(void)24795096aeb2SMarc Bonnici int32_t spmc_setup(void)
24805096aeb2SMarc Bonnici {
24815096aeb2SMarc Bonnici int32_t ret;
2482729d7793SAchin Gupta uint32_t flags;
24835096aeb2SMarc Bonnici
24845096aeb2SMarc Bonnici /* Initialize endpoint descriptors */
24855096aeb2SMarc Bonnici initalize_sp_descs();
24865096aeb2SMarc Bonnici initalize_ns_ep_descs();
24875096aeb2SMarc Bonnici
2488e0b1a6d5SMarc Bonnici /*
2489e0b1a6d5SMarc Bonnici * Retrieve the information of the datastore for tracking shared memory
2490e0b1a6d5SMarc Bonnici * requests allocated by platform code and zero the region if available.
2491e0b1a6d5SMarc Bonnici */
2492e0b1a6d5SMarc Bonnici ret = plat_spmc_shmem_datastore_get(&spmc_shmem_obj_state.data,
2493e0b1a6d5SMarc Bonnici &spmc_shmem_obj_state.data_size);
2494e0b1a6d5SMarc Bonnici if (ret != 0) {
2495e0b1a6d5SMarc Bonnici ERROR("Failed to obtain memory descriptor backing store!\n");
2496e0b1a6d5SMarc Bonnici return ret;
2497e0b1a6d5SMarc Bonnici }
2498e0b1a6d5SMarc Bonnici memset(spmc_shmem_obj_state.data, 0, spmc_shmem_obj_state.data_size);
2499e0b1a6d5SMarc Bonnici
25007affa25cSMarc Bonnici /* Setup logical SPs. */
25017affa25cSMarc Bonnici ret = logical_sp_init();
25027affa25cSMarc Bonnici if (ret != 0) {
25037affa25cSMarc Bonnici ERROR("Failed to initialize Logical Partitions.\n");
25047affa25cSMarc Bonnici return ret;
25057affa25cSMarc Bonnici }
25067affa25cSMarc Bonnici
25075096aeb2SMarc Bonnici /* Perform physical SP setup. */
25085096aeb2SMarc Bonnici
25095096aeb2SMarc Bonnici /* Disable MMU at EL1 (initialized by BL2) */
25105096aeb2SMarc Bonnici disable_mmu_icache_el1();
25115096aeb2SMarc Bonnici
25125096aeb2SMarc Bonnici /* Initialize context of the SP */
25135096aeb2SMarc Bonnici INFO("Secure Partition context setup start.\n");
25145096aeb2SMarc Bonnici
25155096aeb2SMarc Bonnici ret = find_and_prepare_sp_context();
25165096aeb2SMarc Bonnici if (ret != 0) {
25175096aeb2SMarc Bonnici ERROR("Error in SP finding and context preparation.\n");
25185096aeb2SMarc Bonnici return ret;
25195096aeb2SMarc Bonnici }
25205096aeb2SMarc Bonnici
252159bd2ad8SMarc Bonnici /* Register power management hooks with PSCI */
252259bd2ad8SMarc Bonnici psci_register_spd_pm_hook(&spmc_pm);
252359bd2ad8SMarc Bonnici
2524729d7793SAchin Gupta /*
2525729d7793SAchin Gupta * Register an interrupt handler for S-EL1 interrupts
2526729d7793SAchin Gupta * when generated during code executing in the
2527729d7793SAchin Gupta * non-secure state.
2528729d7793SAchin Gupta */
2529729d7793SAchin Gupta flags = 0;
2530729d7793SAchin Gupta set_interrupt_rm_flag(flags, NON_SECURE);
2531729d7793SAchin Gupta ret = register_interrupt_type_handler(INTR_TYPE_S_EL1,
2532729d7793SAchin Gupta spmc_sp_interrupt_handler,
2533729d7793SAchin Gupta flags);
2534729d7793SAchin Gupta if (ret != 0) {
2535729d7793SAchin Gupta ERROR("Failed to register interrupt handler! (%d)\n", ret);
2536729d7793SAchin Gupta panic();
2537729d7793SAchin Gupta }
2538729d7793SAchin Gupta
25395096aeb2SMarc Bonnici /* Register init function for deferred init. */
25405096aeb2SMarc Bonnici bl31_register_bl32_init(&sp_init);
25415096aeb2SMarc Bonnici
25425096aeb2SMarc Bonnici INFO("Secure Partition setup done.\n");
25435096aeb2SMarc Bonnici
25445096aeb2SMarc Bonnici return 0;
25455096aeb2SMarc Bonnici }
25465096aeb2SMarc Bonnici
25475096aeb2SMarc Bonnici /*******************************************************************************
25485096aeb2SMarc Bonnici * Secure Partition Manager SMC handler.
25495096aeb2SMarc Bonnici ******************************************************************************/
spmc_smc_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)25505096aeb2SMarc Bonnici uint64_t spmc_smc_handler(uint32_t smc_fid,
25515096aeb2SMarc Bonnici bool secure_origin,
25525096aeb2SMarc Bonnici uint64_t x1,
25535096aeb2SMarc Bonnici uint64_t x2,
25545096aeb2SMarc Bonnici uint64_t x3,
25555096aeb2SMarc Bonnici uint64_t x4,
25565096aeb2SMarc Bonnici void *cookie,
25575096aeb2SMarc Bonnici void *handle,
25585096aeb2SMarc Bonnici uint64_t flags)
25595096aeb2SMarc Bonnici {
25605096aeb2SMarc Bonnici switch (smc_fid) {
25615096aeb2SMarc Bonnici
25620c7707fdSMarc Bonnici case FFA_VERSION:
25630c7707fdSMarc Bonnici return ffa_version_handler(smc_fid, secure_origin, x1, x2, x3,
25640c7707fdSMarc Bonnici x4, cookie, handle, flags);
25650c7707fdSMarc Bonnici
256646872e01SMarc Bonnici case FFA_SPM_ID_GET:
256746872e01SMarc Bonnici return ffa_spm_id_get_handler(smc_fid, secure_origin, x1, x2,
256846872e01SMarc Bonnici x3, x4, cookie, handle, flags);
256946872e01SMarc Bonnici
2570d5fe9235SMarc Bonnici case FFA_ID_GET:
2571d5fe9235SMarc Bonnici return ffa_id_get_handler(smc_fid, secure_origin, x1, x2, x3,
2572d5fe9235SMarc Bonnici x4, cookie, handle, flags);
2573d5fe9235SMarc Bonnici
257455a29638SMarc Bonnici case FFA_FEATURES:
257555a29638SMarc Bonnici return ffa_features_handler(smc_fid, secure_origin, x1, x2, x3,
257655a29638SMarc Bonnici x4, cookie, handle, flags);
257755a29638SMarc Bonnici
257859bd2ad8SMarc Bonnici case FFA_SECONDARY_EP_REGISTER_SMC64:
257959bd2ad8SMarc Bonnici return ffa_sec_ep_register_handler(smc_fid, secure_origin, x1,
258059bd2ad8SMarc Bonnici x2, x3, x4, cookie, handle,
258159bd2ad8SMarc Bonnici flags);
258259bd2ad8SMarc Bonnici
25839741327dSMarc Bonnici case FFA_MSG_SEND_DIRECT_REQ_SMC32:
25849741327dSMarc Bonnici case FFA_MSG_SEND_DIRECT_REQ_SMC64:
258509a580b7SLevi Yun case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
25869741327dSMarc Bonnici return direct_req_smc_handler(smc_fid, secure_origin, x1, x2,
25879741327dSMarc Bonnici x3, x4, cookie, handle, flags);
25889741327dSMarc Bonnici
25899741327dSMarc Bonnici case FFA_MSG_SEND_DIRECT_RESP_SMC32:
25909741327dSMarc Bonnici case FFA_MSG_SEND_DIRECT_RESP_SMC64:
259109a580b7SLevi Yun case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
25929741327dSMarc Bonnici return direct_resp_smc_handler(smc_fid, secure_origin, x1, x2,
25939741327dSMarc Bonnici x3, x4, cookie, handle, flags);
25949741327dSMarc Bonnici
25951a752245SMarc Bonnici case FFA_RXTX_MAP_SMC32:
25961a752245SMarc Bonnici case FFA_RXTX_MAP_SMC64:
25971a752245SMarc Bonnici return rxtx_map_handler(smc_fid, secure_origin, x1, x2, x3, x4,
25981a752245SMarc Bonnici cookie, handle, flags);
25991a752245SMarc Bonnici
26001a752245SMarc Bonnici case FFA_RXTX_UNMAP:
26011a752245SMarc Bonnici return rxtx_unmap_handler(smc_fid, secure_origin, x1, x2, x3,
26021a752245SMarc Bonnici x4, cookie, handle, flags);
26031a752245SMarc Bonnici
2604f74e2772SMarc Bonnici case FFA_PARTITION_INFO_GET:
2605f74e2772SMarc Bonnici return partition_info_get_handler(smc_fid, secure_origin, x1,
2606f74e2772SMarc Bonnici x2, x3, x4, cookie, handle,
2607f74e2772SMarc Bonnici flags);
2608f74e2772SMarc Bonnici
2609f0c25a08SMarc Bonnici case FFA_RX_RELEASE:
2610f0c25a08SMarc Bonnici return rx_release_handler(smc_fid, secure_origin, x1, x2, x3,
2611f0c25a08SMarc Bonnici x4, cookie, handle, flags);
2612f0c25a08SMarc Bonnici
2613c4db76f0SMarc Bonnici case FFA_MSG_WAIT:
2614c4db76f0SMarc Bonnici return msg_wait_handler(smc_fid, secure_origin, x1, x2, x3, x4,
2615c4db76f0SMarc Bonnici cookie, handle, flags);
2616c4db76f0SMarc Bonnici
2617d663fe7aSMarc Bonnici case FFA_ERROR:
2618d663fe7aSMarc Bonnici return ffa_error_handler(smc_fid, secure_origin, x1, x2, x3, x4,
2619d663fe7aSMarc Bonnici cookie, handle, flags);
2620d663fe7aSMarc Bonnici
2621aad20c85SMarc Bonnici case FFA_MSG_RUN:
2622aad20c85SMarc Bonnici return ffa_run_handler(smc_fid, secure_origin, x1, x2, x3, x4,
2623aad20c85SMarc Bonnici cookie, handle, flags);
2624e0b1a6d5SMarc Bonnici
2625e0b1a6d5SMarc Bonnici case FFA_MEM_SHARE_SMC32:
2626e0b1a6d5SMarc Bonnici case FFA_MEM_SHARE_SMC64:
2627e0b1a6d5SMarc Bonnici case FFA_MEM_LEND_SMC32:
2628e0b1a6d5SMarc Bonnici case FFA_MEM_LEND_SMC64:
2629e0b1a6d5SMarc Bonnici return spmc_ffa_mem_send(smc_fid, secure_origin, x1, x2, x3, x4,
2630e0b1a6d5SMarc Bonnici cookie, handle, flags);
2631e0b1a6d5SMarc Bonnici
2632e0b1a6d5SMarc Bonnici case FFA_MEM_FRAG_TX:
2633e0b1a6d5SMarc Bonnici return spmc_ffa_mem_frag_tx(smc_fid, secure_origin, x1, x2, x3,
2634e0b1a6d5SMarc Bonnici x4, cookie, handle, flags);
2635e0b1a6d5SMarc Bonnici
2636e0b1a6d5SMarc Bonnici case FFA_MEM_FRAG_RX:
2637e0b1a6d5SMarc Bonnici return spmc_ffa_mem_frag_rx(smc_fid, secure_origin, x1, x2, x3,
2638e0b1a6d5SMarc Bonnici x4, cookie, handle, flags);
2639e0b1a6d5SMarc Bonnici
2640e0b1a6d5SMarc Bonnici case FFA_MEM_RETRIEVE_REQ_SMC32:
2641e0b1a6d5SMarc Bonnici case FFA_MEM_RETRIEVE_REQ_SMC64:
2642e0b1a6d5SMarc Bonnici return spmc_ffa_mem_retrieve_req(smc_fid, secure_origin, x1, x2,
2643e0b1a6d5SMarc Bonnici x3, x4, cookie, handle, flags);
2644e0b1a6d5SMarc Bonnici
2645e0b1a6d5SMarc Bonnici case FFA_MEM_RELINQUISH:
2646e0b1a6d5SMarc Bonnici return spmc_ffa_mem_relinquish(smc_fid, secure_origin, x1, x2,
2647e0b1a6d5SMarc Bonnici x3, x4, cookie, handle, flags);
2648e0b1a6d5SMarc Bonnici
2649e0b1a6d5SMarc Bonnici case FFA_MEM_RECLAIM:
2650e0b1a6d5SMarc Bonnici return spmc_ffa_mem_reclaim(smc_fid, secure_origin, x1, x2, x3,
2651e0b1a6d5SMarc Bonnici x4, cookie, handle, flags);
2652638a6f8eSShruti Gupta case FFA_CONSOLE_LOG_SMC32:
2653638a6f8eSShruti Gupta case FFA_CONSOLE_LOG_SMC64:
2654638a6f8eSShruti Gupta return spmc_ffa_console_log(smc_fid, secure_origin, x1, x2, x3,
2655638a6f8eSShruti Gupta x4, cookie, handle, flags);
2656e0b1a6d5SMarc Bonnici
2657ddf72e6aSLevi Yun case FFA_MEM_PERM_GET_SMC32:
2658ddf72e6aSLevi Yun case FFA_MEM_PERM_GET_SMC64:
26591f6b2b26SNishant Sharma return ffa_mem_perm_get_handler(smc_fid, secure_origin, x1, x2,
26601f6b2b26SNishant Sharma x3, x4, cookie, handle, flags);
26611f6b2b26SNishant Sharma
2662ddf72e6aSLevi Yun case FFA_MEM_PERM_SET_SMC32:
2663ddf72e6aSLevi Yun case FFA_MEM_PERM_SET_SMC64:
26641f6b2b26SNishant Sharma return ffa_mem_perm_set_handler(smc_fid, secure_origin, x1, x2,
26651f6b2b26SNishant Sharma x3, x4, cookie, handle, flags);
26661f6b2b26SNishant Sharma
26675096aeb2SMarc Bonnici default:
26685096aeb2SMarc Bonnici WARN("Unsupported FF-A call 0x%08x.\n", smc_fid);
26695096aeb2SMarc Bonnici break;
26705096aeb2SMarc Bonnici }
26715096aeb2SMarc Bonnici return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
26725096aeb2SMarc Bonnici }
2673729d7793SAchin Gupta
2674729d7793SAchin Gupta /*******************************************************************************
2675729d7793SAchin Gupta * This function is the handler registered for S-EL1 interrupts by the SPMC. It
2676729d7793SAchin Gupta * validates the interrupt and upon success arranges entry into the SP for
2677729d7793SAchin Gupta * handling the interrupt.
2678729d7793SAchin Gupta ******************************************************************************/
spmc_sp_interrupt_handler(uint32_t id,uint32_t flags,void * handle,void * cookie)2679729d7793SAchin Gupta static uint64_t spmc_sp_interrupt_handler(uint32_t id,
2680729d7793SAchin Gupta uint32_t flags,
2681729d7793SAchin Gupta void *handle,
2682729d7793SAchin Gupta void *cookie)
2683729d7793SAchin Gupta {
2684729d7793SAchin Gupta struct secure_partition_desc *sp = spmc_get_current_sp_ctx();
2685729d7793SAchin Gupta struct sp_exec_ctx *ec;
2686729d7793SAchin Gupta uint32_t linear_id = plat_my_core_pos();
2687729d7793SAchin Gupta
2688729d7793SAchin Gupta /* Sanity check for a NULL pointer dereference. */
2689729d7793SAchin Gupta assert(sp != NULL);
2690729d7793SAchin Gupta
2691729d7793SAchin Gupta /* Check the security state when the exception was generated. */
2692729d7793SAchin Gupta assert(get_interrupt_src_ss(flags) == NON_SECURE);
2693729d7793SAchin Gupta
2694729d7793SAchin Gupta /* Panic if not an S-EL1 Partition. */
2695729d7793SAchin Gupta if (sp->runtime_el != S_EL1) {
2696729d7793SAchin Gupta ERROR("Interrupt received for a non S-EL1 SP on core%u.\n",
2697729d7793SAchin Gupta linear_id);
2698729d7793SAchin Gupta panic();
2699729d7793SAchin Gupta }
2700729d7793SAchin Gupta
2701729d7793SAchin Gupta /* Obtain a reference to the SP execution context. */
2702729d7793SAchin Gupta ec = spmc_get_sp_ec(sp);
2703729d7793SAchin Gupta
2704729d7793SAchin Gupta /* Ensure that the execution context is in waiting state else panic. */
2705729d7793SAchin Gupta if (ec->rt_state != RT_STATE_WAITING) {
2706729d7793SAchin Gupta ERROR("SP EC on core%u is not waiting (%u), it is (%u).\n",
2707729d7793SAchin Gupta linear_id, RT_STATE_WAITING, ec->rt_state);
2708729d7793SAchin Gupta panic();
2709729d7793SAchin Gupta }
2710729d7793SAchin Gupta
2711729d7793SAchin Gupta /* Update the runtime model and state of the partition. */
2712729d7793SAchin Gupta ec->rt_model = RT_MODEL_INTR;
2713729d7793SAchin Gupta ec->rt_state = RT_STATE_RUNNING;
2714729d7793SAchin Gupta
2715729d7793SAchin Gupta VERBOSE("SP (0x%x) interrupt start on core%u.\n", sp->sp_id, linear_id);
2716729d7793SAchin Gupta
2717729d7793SAchin Gupta /*
2718729d7793SAchin Gupta * Forward the interrupt to the S-EL1 SP. The interrupt ID is not
2719729d7793SAchin Gupta * populated as the SP can determine this by itself.
2720c925867eSOlivier Deprez * The flags field is forced to 0 mainly to pass the SVE hint bit
2721c925867eSOlivier Deprez * cleared for consumption by the lower EL.
2722729d7793SAchin Gupta */
2723729d7793SAchin Gupta return spmd_smc_switch_state(FFA_INTERRUPT, false,
2724729d7793SAchin Gupta FFA_PARAM_MBZ, FFA_PARAM_MBZ,
2725729d7793SAchin Gupta FFA_PARAM_MBZ, FFA_PARAM_MBZ,
2726bb9fc8c0SJay Monkman handle, 0ULL, sp->ffa_version);
2727729d7793SAchin Gupta }
2728