From 73947a639a54560f064bd2d6e3631f0a4ed9bd08 Mon Sep 17 00:00:00 2001 From: Arteom Katkov Date: Wed, 20 May 2026 10:07:05 -0500 Subject: [PATCH] core: ffa: add direct request v2 support Add support for FF-A direct request/response v2 messages for secure partitions. Direct request v2 carries the target service UUID in x2/x3 and uses x4-x17 for the payload, so preserve the full AArch64 FF-A register set when entering and returning from secure partitions. Advertise DirectReq2/Resp2 to normal-world and secure partition callers, and expose the corresponding partition properties for AArch64 secure partitions that support direct messaging. Validate DirectReq2 messages by checking sender and receiver capabilities and matching non-nil UUIDs against the destination partition UUID. Logical secure partitions do not support DirectReq2 yet, so reject Req2 messages targeting LSPs. Signed-off-by: Arteom Katkov Signed-off-by: Sahil Kaushal Reviewed-by: Jens Wiklander --- core/arch/arm/include/ffa.h | 2 + .../arm/include/kernel/secure_partition.h | 2 + .../arm/include/kernel/thread_private_arch.h | 2 +- core/arch/arm/kernel/secure_partition.c | 46 +++++---- core/arch/arm/kernel/spmc_sp_handler.c | 95 +++++++++++++++++-- core/arch/arm/kernel/thread.c | 69 +++++++++++--- core/arch/arm/kernel/thread_spmc.c | 49 +++++++++- 7 files changed, 220 insertions(+), 45 deletions(-) diff --git a/core/arch/arm/include/ffa.h b/core/arch/arm/include/ffa.h index 6f03cd00b49..a7519348c12 100644 --- a/core/arch/arm/include/ffa.h +++ b/core/arch/arm/include/ffa.h @@ -224,6 +224,8 @@ static inline uint16_t ffa_target_info_get_vcpu_id(uint32_t target_info) #define FFA_PART_PROP_NOTIF_CREATED BIT(6) #define FFA_PART_PROP_NOTIF_DESTROYED BIT(7) #define FFA_PART_PROP_AARCH64_STATE BIT(8) +#define FFA_PART_PROP_DIRECT_REQ2_RECV BIT(9) +#define FFA_PART_PROP_DIRECT_REQ2_SEND BIT(10) #define FFA_MEMORY_HANDLE_HYPERVISOR_BIT BIT64(63) #define FFA_MEMORY_HANDLE_SECURE_BIT BIT64(45) diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h index 9b79989fc91..83c483c8df3 100644 --- a/core/arch/arm/include/kernel/secure_partition.h +++ b/core/arch/arm/include/kernel/secure_partition.h @@ -26,6 +26,7 @@ struct sp_session { uint16_t endpoint_id; uint16_t thread_id; uint16_t caller_id; + uint32_t caller_fid; uint32_t boot_order; struct ts_session ts_sess; unsigned int spinlock; @@ -77,6 +78,7 @@ TEE_Result sp_enter(struct thread_smc_1_2_regs *args, struct sp_session *sp); TEE_Result sp_partition_info_get(uint32_t ffa_vers, void *buf, size_t buf_size, const uint32_t uuid_words[4], size_t *elem_count, bool count_only); +bool sp_has_ffa_uuid(struct sp_session *sp, const uint32_t uuid_words[4]); bool sp_has_exclusive_access(struct sp_mem_map_region *mem, struct user_mode_ctx *uctx); TEE_Result sp_map_shared(struct sp_session *s, diff --git a/core/arch/arm/include/kernel/thread_private_arch.h b/core/arch/arm/include/kernel/thread_private_arch.h index eb50b9a1d97..585a38df903 100644 --- a/core/arch/arm/include/kernel/thread_private_arch.h +++ b/core/arch/arm/include/kernel/thread_private_arch.h @@ -130,7 +130,7 @@ void thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5); -void thread_sp_alloc_and_run(struct thread_smc_args *args); +void thread_sp_alloc_and_run(struct thread_smc_1_2_regs *args); /* * Resumes execution of currently active thread by restoring context and diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c index 4a31a365e76..325d3e169ba 100644 --- a/core/arch/arm/kernel/secure_partition.c +++ b/core/arch/arm/kernel/secure_partition.c @@ -63,6 +63,8 @@ #define SP_MANIFEST_DIRECT_REQ_RECEIVE BIT(0) #define SP_MANIFEST_DIRECT_REQ_SEND BIT(1) #define SP_MANIFEST_INDIRECT_REQ BIT(2) +#define SP_MANIFEST_DIRECT_REQ2_RECEIVE BIT(9) +#define SP_MANIFEST_DIRECT_REQ2_SEND BIT(10) #define SP_MANIFEST_VM_CREATED_MSG BIT(0) #define SP_MANIFEST_VM_DESTROYED_MSG BIT(1) @@ -459,6 +461,18 @@ static TEE_Result sp_dt_get_uuid(const void *fdt, int node, return TEE_SUCCESS; } +bool sp_has_ffa_uuid(struct sp_session *sp, const uint32_t uuid_words[4]) +{ + TEE_UUID uuid = { }; + + if (!sp || !uuid_words) + return false; + + tee_uuid_from_octets(&uuid, (const uint8_t *)uuid_words); + + return !memcmp(&sp->ffa_uuid, &uuid, sizeof(uuid)); +} + static TEE_Result sp_is_elf_format(const void *fdt, int sp_node, bool *is_elf_format) { @@ -1488,7 +1502,7 @@ static TEE_Result read_ffa_version(const void *fdt, struct sp_session *s) return res; } - if (ffa_version != FFA_VERSION_1_0 && ffa_version != FFA_VERSION_1_1) { + if (ffa_version < FFA_VERSION_1_0 || ffa_version > FFA_VERSION_1_2) { EMSG("Invalid FF-A version value: 0x%08"PRIx32, ffa_version); return TEE_ERROR_BAD_PARAMETERS; } @@ -1537,6 +1551,14 @@ static TEE_Result read_sp_msg_types(const void *fdt, struct sp_session *s) if (msg_method & SP_MANIFEST_DIRECT_REQ_SEND) s->props |= FFA_PART_PROP_DIRECT_REQ_SEND; + if (s->rxtx.ffa_vers >= FFA_VERSION_1_2 && + (s->props & FFA_PART_PROP_AARCH64_STATE)) { + if (msg_method & SP_MANIFEST_DIRECT_REQ2_RECEIVE) + s->props |= FFA_PART_PROP_DIRECT_REQ2_RECV; + if (msg_method & SP_MANIFEST_DIRECT_REQ2_SEND) + s->props |= FFA_PART_PROP_DIRECT_REQ2_SEND; + } + if (msg_method & SP_MANIFEST_INDIRECT_REQ) IMSG("Indirect messaging is not supported"); @@ -1729,14 +1751,7 @@ TEE_Result sp_enter(struct thread_smc_1_2_regs *args, struct sp_session *sp) TEE_Result res = TEE_SUCCESS; struct sp_ctx *ctx = to_sp_ctx(sp->ts_sess.ctx); - ctx->sp_regs.x[0] = args->a0; - ctx->sp_regs.x[1] = args->a1; - ctx->sp_regs.x[2] = args->a2; - ctx->sp_regs.x[3] = args->a3; - ctx->sp_regs.x[4] = args->a4; - ctx->sp_regs.x[5] = args->a5; - ctx->sp_regs.x[6] = args->a6; - ctx->sp_regs.x[7] = args->a7; + memcpy(ctx->sp_regs.x, args->a, sizeof(args->a)); #ifdef CFG_TA_PAUTH ctx->sp_regs.apiakey_hi = ctx->uctx.keys.apia_hi; ctx->sp_regs.apiakey_lo = ctx->uctx.keys.apia_lo; @@ -1744,14 +1759,7 @@ TEE_Result sp_enter(struct thread_smc_1_2_regs *args, struct sp_session *sp) res = sp->ts_sess.ctx->ops->enter_invoke_cmd(&sp->ts_sess, 0); - args->a0 = ctx->sp_regs.x[0]; - args->a1 = ctx->sp_regs.x[1]; - args->a2 = ctx->sp_regs.x[2]; - args->a3 = ctx->sp_regs.x[3]; - args->a4 = ctx->sp_regs.x[4]; - args->a5 = ctx->sp_regs.x[5]; - args->a6 = ctx->sp_regs.x[6]; - args->a7 = ctx->sp_regs.x[7]; + memcpy(args->a, ctx->sp_regs.x, sizeof(args->a)); return res; } @@ -1877,8 +1885,8 @@ static bool sp_handle_scall(struct thread_scall_regs *regs) * handler. * We always return to S-El1 after handling the SVC. We will continue * in sp_enter_invoke_cmd() (return from __thread_enter_user_mode). - * The sp_enter() function copies the FF-A parameters (a0-a7) from the - * saved registers to the thread_smc_args. The thread_smc_args object is + * The sp_enter() function copies the FF-A parameters from the + * saved registers to the thread_smc_1_2_regs object. This object is * afterward used by the spmc_sp_msg_handler() to handle the * FF-A message send by the SP. */ diff --git a/core/arch/arm/kernel/spmc_sp_handler.c b/core/arch/arm/kernel/spmc_sp_handler.c index 48940bae280..77cc0b59d74 100644 --- a/core/arch/arm/kernel/spmc_sp_handler.c +++ b/core/arch/arm/kernel/spmc_sp_handler.c @@ -16,13 +16,14 @@ #include #include #include +#include /* Protects the ref_count field in struct sp_mem_receiver */ static unsigned int mem_ref_lock = SPINLOCK_UNLOCK; int spmc_sp_start_thread(struct thread_smc_1_2_regs *args) { - thread_sp_alloc_and_run(&args->arg11); + thread_sp_alloc_and_run(args); /* * thread_sp_alloc_and_run() only returns if all threads are busy. * The caller must try again. @@ -41,6 +42,21 @@ static void ffa_success(struct thread_smc_1_2_regs *args) spmc_set_args(args, FFA_SUCCESS_32, 0, 0, 0, 0, 0); } +static bool is_nil_uuid_words(const uint32_t uuid_words[4]) +{ + return !uuid_words || (!uuid_words[0] && !uuid_words[1] && + !uuid_words[2] && !uuid_words[3]); +} + +static void direct_req2_uuid_from_args(struct thread_smc_1_2_regs *args, + uint32_t uuid_words[4]) +{ + uuid_words[0] = low32_from_64(args->a2); + uuid_words[1] = high32_from_64(args->a2); + uuid_words[2] = low32_from_64(args->a3); + uuid_words[3] = high32_from_64(args->a3); +} + static TEE_Result ffa_get_dst(struct thread_smc_1_2_regs *args, struct sp_session *caller, struct sp_session **dst) @@ -899,6 +915,16 @@ ffa_handle_sp_direct_req(struct thread_smc_1_2_regs *args, struct sp_session *dst = NULL; struct spmc_lsp_desc *lsp = NULL; TEE_Result res = FFA_OK; + uint32_t caller_props = 0; + uint32_t dst_props = 0; + + if (args->a0 == FFA_MSG_SEND_DIRECT_REQ2) { + caller_props = FFA_PART_PROP_DIRECT_REQ2_SEND; + dst_props = FFA_PART_PROP_DIRECT_REQ2_RECV; + } else { + caller_props = FFA_PART_PROP_DIRECT_REQ_SEND; + dst_props = FFA_PART_PROP_DIRECT_REQ_RECV; + } res = ffa_get_dst(args, caller_sp, &dst); if (res) { @@ -921,22 +947,21 @@ ffa_handle_sp_direct_req(struct thread_smc_1_2_regs *args, return caller_sp; } - if (caller_sp && - !(caller_sp->props & FFA_PART_PROP_DIRECT_REQ_SEND)) { + if (caller_sp && !(caller_sp->props & caller_props)) { EMSG("SP 0x%"PRIx16" doesn't support sending direct requests", caller_sp->endpoint_id); ffa_set_error(args, FFA_NOT_SUPPORTED); return caller_sp; } - if (dst && !(dst->props & FFA_PART_PROP_DIRECT_REQ_RECV)) { + if (dst && !(dst->props & dst_props)) { EMSG("SP 0x%"PRIx16" doesn't support receipt of direct requests", dst->endpoint_id); ffa_set_error(args, FFA_NOT_SUPPORTED); return caller_sp; } - if (lsp && !(lsp->properties & FFA_PART_PROP_DIRECT_REQ_RECV)) { + if (lsp && !(lsp->properties & dst_props)) { EMSG("LSP 0x%"PRIx16" doesn't support receipt of direct requests", lsp->sp_id); ffa_set_error(args, FFA_NOT_SUPPORTED); @@ -948,7 +973,16 @@ ffa_handle_sp_direct_req(struct thread_smc_1_2_regs *args, return caller_sp; } - if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { + if (args->a0 == FFA_MSG_SEND_DIRECT_REQ2) { + uint32_t uuid_words[4] = { }; + + direct_req2_uuid_from_args(args, uuid_words); + if (!is_nil_uuid_words(uuid_words) && + !sp_has_ffa_uuid(dst, uuid_words)) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + } else if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { switch (args->a2 & FFA_MSG_TYPE_MASK) { case FFA_MSG_SEND_VM_CREATED: /* The sender must be the NWd hypervisor (ID 0) */ @@ -997,10 +1031,12 @@ ffa_handle_sp_direct_req(struct thread_smc_1_2_regs *args, cpu_spin_unlock(&dst->spinlock); /* - * Store the calling endpoint id. This will make it possible to check - * if the response is sent back to the correct endpoint. + * Store the calling endpoint ID and request function ID. This makes it + * possible to check that the response is sent back to the correct + * endpoint and uses the matching direct response ABI. */ dst->caller_id = FFA_SRC(args->a1); + dst->caller_fid = args->a0; /* Forward the message to the destination SP */ res = sp_enter(args, dst); @@ -1014,6 +1050,20 @@ ffa_handle_sp_direct_req(struct thread_smc_1_2_regs *args, return dst; } +static bool direct_resp_matches_req(uint32_t req_fid, uint32_t resp_fid) +{ + switch (resp_fid) { + case FFA_MSG_SEND_DIRECT_RESP_32: + return req_fid == FFA_MSG_SEND_DIRECT_REQ_32; + case FFA_MSG_SEND_DIRECT_RESP_64: + return req_fid == FFA_MSG_SEND_DIRECT_REQ_64; + case FFA_MSG_SEND_DIRECT_RESP2: + return req_fid == FFA_MSG_SEND_DIRECT_REQ2; + default: + return false; + } +} + static struct sp_session * ffa_handle_sp_direct_resp(struct thread_smc_1_2_regs *args, struct sp_session *caller_sp) @@ -1035,7 +1085,20 @@ ffa_handle_sp_direct_resp(struct thread_smc_1_2_regs *args, return caller_sp; } - if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { + if (args->a0 == FFA_MSG_SEND_DIRECT_RESP2) { + if (args->a2 || args->a3) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + if (!(caller_sp->props & FFA_PART_PROP_DIRECT_REQ2_RECV)) { + ffa_set_error(args, FFA_DENIED); + return caller_sp; + } + if (dst && !(dst->props & FFA_PART_PROP_DIRECT_REQ2_SEND)) { + ffa_set_error(args, FFA_DENIED); + return caller_sp; + } + } else if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { switch (args->a2 & FFA_MSG_TYPE_MASK) { case FFA_MSG_RESP_VM_CREATED: /* The destination must be the NWd hypervisor (ID 0) */ @@ -1090,7 +1153,14 @@ ffa_handle_sp_direct_resp(struct thread_smc_1_2_regs *args, return caller_sp; } + if (!direct_resp_matches_req(caller_sp->caller_fid, args->a0)) { + EMSG("Direct response type doesn't match direct request"); + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + caller_sp->caller_id = 0; + caller_sp->caller_fid = 0; cpu_spin_lock(&caller_sp->spinlock); caller_sp->state = sp_idle; @@ -1146,6 +1216,11 @@ static void handle_features(struct thread_smc_1_2_regs *args) ret_fid = FFA_SUCCESS_32; ret_w2 = 0; /* 4kB Minimum buffer size and alignment boundary */ break; + case FFA_MSG_SEND_DIRECT_REQ2: + case FFA_MSG_SEND_DIRECT_RESP2: + ret_fid = FFA_SUCCESS_32; + ret_w2 = FFA_PARAM_MBZ; + break; case FFA_ERROR: case FFA_VERSION: case FFA_SUCCESS_32: @@ -1341,12 +1416,14 @@ void spmc_sp_msg_handler(struct thread_smc_1_2_regs *args, case FFA_MSG_SEND_DIRECT_REQ_64: #endif case FFA_MSG_SEND_DIRECT_REQ_32: + case FFA_MSG_SEND_DIRECT_REQ2: caller_sp = ffa_handle_sp_direct_req(args, caller_sp); break; #ifdef ARM64 case FFA_MSG_SEND_DIRECT_RESP_64: #endif case FFA_MSG_SEND_DIRECT_RESP_32: + case FFA_MSG_SEND_DIRECT_RESP2: caller_sp = ffa_handle_sp_direct_resp(args, caller_sp); break; case FFA_ERROR: diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c index e3751115003..1d8920a52e8 100644 --- a/core/arch/arm/kernel/thread.c +++ b/core/arch/arm/kernel/thread.c @@ -217,10 +217,7 @@ static void init_regs(struct thread_ctx *thread, uint32_t a0, uint32_t a1, } #endif /*ARM64*/ -static void __thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, - uint32_t a3, uint32_t a4, uint32_t a5, - uint32_t a6, uint32_t a7, - void *pc, uint32_t flags) +static struct thread_ctx *alloc_thread(uint32_t flags) { struct thread_core_local *l = thread_get_core_local(); bool found_thread = false; @@ -241,25 +238,39 @@ static void __thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, thread_unlock_global(); if (!found_thread) - return; + return NULL; l->curr_thread = n; - threads[n].flags = flags; - init_regs(threads + n, a0, a1, a2, a3, a4, a5, a6, a7, pc); + + return threads + n; +} + +static void __thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6, uint32_t a7, + void *pc, uint32_t flags) +{ + struct thread_core_local *l = thread_get_core_local(); + struct thread_ctx *thread = alloc_thread(flags); + + if (!thread) + return; + + init_regs(thread, a0, a1, a2, a3, a4, a5, a6, a7, pc); #ifdef CFG_CORE_PAUTH /* * Copy the APIA key into the registers to be restored with * thread_resume(). */ - threads[n].regs.apiakey_hi = threads[n].keys.apia_hi; - threads[n].regs.apiakey_lo = threads[n].keys.apia_lo; + thread->regs.apiakey_hi = thread->keys.apia_hi; + thread->regs.apiakey_lo = thread->keys.apia_lo; #endif thread_lazy_save_ns_vfp(); l->flags &= ~THREAD_CLF_TMP; - thread_resume(&threads[n].regs); + thread_resume(&thread->regs); /*NOTREACHED*/ panic(); } @@ -272,11 +283,41 @@ void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, } #ifdef CFG_SECURE_PARTITION -void thread_sp_alloc_and_run(struct thread_smc_args *args __maybe_unused) +static void init_regs_spmc(struct thread_ctx *thread, + const struct thread_smc_1_2_regs *args, void *pc) { - __thread_alloc_and_run(args->a0, args->a1, args->a2, args->a3, args->a4, - args->a5, args->a6, args->a7, - spmc_sp_thread_entry, THREAD_FLAGS_FFA_ONLY); + size_t n = 0; + + thread->regs.pc = (vaddr_t)pc; + thread->regs.cpsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, + THREAD_EXCP_FOREIGN_INTR | DAIFBIT_ABT); + thread->regs.sp = thread->stack_va_end; + + for (n = 0; n < ARRAY_SIZE(args->a); n++) + thread->regs.x[n] = args->a[n]; + for (; n < ARRAY_SIZE(thread->regs.x); n++) + thread->regs.x[n] = 0; +} + +void thread_sp_alloc_and_run(struct thread_smc_1_2_regs *args) +{ + struct thread_core_local *l = thread_get_core_local(); + struct thread_ctx *thread = alloc_thread(THREAD_FLAGS_FFA_ONLY); + + if (!thread) + return; + + init_regs_spmc(thread, args, spmc_sp_thread_entry); +#ifdef CFG_CORE_PAUTH + thread->regs.apiakey_hi = thread->keys.apia_hi; + thread->regs.apiakey_lo = thread->keys.apia_lo; +#endif + + thread_lazy_save_ns_vfp(); + + l->flags &= ~THREAD_CLF_TMP; + thread_resume(&thread->regs); + panic(); } #endif diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c index 21639756125..7ce5c0da64d 100644 --- a/core/arch/arm/kernel/thread_spmc.c +++ b/core/arch/arm/kernel/thread_spmc.c @@ -274,6 +274,15 @@ static void handle_features(struct thread_smc_1_2_regs *args) ret_fid = FFA_SUCCESS_32; ret_w2 = 0; /* 4kB Minimum buffer size and alignment boundary */ break; +#ifdef ARM64 + case FFA_MSG_SEND_DIRECT_REQ2: + case FFA_MSG_SEND_DIRECT_RESP2: + if (my_rxtx.ffa_vers >= FFA_VERSION_1_2) { + ret_fid = FFA_SUCCESS_32; + ret_w2 = FFA_PARAM_MBZ; + } + break; +#endif #ifdef ARM64 case FFA_MEM_SHARE_64: #endif @@ -548,12 +557,26 @@ TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen, fpi->partition_properties = part_props; - /* In FF-A 1.0 only bits [2:0] are defined, let's mask others */ + /* Mask out bits introduced with FF-A version 1.1 */ if (ffa_vers < FFA_VERSION_1_1) fpi->partition_properties &= FFA_PART_PROP_DIRECT_REQ_RECV | FFA_PART_PROP_DIRECT_REQ_SEND | FFA_PART_PROP_INDIRECT_MSGS; + /* Mask out bits introduced with FF-A version 1.2 */ + if (ffa_vers < FFA_VERSION_1_2) + fpi->partition_properties &= FFA_PART_PROP_DIRECT_REQ_RECV | + FFA_PART_PROP_DIRECT_REQ_SEND | + FFA_PART_PROP_INDIRECT_MSGS | + FFA_PART_PROP_RECV_NOTIF | + FFA_PART_PROP_IS_PE_ID | + FFA_PART_PROP_IS_SEPID_INDEP | + FFA_PART_PROP_IS_SEPID_DEP | + FFA_PART_PROP_IS_AUX_ID | + FFA_PART_PROP_NOTIF_CREATED | + FFA_PART_PROP_NOTIF_DESTROYED | + FFA_PART_PROP_AARCH64_STATE; + if (ffa_vers >= FFA_VERSION_1_1) { if (uuid_words) memcpy(fpi->uuid, uuid_words, FFA_UUID_SIZE); @@ -739,7 +762,11 @@ static uint32_t spmc_enable_async_notif(uint32_t bottom_half_value, static uint32_t get_direct_resp_fid(uint32_t fid) { assert(fid == FFA_MSG_SEND_DIRECT_REQ_64 || - fid == FFA_MSG_SEND_DIRECT_REQ_32); + fid == FFA_MSG_SEND_DIRECT_REQ_32 || + fid == FFA_MSG_SEND_DIRECT_REQ2); + + if (fid == FFA_MSG_SEND_DIRECT_REQ2) + return FFA_MSG_SEND_DIRECT_RESP2; if (OPTEE_SMC_IS_64(fid)) return FFA_MSG_SEND_DIRECT_RESP_64; @@ -905,6 +932,11 @@ optee_lsp_handle_direct_request(struct thread_smc_1_2_regs *args, return; } + if (args->a0 == FFA_MSG_SEND_DIRECT_REQ2) { + set_simple_ret_val(args, FFA_NOT_SUPPORTED); + return; + } + if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { handle_framework_direct_request(args); return; @@ -941,6 +973,11 @@ optee_spmc_lsp_handle_direct_request(struct thread_smc_1_2_regs *args, return; } + if (args->a0 == FFA_MSG_SEND_DIRECT_REQ2) { + set_simple_ret_val(args, FFA_NOT_SUPPORTED); + return; + } + if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) handle_framework_direct_request(args); else @@ -1985,6 +2022,14 @@ void thread_spmc_msg_recv(struct thread_smc_1_2_regs *args) case FFA_MSG_SEND_DIRECT_REQ_32: handle_direct_request(args); break; +#ifdef ARM64 + case FFA_MSG_SEND_DIRECT_REQ2: + if (my_rxtx.ffa_vers < FFA_VERSION_1_2) + set_simple_ret_val(args, FFA_NOT_SUPPORTED); + else + handle_direct_request(args); + break; +#endif #if defined(CFG_CORE_SEL1_SPMC) #ifdef ARM64 case FFA_MEM_SHARE_64: