From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1764258792379726.4271180047749; Thu, 27 Nov 2025 07:53:12 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174075.1499052 (Exim 4.92) (envelope-from ) id 1vOeIe-00044G-T1; Thu, 27 Nov 2025 15:52:52 +0000 Received: by outflank-mailman (output) from mailman id 1174075.1499052; Thu, 27 Nov 2025 15:52:52 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIe-000447-QT; Thu, 27 Nov 2025 15:52:52 +0000 Received: by outflank-mailman (input) for mailman id 1174075; Thu, 27 Nov 2025 15:52:51 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeId-0003dB-BF for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:52:51 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 2087d7e9-cba9-11f0-9d18-b5c5bf9af7f9; Thu, 27 Nov 2025 16:52:50 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8AB71176A; Thu, 27 Nov 2025 07:52:42 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9A1173F73B; Thu, 27 Nov 2025 07:52:48 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 2087d7e9-cba9-11f0-9d18-b5c5bf9af7f9 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 01/10] xen/arm: ffa: add FF-A v1.2 function IDs Date: Thu, 27 Nov 2025 16:51:32 +0100 Message-ID: <2264daf90cbb25b9a60ebe8edbebb8988d95966b.1764254975.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764258792604019200 Content-Type: text/plain; charset="utf-8" Bring the FF-A headers up to the v1.2 baseline and fix the function-number range used for ABI discovery: - update FFA_FNUM_MAX_VALUE so the FF-A function-number window covers the full v1.2 range, and derive the ABI bitmap bounds from FFA_FNUM_MIN_VALUE/FFA_FNUM_MAX_VALUE instead of hard-coding FFA_ERROR/FFA_MSG_SEND2 - define the new v1.2 function IDs; CONSOLE_LOG and PARTITION_INFO_GET_REGS are added for ABI discovery even though they are not implemented yet - extend the firmware ABI table to probe RUN and MSG_SEND_DIRECT_REQ2/RESP2 - while there, fix an off-by-one in ffa_fw_supports_fid(): the computed bit index must be strictly smaller than FFA_ABI_BITMAP_SIZE, so use >=3D in t= he bounds check Keep FFA_MY_VERSION at 1.1 for now; we only advertise v1.2 once the implementation is fully compliant. Signed-off-by: Bertrand Marquis --- xen/arch/arm/include/asm/tee/ffa.h | 2 +- xen/arch/arm/tee/ffa.c | 4 ++++ xen/arch/arm/tee/ffa_private.h | 18 +++++++++++------- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/xen/arch/arm/include/asm/tee/ffa.h b/xen/arch/arm/include/asm/= tee/ffa.h index 24cd4d99c8f9..c587f76e63ca 100644 --- a/xen/arch/arm/include/asm/tee/ffa.h +++ b/xen/arch/arm/include/asm/tee/ffa.h @@ -16,7 +16,7 @@ #include =20 #define FFA_FNUM_MIN_VALUE _AC(0x60,U) -#define FFA_FNUM_MAX_VALUE _AC(0x86,U) +#define FFA_FNUM_MAX_VALUE _AC(0x8F,U) =20 static inline bool is_ffa_fid(uint32_t fid) { diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 1d0239cf6950..2b4e24750d52 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -11,6 +11,8 @@ * https://developer.arm.com/documentation/den0077/a * FF-A-1.1-REL0: FF-A specification version 1.1 available at * https://developer.arm.com/documentation/den0077/e + * FF-A-1.2-REL0: FF-A specification version 1.2 available at + * https://developer.arm.com/documentation/den0077/j * TEEC-1.0C: TEE Client API Specification version 1.0c available at * https://globalplatform.org/specs-library/tee-client-api-spec= ification/ * @@ -102,6 +104,8 @@ static const struct ffa_fw_abi ffa_fw_abi_needed[] =3D { FW_ABI(FFA_MSG_SEND_DIRECT_REQ_32), FW_ABI(FFA_MSG_SEND_DIRECT_REQ_64), FW_ABI(FFA_MSG_SEND2), + FW_ABI(FFA_MSG_SEND_DIRECT_REQ2), + FW_ABI(FFA_RUN), }; =20 /* diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 6dbdb200d840..d7e6b6f5ef45 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -15,6 +15,7 @@ #include #include #include +#include =20 /* Error codes */ #define FFA_RET_OK 0 @@ -42,6 +43,7 @@ =20 #define FFA_VERSION_1_0 MAKE_FFA_VERSION(1, 0) #define FFA_VERSION_1_1 MAKE_FFA_VERSION(1, 1) +#define FFA_VERSION_1_2 MAKE_FFA_VERSION(1, 2) /* The minimal FF-A version of the SPMC that can be supported */ #define FFA_MIN_SPMC_VERSION FFA_VERSION_1_1 =20 @@ -270,6 +272,10 @@ #define FFA_RX_ACQUIRE 0x84000084U #define FFA_SPM_ID_GET 0x84000085U #define FFA_MSG_SEND2 0x84000086U +#define FFA_CONSOLE_LOG 0x8400008AU +#define FFA_PARTITION_INFO_GET_REGS 0x8400008BU +#define FFA_MSG_SEND_DIRECT_REQ2 0xC400008DU +#define FFA_MSG_SEND_DIRECT_RESP2 0xC400008EU =20 /** * Encoding of features supported or not by the fw in a bitmap: @@ -280,11 +286,9 @@ #define FFA_ABI_ID(id) ((id) & ARM_SMCCC_FUNC_MASK) #define FFA_ABI_CONV(id) (((id) >> ARM_SMCCC_CONV_SHIFT) & BIT(0,U)) =20 -#define FFA_ABI_MIN FFA_ABI_ID(FFA_ERROR) -#define FFA_ABI_MAX FFA_ABI_ID(FFA_MSG_SEND2) - -#define FFA_ABI_BITMAP_SIZE (2 * (FFA_ABI_MAX - FFA_ABI_MIN + 1)) -#define FFA_ABI_BITNUM(id) ((FFA_ABI_ID(id) - FFA_ABI_MIN) << 1 | \ +#define FFA_ABI_BITMAP_SIZE (2 * (FFA_FNUM_MAX_VALUE - FFA_FNUM_MIN_VALU= E \ + + 1)) +#define FFA_ABI_BITNUM(id) ((FFA_ABI_ID(id) - FFA_FNUM_MIN_VALUE) << 1 = | \ FFA_ABI_CONV(id)) =20 /* Constituent memory region descriptor */ @@ -549,9 +553,9 @@ static inline int32_t ffa_hyp_rx_release(void) =20 static inline bool ffa_fw_supports_fid(uint32_t fid) { - BUILD_BUG_ON(FFA_ABI_MIN > FFA_ABI_MAX); + BUILD_BUG_ON(FFA_FNUM_MIN_VALUE > FFA_FNUM_MAX_VALUE); =20 - if ( FFA_ABI_BITNUM(fid) > FFA_ABI_BITMAP_SIZE) + if ( FFA_ABI_BITNUM(fid) >=3D FFA_ABI_BITMAP_SIZE) return false; return test_bit(FFA_ABI_BITNUM(fid), ffa_fw_abi_supported); } --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 176425878769011.771441087308972; Thu, 27 Nov 2025 07:53:07 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174076.1499062 (Exim 4.92) (envelope-from ) id 1vOeIg-0004IH-34; Thu, 27 Nov 2025 15:52:54 +0000 Received: by outflank-mailman (output) from mailman id 1174076.1499062; Thu, 27 Nov 2025 15:52:54 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIf-0004IA-WC; Thu, 27 Nov 2025 15:52:54 +0000 Received: by outflank-mailman (input) for mailman id 1174076; Thu, 27 Nov 2025 15:52:53 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIf-0003dB-1d for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:52:53 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 21965254-cba9-11f0-9d18-b5c5bf9af7f9; Thu, 27 Nov 2025 16:52:52 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 52CC7176C; Thu, 27 Nov 2025 07:52:44 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5CE9D3F73B; Thu, 27 Nov 2025 07:52:50 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 21965254-cba9-11f0-9d18-b5c5bf9af7f9 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 02/10] xen/arm: ffa: per-VM FFA_VERSION negotiation state Date: Thu, 27 Nov 2025 16:51:33 +0100 Message-ID: <5e66b2991340f010befcaa3a57d0f35ad18d4149.1764254975.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764258788807019200 Content-Type: text/plain; charset="utf-8" Track FF-A version negotiation per VM and enforce that no FF-A ABI (other than FFA_VERSION) is processed before a guest has selected a version. Each ffa_ctx gains a dedicated guest_vers_lock, a negotiated version (guest_vers) and a guest_vers_negotiated flag. guest_vers records the version requested by the guest so the mediator can provide data structures compatible with older minor versions. The value returned to the guest by FFA_VERSION is always FFA_MY_VERSION, the implementation version, as required by FF-A. FFA_VERSION may be issued multiple times. Negotiation becomes final only when a non-FFA_VERSION ABI is invoked, in accordance with the FF-A requirement that the version cannot change once any other ABI has been used. Before this point, non-FFA_VERSION ABIs are rejected if no valid version has been provided. Once negotiation completes, the context is added to the global FF-A VM list (when VM-to-VM is enabled) and the version may not be modified for the lifetime of the VM. All VM-to-VM paths and teardown logic are updated to use the guest_vers_negotiated flag. This prevents partially initialised contexts from using the mediator and complies with the FF-A 1.2 FFA_VERSION semantics. Signed-off-by: Bertrand Marquis --- xen/arch/arm/tee/ffa.c | 115 +++++++++++++++++++++++++-------- xen/arch/arm/tee/ffa_msg.c | 2 +- xen/arch/arm/tee/ffa_private.h | 21 ++++-- 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 2b4e24750d52..3309ca875ec4 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -158,40 +158,89 @@ static bool ffa_abi_supported(uint32_t id) return !ffa_simple_call(FFA_FEATURES, id, 0, 0, 0); } =20 -static void handle_version(struct cpu_user_regs *regs) +static bool ffa_negotiate_version(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; - uint32_t vers =3D get_user_reg(regs, 1); - uint32_t old_vers; + uint32_t fid =3D get_user_reg(regs, 0); + uint32_t in_vers =3D get_user_reg(regs, 1); + uint32_t out_vers =3D FFA_MY_VERSION; =20 - /* - * Guest will use the version it requested if it is our major and minor - * lower or equals to ours. If the minor is greater, our version will = be - * used. - * In any case return our version to the caller. - */ - if ( FFA_VERSION_MAJOR(vers) =3D=3D FFA_MY_VERSION_MAJOR ) - { - spin_lock(&ctx->lock); - old_vers =3D ctx->guest_vers; + spin_lock(&ctx->guest_vers_lock); =20 - if ( FFA_VERSION_MINOR(vers) > FFA_MY_VERSION_MINOR ) - ctx->guest_vers =3D FFA_MY_VERSION; - else - ctx->guest_vers =3D vers; - spin_unlock(&ctx->lock); + /* Handle FFA_VERSION races from different vCPUs. */ + if ( ctx->guest_vers_negotiated ) + goto out_continue; =20 - if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !old_vers ) + if ( fid !=3D FFA_VERSION ) + { + if ( !ctx->guest_vers ) { - /* One more VM with FF-A support available */ - inc_ffa_vm_count(); - write_lock(&ffa_ctx_list_rwlock); - list_add_tail(&ctx->ctx_list, &ffa_ctx_head); - write_unlock(&ffa_ctx_list_rwlock); + out_vers =3D 0; + goto out_handled; } + + /* + * A successful FFA_VERSION call does not freeze negotiation. Gues= ts + * are allowed to issue multiple FFA_VERSION attempts (e.g. probing + * several minor versions). Negotiation becomes final only when a + * non-VERSION ABI is invoked, as required by the FF-A specificati= on. + */ + if ( !ctx->guest_vers_negotiated ) + { + ctx->guest_vers_negotiated =3D true; + + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + { + /* One more VM with FF-A support available */ + inc_ffa_vm_count(); + write_lock(&ffa_ctx_list_rwlock); + list_add_tail(&ctx->ctx_list, &ffa_ctx_head); + write_unlock(&ffa_ctx_list_rwlock); + } + } + + goto out_continue; + } + + /* + * guest_vers stores the version selected by the guest (lower minor may + * require reduced data structures). However, the value returned to the + * guest via FFA_VERSION is always FFA_MY_VERSION, the implementation + * version, as required by FF-A. The two values intentionally differ. + */ + + /* + * Return our highest implementation version on request different than= our + * major and mark negotiated version as our implementation version. + */ + if ( FFA_VERSION_MAJOR(in_vers) !=3D FFA_MY_VERSION_MAJOR ) + { + ctx->guest_vers =3D FFA_MY_VERSION; + goto out_handled; } - ffa_set_regs(regs, FFA_MY_VERSION, 0, 0, 0, 0, 0, 0, 0); + + /* + * Use our minor version if a greater minor was requested or the reque= sted + * minor if it is lower than ours was requested. + */ + if ( FFA_VERSION_MINOR(in_vers) > FFA_MY_VERSION_MINOR ) + ctx->guest_vers =3D FFA_MY_VERSION; + else + ctx->guest_vers =3D in_vers; + +out_handled: + spin_unlock(&ctx->guest_vers_lock); + if ( out_vers ) + ffa_set_regs(regs, out_vers, 0, 0, 0, 0, 0, 0, 0); + else + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); + return true; + +out_continue: + spin_unlock(&ctx->guest_vers_lock); + + return false; } =20 static void handle_features(struct cpu_user_regs *regs) @@ -274,10 +323,17 @@ static bool ffa_handle_call(struct cpu_user_regs *reg= s) if ( !ctx ) return false; =20 + /* A version must be negotiated first */ + if ( !ctx->guest_vers_negotiated ) + { + if ( ffa_negotiate_version(regs) ) + return true; + } + switch ( fid ) { case FFA_VERSION: - handle_version(regs); + ffa_set_regs(regs, FFA_MY_VERSION, 0, 0, 0, 0, 0, 0, 0); return true; case FFA_ID_GET: ffa_set_regs_success(regs, ffa_get_vm_id(d), 0); @@ -371,6 +427,11 @@ static int ffa_domain_init(struct domain *d) d->arch.tee =3D ctx; ctx->teardown_d =3D d; INIT_LIST_HEAD(&ctx->shm_list); + spin_lock_init(&ctx->lock); + spin_lock_init(&ctx->guest_vers_lock); + ctx->guest_vers =3D 0; + ctx->guest_vers_negotiated =3D false; + INIT_LIST_HEAD(&ctx->ctx_list); =20 ctx->ffa_id =3D ffa_get_vm_id(d); ctx->num_vcpus =3D d->max_vcpus; @@ -452,7 +513,7 @@ static int ffa_domain_teardown(struct domain *d) if ( !ctx ) return 0; =20 - if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) && ctx->guest_vers ) + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) && ctx->guest_vers_negotiated ) { dec_ffa_vm_count(); write_lock(&ffa_ctx_list_rwlock); diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c index c20c5bec0f76..dec429cbf160 100644 --- a/xen/arch/arm/tee/ffa_msg.c +++ b/xen/arch/arm/tee/ffa_msg.c @@ -113,7 +113,7 @@ static int32_t ffa_msg_send2_vm(uint16_t dst_id, const = void *src_buf, } =20 dst_ctx =3D dst_d->arch.tee; - if ( !dst_ctx->guest_vers ) + if ( !dst_ctx->guest_vers_negotiated ) { ret =3D FFA_RET_INVALID_PARAMETERS; goto out_unlock; diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index d7e6b6f5ef45..88b85c7c453a 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -354,12 +354,6 @@ struct ffa_ctx { * Global data accessed with lock locked. */ spinlock_t lock; - /* - * FF-A version negotiated by the guest, only modifications to - * this field are done with the lock held as this is expected to - * be done once at init by a guest. - */ - uint32_t guest_vers; /* Number of 4kB pages in each of rx/rx_pg and tx/tx_pg */ unsigned int page_count; /* Number of allocated shared memory object */ @@ -367,6 +361,21 @@ struct ffa_ctx { /* Used shared memory objects, struct ffa_shm_mem */ struct list_head shm_list; =20 + /* + * FF-A version handling + * guest_vers and guest_vers_negotiated are only written with + * guest_vers_lock held. Reads do not take the lock, but ordering is + * guaranteed because the writer updates guest_vers first and then + * guest_vers_negotiated while holding the lock, ensuring any reader + * that observes guest_vers_negotiated =3D=3D true also sees the final + * guest_vers value. + * The ffa_ctx is added to the ctx_list only when a version + * has been negotiated and locked. + */ + spinlock_t guest_vers_lock; + uint32_t guest_vers; + bool guest_vers_negotiated; + /* * Rx buffer, accessed with rx_lock locked. * rx_is_free is used to serialize access. --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1764258793830515.6039559351925; Thu, 27 Nov 2025 07:53:13 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174079.1499071 (Exim 4.92) (envelope-from ) id 1vOeIi-0004YG-FE; Thu, 27 Nov 2025 15:52:56 +0000 Received: by outflank-mailman (output) from mailman id 1174079.1499071; Thu, 27 Nov 2025 15:52:56 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIi-0004Y5-CG; Thu, 27 Nov 2025 15:52:56 +0000 Received: by outflank-mailman (input) for mailman id 1174079; Thu, 27 Nov 2025 15:52:55 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIh-0003dB-1O for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:52:55 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 2299b985-cba9-11f0-9d18-b5c5bf9af7f9; Thu, 27 Nov 2025 16:52:54 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1467B176A; Thu, 27 Nov 2025 07:52:46 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 22BE53F73B; Thu, 27 Nov 2025 07:52:51 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 2299b985-cba9-11f0-9d18-b5c5bf9af7f9 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 03/10] xen/arm: ffa: harden RX/TX mapping Date: Thu, 27 Nov 2025 16:51:34 +0100 Message-ID: X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764258794645019200 Content-Type: text/plain; charset="utf-8" Harden the RX/TX mapping paths and keep signed FF-A return codes end-to-end. Reject zero-length mappings and insist on page-aligned RX/TX buffer addresses before touching the P2M. The unmap plumbing is switched to use the same signed helpers so dispatcher error handling is consistent across map and unmap operations. This avoids partially mapped or silently truncated buffers and makes the mediator behaviour match the FF-A error model more closely. While there also introduce a domain_rxtx_init to properly initialize the rxtx buffers spinlocks. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- xen/arch/arm/tee/ffa.c | 4 ++++ xen/arch/arm/tee/ffa_private.h | 5 +++-- xen/arch/arm/tee/ffa_rxtx.c | 28 +++++++++++++++++++++------- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 3309ca875ec4..47f426e85864 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -446,6 +446,10 @@ static int ffa_domain_init(struct domain *d) if ( ret ) return ret; =20 + ret =3D ffa_rxtx_domain_init(d); + if ( ret ) + return ret; + return ffa_notif_domain_init(d); } =20 diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 88b85c7c453a..4272afd37343 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -427,10 +427,11 @@ void ffa_handle_partition_info_get(struct cpu_user_re= gs *regs); =20 bool ffa_rxtx_init(void); void ffa_rxtx_destroy(void); +int32_t ffa_rxtx_domain_init(struct domain *d); void ffa_rxtx_domain_destroy(struct domain *d); -uint32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, +int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, register_t rx_addr, uint32_t page_count); -uint32_t ffa_handle_rxtx_unmap(void); +int32_t ffa_handle_rxtx_unmap(void); int32_t ffa_rx_acquire(struct domain *d); int32_t ffa_rx_release(struct domain *d); =20 diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c index a40e5b32e3a5..cd467d1dba68 100644 --- a/xen/arch/arm/tee/ffa_rxtx.c +++ b/xen/arch/arm/tee/ffa_rxtx.c @@ -41,10 +41,10 @@ static int32_t ffa_rxtx_unmap(uint16_t id) return ffa_simple_call(FFA_RXTX_UNMAP, ((uint64_t)id) << 16, 0, 0, 0); } =20 -uint32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, +int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, register_t rx_addr, uint32_t page_count) { - uint32_t ret =3D FFA_RET_INVALID_PARAMETERS; + int32_t ret =3D FFA_RET_INVALID_PARAMETERS; struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; struct page_info *tx_pg; @@ -66,13 +66,17 @@ uint32_t ffa_handle_rxtx_map(uint32_t fid, register_t t= x_addr, rx_addr &=3D UINT32_MAX; } =20 - if ( page_count > FFA_MAX_RXTX_PAGE_COUNT ) + if ( page_count > FFA_MAX_RXTX_PAGE_COUNT || !page_count ) { printk(XENLOG_ERR "ffa: RXTX_MAP: error: %u pages requested (limit= %u)\n", page_count, FFA_MAX_RXTX_PAGE_COUNT); return FFA_RET_INVALID_PARAMETERS; } =20 + if ( !IS_ALIGNED(tx_addr, FFA_PAGE_SIZE) || + !IS_ALIGNED(rx_addr, FFA_PAGE_SIZE) ) + return FFA_RET_INVALID_PARAMETERS; + /* Already mapped */ if ( ctx->rx ) return FFA_RET_DENIED; @@ -181,7 +185,7 @@ err_put_tx_pg: return ret; } =20 -static uint32_t rxtx_unmap(struct domain *d) +static int32_t rxtx_unmap(struct domain *d) { struct ffa_ctx *ctx =3D d->arch.tee; =20 @@ -190,7 +194,7 @@ static uint32_t rxtx_unmap(struct domain *d) =20 if ( ffa_fw_supports_fid(FFA_RX_ACQUIRE) ) { - uint32_t ret; + int32_t ret; =20 ret =3D ffa_rxtx_unmap(ffa_get_vm_id(d)); if ( ret !=3D FFA_RET_OK ) @@ -211,7 +215,7 @@ static uint32_t rxtx_unmap(struct domain *d) return FFA_RET_OK; } =20 -uint32_t ffa_handle_rxtx_unmap(void) +int32_t ffa_handle_rxtx_unmap(void) { return rxtx_unmap(current->domain); } @@ -272,6 +276,16 @@ out: return ret; } =20 +int32_t ffa_rxtx_domain_init(struct domain *d) +{ + struct ffa_ctx *ctx =3D d->arch.tee; + + spin_lock_init(&ctx->rx_lock); + spin_lock_init(&ctx->tx_lock); + + return 0; +} + void ffa_rxtx_domain_destroy(struct domain *d) { rxtx_unmap(d); @@ -298,7 +312,7 @@ void ffa_rxtx_destroy(void) =20 bool ffa_rxtx_init(void) { - int e; + int32_t e; =20 /* Firmware not there or not supporting */ if ( !ffa_fw_supports_fid(FFA_RXTX_MAP_64) ) --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1764258794953433.4092793794648; Thu, 27 Nov 2025 07:53:14 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174080.1499082 (Exim 4.92) (envelope-from ) id 1vOeIk-0004pp-Nm; Thu, 27 Nov 2025 15:52:58 +0000 Received: by outflank-mailman (output) from mailman id 1174080.1499082; Thu, 27 Nov 2025 15:52:58 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIk-0004pi-KE; Thu, 27 Nov 2025 15:52:58 +0000 Received: by outflank-mailman (input) for mailman id 1174080; Thu, 27 Nov 2025 15:52:58 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIk-0004I5-4V for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:52:58 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 23a68b88-cba9-11f0-980a-7dc792cee155; Thu, 27 Nov 2025 16:52:55 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id CF361176C; Thu, 27 Nov 2025 07:52:47 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DA95F3F73B; Thu, 27 Nov 2025 07:52:53 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 23a68b88-cba9-11f0-980a-7dc792cee155 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 04/10] xen/arm: ffa: rework SPMC RX/TX buffer management Date: Thu, 27 Nov 2025 16:51:35 +0100 Message-ID: <72d6592157a9ec15d4b5de19751186e0ca1680ba.1764254975.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764258796784019200 Content-Type: text/plain; charset="utf-8" Rework how Xen accesses the RX/TX buffers shared with the SPMC so that ownership and locking are handled centrally. Move the SPMC RX/TX buffer bases into ffa_rxtx.c as ffa_spmc_rx/ffa_spmc_tx, protect them with dedicated ffa_spmc_{rx,tx}_lock spinlocks and expose ffa_rxtx_spmc_{rx,tx}_{acquire,release}() helpers instead of the global ffa_rx/ffa_tx pointers and ffa_{rx,tx}_buffer_lock. The RX helpers now always issue FFA_RX_RELEASE when we are done consuming data from the SPMC, so partition-info enumeration and shared memory paths release the RX buffer on all exit paths. The RX/TX mapping code is updated to use the descriptor offsets (rx_region_offs and tx_region_offs) rather than hard-coded structure layout, and to use the TX acquire/release helpers instead of touching the TX buffer directly. Signed-off-by: Bertrand Marquis --- xen/arch/arm/tee/ffa.c | 22 +----- xen/arch/arm/tee/ffa_partinfo.c | 40 +++++----- xen/arch/arm/tee/ffa_private.h | 18 ++--- xen/arch/arm/tee/ffa_rxtx.c | 132 +++++++++++++++++++++++++------- xen/arch/arm/tee/ffa_shm.c | 26 ++++--- 5 files changed, 153 insertions(+), 85 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 47f426e85864..4c1b9a4c3b48 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -48,8 +48,8 @@ * notification for secure partitions * - doesn't support notifications for Xen itself * - * There are some large locked sections with ffa_tx_buffer_lock and - * ffa_rx_buffer_lock. Especially the ffa_tx_buffer_lock spinlock used + * There are some large locked sections with ffa_spmc_tx_lock and + * ffa_spmc_rx_lock. Especially the ffa_spmc_tx_lock spinlock used * around share_shm() is a very large locked section which can let one VM * affect another VM. */ @@ -108,20 +108,6 @@ static const struct ffa_fw_abi ffa_fw_abi_needed[] =3D= { FW_ABI(FFA_RUN), }; =20 -/* - * Our rx/tx buffers shared with the SPMC. FFA_RXTX_PAGE_COUNT is the - * number of pages used in each of these buffers. - * - * The RX buffer is protected from concurrent usage with ffa_rx_buffer_loc= k. - * Note that the SPMC is also tracking the ownership of our RX buffer so - * for calls which uses our RX buffer to deliver a result we must call - * ffa_rx_release() to let the SPMC know that we're done with the buffer. - */ -void *ffa_rx __read_mostly; -void *ffa_tx __read_mostly; -DEFINE_SPINLOCK(ffa_rx_buffer_lock); -DEFINE_SPINLOCK(ffa_tx_buffer_lock); - LIST_HEAD(ffa_ctx_head); /* RW Lock to protect addition/removal and reading in ffa_ctx_head */ DEFINE_RWLOCK(ffa_ctx_list_rwlock); @@ -612,7 +598,7 @@ static bool ffa_probe_fw(void) ffa_fw_abi_needed[i].name); } =20 - if ( !ffa_rxtx_init() ) + if ( !ffa_rxtx_spmc_init() ) { printk(XENLOG_ERR "ffa: Error during RXTX buffer init\n"); goto err_no_fw; @@ -626,7 +612,7 @@ static bool ffa_probe_fw(void) return true; =20 err_rxtx_destroy: - ffa_rxtx_destroy(); + ffa_rxtx_spmc_destroy(); err_no_fw: ffa_fw_version =3D 0; bitmap_zero(ffa_fw_abi_supported, FFA_ABI_BITMAP_SIZE); diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinf= o.c index fa56b1587e3b..766b75dffb8c 100644 --- a/xen/arch/arm/tee/ffa_partinfo.c +++ b/xen/arch/arm/tee/ffa_partinfo.c @@ -77,28 +77,24 @@ static int32_t ffa_get_sp_partinfo(uint32_t *uuid, uint= 32_t *sp_count, { int32_t ret; uint32_t src_size, real_sp_count; - void *src_buf =3D ffa_rx; + void *src_buf; uint32_t count =3D 0; =20 - /* Do we have a RX buffer with the SPMC */ - if ( !ffa_rx ) - return FFA_RET_DENIED; - /* We need to use the RX buffer to receive the list */ - spin_lock(&ffa_rx_buffer_lock); + src_buf =3D ffa_rxtx_spmc_rx_acquire(); + if ( !src_buf ) + return FFA_RET_DENIED; =20 ret =3D ffa_partition_info_get(uuid, 0, &real_sp_count, &src_size); if ( ret ) goto out; =20 - /* We now own the RX buffer */ - /* Validate the src_size we got */ if ( src_size < sizeof(struct ffa_partition_info_1_0) || src_size >=3D FFA_PAGE_SIZE ) { ret =3D FFA_RET_NOT_SUPPORTED; - goto out_release; + goto out; } =20 /* @@ -114,7 +110,7 @@ static int32_t ffa_get_sp_partinfo(uint32_t *uuid, uint= 32_t *sp_count, if ( real_sp_count > (FFA_RXTX_PAGE_COUNT * FFA_PAGE_SIZE) / src_size ) { ret =3D FFA_RET_NOT_SUPPORTED; - goto out_release; + goto out; } =20 for ( uint32_t sp_num =3D 0; sp_num < real_sp_count; sp_num++ ) @@ -127,7 +123,7 @@ static int32_t ffa_get_sp_partinfo(uint32_t *uuid, uint= 32_t *sp_count, if ( dst_buf > (end_buf - dst_size) ) { ret =3D FFA_RET_NO_MEMORY; - goto out_release; + goto out; } =20 memcpy(dst_buf, src_buf, MIN(src_size, dst_size)); @@ -143,10 +139,8 @@ static int32_t ffa_get_sp_partinfo(uint32_t *uuid, uin= t32_t *sp_count, =20 *sp_count =3D count; =20 -out_release: - ffa_hyp_rx_release(); out: - spin_unlock(&ffa_rx_buffer_lock); + ffa_rxtx_spmc_rx_release(); return ret; } =20 @@ -378,7 +372,7 @@ static void uninit_subscribers(void) XFREE(subscr_vm_destroyed); } =20 -static bool init_subscribers(uint16_t count, uint32_t fpi_size) +static bool init_subscribers(void *buf, uint16_t count, uint32_t fpi_size) { uint16_t n; uint16_t c_pos; @@ -395,7 +389,7 @@ static bool init_subscribers(uint16_t count, uint32_t f= pi_size) subscr_vm_destroyed_count =3D 0; for ( n =3D 0; n < count; n++ ) { - fpi =3D ffa_rx + n * fpi_size; + fpi =3D buf + n * fpi_size; =20 /* * We need to have secure partitions using bit 15 set convention f= or @@ -433,7 +427,7 @@ static bool init_subscribers(uint16_t count, uint32_t f= pi_size) =20 for ( c_pos =3D 0, d_pos =3D 0, n =3D 0; n < count; n++ ) { - fpi =3D ffa_rx + n * fpi_size; + fpi =3D buf + n * fpi_size; =20 if ( FFA_ID_IS_SECURE(fpi->id) ) { @@ -455,10 +449,14 @@ bool ffa_partinfo_init(void) uint32_t fpi_size; uint32_t count; int e; + void *spmc_rx; =20 if ( !ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) || - !ffa_fw_supports_fid(FFA_MSG_SEND_DIRECT_REQ_32) || - !ffa_rx || !ffa_tx ) + !ffa_fw_supports_fid(FFA_MSG_SEND_DIRECT_REQ_32)) + return false; + + spmc_rx =3D ffa_rxtx_spmc_rx_acquire(); + if (!spmc_rx) return false; =20 e =3D ffa_partition_info_get(NULL, 0, &count, &fpi_size); @@ -475,10 +473,10 @@ bool ffa_partinfo_init(void) goto out; } =20 - ret =3D init_subscribers(count, fpi_size); + ret =3D init_subscribers(spmc_rx, count, fpi_size); =20 out: - ffa_hyp_rx_release(); + ffa_rxtx_spmc_rx_release(); return ret; } =20 diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 4272afd37343..cd35c44b8986 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -404,10 +404,6 @@ struct ffa_ctx { unsigned long *vm_destroy_bitmap; }; =20 -extern void *ffa_rx; -extern void *ffa_tx; -extern spinlock_t ffa_rx_buffer_lock; -extern spinlock_t ffa_tx_buffer_lock; extern DECLARE_BITMAP(ffa_fw_abi_supported, FFA_ABI_BITMAP_SIZE); =20 extern struct list_head ffa_ctx_head; @@ -425,8 +421,13 @@ int ffa_partinfo_domain_init(struct domain *d); bool ffa_partinfo_domain_destroy(struct domain *d); void ffa_handle_partition_info_get(struct cpu_user_regs *regs); =20 -bool ffa_rxtx_init(void); -void ffa_rxtx_destroy(void); +bool ffa_rxtx_spmc_init(void); +void ffa_rxtx_spmc_destroy(void); +void *ffa_rxtx_spmc_rx_acquire(void); +void ffa_rxtx_spmc_rx_release(void); +void *ffa_rxtx_spmc_tx_acquire(void); +void ffa_rxtx_spmc_tx_release(void); + int32_t ffa_rxtx_domain_init(struct domain *d); void ffa_rxtx_domain_destroy(struct domain *d); int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, @@ -556,11 +557,6 @@ static inline int32_t ffa_simple_call(uint32_t fid, re= gister_t a1, return ffa_get_ret_code(&resp); } =20 -static inline int32_t ffa_hyp_rx_release(void) -{ - return ffa_simple_call(FFA_RX_RELEASE, 0, 0, 0, 0); -} - static inline bool ffa_fw_supports_fid(uint32_t fid) { BUILD_BUG_ON(FFA_FNUM_MIN_VALUE > FFA_FNUM_MAX_VALUE); diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c index cd467d1dba68..07b01430d139 100644 --- a/xen/arch/arm/tee/ffa_rxtx.c +++ b/xen/arch/arm/tee/ffa_rxtx.c @@ -30,6 +30,20 @@ struct ffa_endpoint_rxtx_descriptor_1_1 { uint32_t tx_region_offs; }; =20 +/* + * Our rx/tx buffers shared with the SPMC. FFA_RXTX_PAGE_COUNT is the + * number of pages used in each of these buffers. + * Each buffer has its own lock to protect from concurrent usage. + * + * Note that the SPMC is also tracking the ownership of our RX buffer so + * for calls which uses our RX buffer to deliver a result we must do an + * FFA_RX_RELEASE to let the SPMC know that we're done with the buffer. + */ +static void *ffa_spmc_rx __read_mostly; +static void *ffa_spmc_tx __read_mostly; +static DEFINE_SPINLOCK(ffa_spmc_rx_lock); +static DEFINE_SPINLOCK(ffa_spmc_tx_lock); + static int32_t ffa_rxtx_map(paddr_t tx_addr, paddr_t rx_addr, uint32_t page_count) { @@ -120,8 +134,9 @@ int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx= _addr, sizeof(struct ffa_address_range) * 2 > FFA_MAX_RXTX_PAGE_COUNT * FFA_PAGE_SIZE); =20 - spin_lock(&ffa_tx_buffer_lock); - rxtx_desc =3D ffa_tx; + rxtx_desc =3D ffa_rxtx_spmc_tx_acquire(); + if ( !rxtx_desc ) + goto err_unmap_rx; =20 /* * We have only one page for each so we pack everything: @@ -138,7 +153,7 @@ int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx= _addr, address_range_array[1]); =20 /* rx buffer */ - mem_reg =3D ffa_tx + sizeof(*rxtx_desc); + mem_reg =3D (void *)rxtx_desc + rxtx_desc->rx_region_offs; mem_reg->total_page_count =3D 1; mem_reg->address_range_count =3D 1; mem_reg->reserved =3D 0; @@ -148,7 +163,7 @@ int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx= _addr, mem_reg->address_range_array[0].reserved =3D 0; =20 /* tx buffer */ - mem_reg =3D ffa_tx + rxtx_desc->tx_region_offs; + mem_reg =3D (void *)rxtx_desc + rxtx_desc->tx_region_offs; mem_reg->total_page_count =3D 1; mem_reg->address_range_count =3D 1; mem_reg->reserved =3D 0; @@ -159,7 +174,7 @@ int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx= _addr, =20 ret =3D ffa_rxtx_map(0, 0, 0); =20 - spin_unlock(&ffa_tx_buffer_lock); + ffa_rxtx_spmc_tx_release(); =20 if ( ret !=3D FFA_RET_OK ) goto err_unmap_rx; @@ -291,49 +306,114 @@ void ffa_rxtx_domain_destroy(struct domain *d) rxtx_unmap(d); } =20 -void ffa_rxtx_destroy(void) +void *ffa_rxtx_spmc_rx_acquire(void) +{ + ASSERT(!spin_is_locked(&ffa_spmc_rx_lock)); + + spin_lock(&ffa_spmc_rx_lock); + + if ( ffa_spmc_rx ) + return ffa_spmc_rx; + + spin_unlock(&ffa_spmc_rx_lock); + return NULL; +} + +void ffa_rxtx_spmc_rx_release(void) +{ + int32_t ret; + + ASSERT(spin_is_locked(&ffa_spmc_rx_lock)); + + /* Inform the SPMC that we are done with our RX buffer */ + ret =3D ffa_simple_call(FFA_RX_RELEASE, 0, 0, 0, 0); + if ( ret !=3D FFA_RET_OK ) + printk(XENLOG_DEBUG "Error releasing SPMC RX buffer: %d\n", ret); + + spin_unlock(&ffa_spmc_rx_lock); +} + +void *ffa_rxtx_spmc_tx_acquire(void) { - bool need_unmap =3D ffa_tx && ffa_rx; + ASSERT(!spin_is_locked(&ffa_spmc_tx_lock)); =20 - if ( ffa_tx ) + spin_lock(&ffa_spmc_tx_lock); + + if ( ffa_spmc_tx ) + return ffa_spmc_tx; + + spin_unlock(&ffa_spmc_tx_lock); + return NULL; +} + +void ffa_rxtx_spmc_tx_release(void) +{ + ASSERT(spin_is_locked(&ffa_spmc_tx_lock)); + + spin_unlock(&ffa_spmc_tx_lock); +} + +void ffa_rxtx_spmc_destroy(void) +{ + bool need_unmap; + + spin_lock(&ffa_spmc_rx_lock); + spin_lock(&ffa_spmc_tx_lock); + need_unmap =3D ffa_spmc_tx && ffa_spmc_rx; + + if ( ffa_spmc_tx ) { - free_xenheap_pages(ffa_tx, 0); - ffa_tx =3D NULL; + free_xenheap_pages(ffa_spmc_tx, 0); + ffa_spmc_tx =3D NULL; } - if ( ffa_rx ) + if ( ffa_spmc_rx ) { - free_xenheap_pages(ffa_rx, 0); - ffa_rx =3D NULL; + free_xenheap_pages(ffa_spmc_rx, 0); + ffa_spmc_rx =3D NULL; } =20 if ( need_unmap ) ffa_rxtx_unmap(0); + + spin_unlock(&ffa_spmc_tx_lock); + spin_unlock(&ffa_spmc_rx_lock); } =20 -bool ffa_rxtx_init(void) +bool ffa_rxtx_spmc_init(void) { int32_t e; + bool ret =3D false; =20 /* Firmware not there or not supporting */ if ( !ffa_fw_supports_fid(FFA_RXTX_MAP_64) ) return false; =20 - ffa_rx =3D alloc_xenheap_pages(get_order_from_pages(FFA_RXTX_PAGE_COUN= T), 0); - if ( !ffa_rx ) - return false; + spin_lock(&ffa_spmc_rx_lock); + spin_lock(&ffa_spmc_tx_lock); + + ffa_spmc_rx =3D alloc_xenheap_pages( + get_order_from_pages(FFA_RXTX_PAGE_COUNT), 0); + if ( !ffa_spmc_rx ) + goto exit; =20 - ffa_tx =3D alloc_xenheap_pages(get_order_from_pages(FFA_RXTX_PAGE_COUN= T), 0); - if ( !ffa_tx ) - goto err; + ffa_spmc_tx =3D alloc_xenheap_pages( + get_order_from_pages(FFA_RXTX_PAGE_COUNT), 0); + if ( !ffa_spmc_tx ) + goto exit; =20 - e =3D ffa_rxtx_map(__pa(ffa_tx), __pa(ffa_rx), FFA_RXTX_PAGE_COUNT); + e =3D ffa_rxtx_map(__pa(ffa_spmc_tx), __pa(ffa_spmc_rx), + FFA_RXTX_PAGE_COUNT); if ( e ) - goto err; + goto exit; =20 - return true; + ret =3D true; =20 -err: - ffa_rxtx_destroy(); +exit: + spin_unlock(&ffa_spmc_tx_lock); + spin_unlock(&ffa_spmc_rx_lock); =20 - return false; + if ( !ret ) + ffa_rxtx_spmc_destroy(); + + return ret; } diff --git a/xen/arch/arm/tee/ffa_shm.c b/xen/arch/arm/tee/ffa_shm.c index d628c1b70609..b9022797c3bf 100644 --- a/xen/arch/arm/tee/ffa_shm.c +++ b/xen/arch/arm/tee/ffa_shm.c @@ -286,9 +286,8 @@ static void init_range(struct ffa_address_range *addr_r= ange, } =20 /* - * This function uses the ffa_tx buffer to transmit the memory transaction - * descriptor. The function depends ffa_tx_buffer_lock to be used to guard - * the buffer from concurrent use. + * This function uses the ffa_spmc tx buffer to transmit the memory transa= ction + * descriptor. */ static int share_shm(struct ffa_shm_mem *shm) { @@ -298,17 +297,22 @@ static int share_shm(struct ffa_shm_mem *shm) struct ffa_address_range *addr_range; struct ffa_mem_region *region_descr; const unsigned int region_count =3D 1; - void *buf =3D ffa_tx; uint32_t frag_len; uint32_t tot_len; paddr_t last_pa; unsigned int n; paddr_t pa; + int32_t ret; + void *buf; =20 - ASSERT(spin_is_locked(&ffa_tx_buffer_lock)); ASSERT(shm->page_count); =20 + buf =3D ffa_rxtx_spmc_tx_acquire(); + if ( !buf ) + return FFA_RET_NOT_SUPPORTED; + descr =3D buf; + memset(descr, 0, sizeof(*descr)); descr->sender_id =3D shm->sender_id; descr->handle =3D shm->handle; @@ -340,7 +344,10 @@ static int share_shm(struct ffa_shm_mem *shm) tot_len =3D ADDR_RANGE_OFFSET(descr->mem_access_count, region_count, region_descr->address_range_count); if ( tot_len > max_frag_len ) + { + ffa_rxtx_spmc_tx_release(); return FFA_RET_NOT_SUPPORTED; + } =20 addr_range =3D region_descr->address_range_array; frag_len =3D ADDR_RANGE_OFFSET(descr->mem_access_count, region_count, = 1); @@ -360,7 +367,11 @@ static int share_shm(struct ffa_shm_mem *shm) init_range(addr_range, pa); } =20 - return ffa_mem_share(tot_len, frag_len, 0, 0, &shm->handle); + ret =3D ffa_mem_share(tot_len, frag_len, 0, 0, &shm->handle); + + ffa_rxtx_spmc_tx_release(); + + return ret; } =20 static int read_mem_transaction(uint32_t ffa_vers, const void *buf, size_t= blen, @@ -578,10 +589,7 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) if ( ret ) goto out; =20 - /* Note that share_shm() uses our tx buffer */ - spin_lock(&ffa_tx_buffer_lock); ret =3D share_shm(shm); - spin_unlock(&ffa_tx_buffer_lock); if ( ret ) goto out; =20 --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 17642588001366.868716832723635; Thu, 27 Nov 2025 07:53:20 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174081.1499092 (Exim 4.92) (envelope-from ) id 1vOeIm-00057K-VZ; Thu, 27 Nov 2025 15:53:00 +0000 Received: by outflank-mailman (output) from mailman id 1174081.1499092; Thu, 27 Nov 2025 15:53:00 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIm-000577-RN; Thu, 27 Nov 2025 15:53:00 +0000 Received: by outflank-mailman (input) for mailman id 1174081; Thu, 27 Nov 2025 15:52:59 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIl-0004I5-Lf for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:52:59 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 24ac3a9f-cba9-11f0-980a-7dc792cee155; Thu, 27 Nov 2025 16:52:57 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8C12719F6; Thu, 27 Nov 2025 07:52:49 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A1BA73F73B; Thu, 27 Nov 2025 07:52:55 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 24ac3a9f-cba9-11f0-980a-7dc792cee155 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 05/10] xen/arm: ffa: use signed 32-bit status codes Date: Thu, 27 Nov 2025 16:51:36 +0100 Message-ID: <6e31745ff6473189d79a53cec2c29fdd41a22251.1764254975.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764258800836019200 Content-Type: text/plain; charset="utf-8" The FF-A spec defines return status values as signed 32-bit integers. Align the Xen mediator with this requirement by: - switching the FF-A helpers (ffa_handle_mem_reclaim(), partition info init, notification ops, dispatcher glue, etc.) to int32_t return types so callers cannot silently truncate negative values - masking SMCCC responses/exits in ffa_get_version(), ffa_get_ret_code() and ffa_set_regs_error() to 32 bits before storing them in guest registers - updating notifier, shared-memory reclaim, partition-info and dispatcher call sites to use the new prototypes so the entire FF-A path propagates spec-compliant 32-bit signed error codes While there, tidy up the FF-A notification helpers by using GENMASK(15, 0) for endpoint extraction and fix the secure-endpoint check in ffa_handle_notification_set() to apply the mask to the endpoint ID before calling FFA_ID_IS_SECURE(), instead of testing the wrong halfword of src_dst. Fixes: 911b305e7bdab ("xen/arm: ffa: Enable VM to VM without firmware") Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- xen/arch/arm/tee/ffa.c | 12 +++++++----- xen/arch/arm/tee/ffa_notif.c | 14 +++++++------- xen/arch/arm/tee/ffa_partinfo.c | 4 ++-- xen/arch/arm/tee/ffa_private.h | 21 +++++++++++---------- xen/arch/arm/tee/ffa_shm.c | 4 ++-- 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 4c1b9a4c3b48..7392bb6c3db9 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -129,12 +129,14 @@ static bool ffa_get_version(uint32_t *vers) .a1 =3D FFA_MY_VERSION, }; struct arm_smccc_1_2_regs resp; + int32_t ret; =20 arm_smccc_1_2_smc(&arg, &resp); - if ( resp.a0 =3D=3D FFA_RET_NOT_SUPPORTED ) + ret =3D resp.a0 & GENMASK_ULL(31, 0); + if ( ret =3D=3D FFA_RET_NOT_SUPPORTED ) return false; =20 - *vers =3D resp.a0; + *vers =3D resp.a0 & GENMASK_ULL(31, 0); =20 return true; } @@ -304,7 +306,7 @@ static bool ffa_handle_call(struct cpu_user_regs *regs) uint32_t fid =3D get_user_reg(regs, 0); struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; - int e; + int32_t e; =20 if ( !ctx ) return false; @@ -376,8 +378,8 @@ static bool ffa_handle_call(struct cpu_user_regs *regs) =20 default: gprintk(XENLOG_ERR, "ffa: unhandled fid 0x%x\n", fid); - ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); - return true; + e =3D FFA_RET_NOT_SUPPORTED; + break; } =20 if ( e ) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 86bef6b3b2ab..37b05747cd21 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -19,7 +19,7 @@ static bool __ro_after_init fw_notif_enabled; static unsigned int __ro_after_init notif_sri_irq; =20 -int ffa_handle_notification_bind(struct cpu_user_regs *regs) +int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; uint32_t src_dst =3D get_user_reg(regs, 1); @@ -27,7 +27,7 @@ int ffa_handle_notification_bind(struct cpu_user_regs *re= gs) uint32_t bitmap_lo =3D get_user_reg(regs, 3); uint32_t bitmap_hi =3D get_user_reg(regs, 4); =20 - if ( (src_dst & 0xFFFFU) !=3D ffa_get_vm_id(d) ) + if ( (src_dst & GENMASK(15, 0)) !=3D ffa_get_vm_id(d) ) return FFA_RET_INVALID_PARAMETERS; =20 if ( flags ) /* Only global notifications are supported */ @@ -40,14 +40,14 @@ int ffa_handle_notification_bind(struct cpu_user_regs *= regs) return FFA_RET_NOT_SUPPORTED; } =20 -int ffa_handle_notification_unbind(struct cpu_user_regs *regs) +int32_t ffa_handle_notification_unbind(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; uint32_t src_dst =3D get_user_reg(regs, 1); uint32_t bitmap_lo =3D get_user_reg(regs, 3); uint32_t bitmap_hi =3D get_user_reg(regs, 4); =20 - if ( (src_dst & 0xFFFFU) !=3D ffa_get_vm_id(d) ) + if ( (src_dst & GENMASK(15, 0)) !=3D ffa_get_vm_id(d) ) return FFA_RET_INVALID_PARAMETERS; =20 if ( FFA_ID_IS_SECURE(src_dst >> 16) && fw_notif_enabled ) @@ -106,7 +106,7 @@ void ffa_handle_notification_get(struct cpu_user_regs *= regs) return; } =20 - if ( (recv & 0xFFFFU) !=3D ffa_get_vm_id(d) ) + if ( (recv & GENMASK(15, 0)) !=3D ffa_get_vm_id(d) ) { ffa_set_regs_error(regs, FFA_RET_INVALID_PARAMETERS); return; @@ -162,7 +162,7 @@ void ffa_handle_notification_get(struct cpu_user_regs *= regs) ffa_set_regs(regs, FFA_SUCCESS_32, 0, w2, w3, w4, w5, w6, w7); } =20 -int ffa_handle_notification_set(struct cpu_user_regs *regs) +int32_t ffa_handle_notification_set(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; uint32_t src_dst =3D get_user_reg(regs, 1); @@ -173,7 +173,7 @@ int ffa_handle_notification_set(struct cpu_user_regs *r= egs) if ( (src_dst >> 16) !=3D ffa_get_vm_id(d) ) return FFA_RET_INVALID_PARAMETERS; =20 - if ( FFA_ID_IS_SECURE(src_dst >> 16) && fw_notif_enabled ) + if ( FFA_ID_IS_SECURE(src_dst & GENMASK(15, 0)) && fw_notif_enabled ) return ffa_simple_call(FFA_NOTIFICATION_SET, src_dst, flags, bitma= p_lo, bitmap_hi); =20 diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinf= o.c index 766b75dffb8c..3f4a779f4146 100644 --- a/xen/arch/arm/tee/ffa_partinfo.c +++ b/xen/arch/arm/tee/ffa_partinfo.c @@ -448,7 +448,7 @@ bool ffa_partinfo_init(void) bool ret =3D false; uint32_t fpi_size; uint32_t count; - int e; + int32_t e; void *spmc_rx; =20 if ( !ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) || @@ -515,7 +515,7 @@ static void vm_destroy_bitmap_init(struct ffa_ctx *ctx, } } =20 -int ffa_partinfo_domain_init(struct domain *d) +int32_t ffa_partinfo_domain_init(struct domain *d) { unsigned int count =3D BITS_TO_LONGS(subscr_vm_destroyed_count); struct ffa_ctx *ctx =3D d->arch.tee; diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index cd35c44b8986..9cae238f972c 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -31,9 +31,9 @@ =20 /* FFA_VERSION helpers */ #define FFA_VERSION_MAJOR_SHIFT 16U -#define FFA_VERSION_MAJOR_MASK 0x7FFFU +#define FFA_VERSION_MAJOR_MASK GENMASK(14, 0) #define FFA_VERSION_MINOR_SHIFT 0U -#define FFA_VERSION_MINOR_MASK 0xFFFFU +#define FFA_VERSION_MINOR_MASK GENMASK(15, 0) #define MAKE_FFA_VERSION(major, minor) \ ((((major) & FFA_VERSION_MAJOR_MASK) << FFA_VERSION_MAJOR_SHIFT) |= \ ((minor) & FFA_VERSION_MINOR_MASK)) @@ -414,10 +414,10 @@ extern atomic_t ffa_vm_count; =20 bool ffa_shm_domain_destroy(struct domain *d); void ffa_handle_mem_share(struct cpu_user_regs *regs); -int ffa_handle_mem_reclaim(uint64_t handle, uint32_t flags); +int32_t ffa_handle_mem_reclaim(uint64_t handle, uint32_t flags); =20 bool ffa_partinfo_init(void); -int ffa_partinfo_domain_init(struct domain *d); +int32_t ffa_partinfo_domain_init(struct domain *d); bool ffa_partinfo_domain_destroy(struct domain *d); void ffa_handle_partition_info_get(struct cpu_user_regs *regs); =20 @@ -441,11 +441,11 @@ void ffa_notif_init_interrupt(void); int ffa_notif_domain_init(struct domain *d); void ffa_notif_domain_destroy(struct domain *d); =20 -int ffa_handle_notification_bind(struct cpu_user_regs *regs); -int ffa_handle_notification_unbind(struct cpu_user_regs *regs); +int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs); +int32_t ffa_handle_notification_unbind(struct cpu_user_regs *regs); void ffa_handle_notification_info_get(struct cpu_user_regs *regs); void ffa_handle_notification_get(struct cpu_user_regs *regs); -int ffa_handle_notification_set(struct cpu_user_regs *regs); +int32_t ffa_handle_notification_set(struct cpu_user_regs *regs); =20 #ifdef CONFIG_FFA_VM_TO_VM void ffa_raise_rx_buffer_full(struct domain *d); @@ -511,9 +511,10 @@ static inline void ffa_set_regs(struct cpu_user_regs *= regs, register_t v0, } =20 static inline void ffa_set_regs_error(struct cpu_user_regs *regs, - uint32_t error_code) + int32_t error_code) { - ffa_set_regs(regs, FFA_ERROR, 0, error_code, 0, 0, 0, 0, 0); + ffa_set_regs(regs, FFA_ERROR, 0, error_code & GENMASK_ULL(31, 0), 0, 0= , 0, + 0, 0); } =20 static inline void ffa_set_regs_success(struct cpu_user_regs *regs, @@ -528,7 +529,7 @@ static inline int32_t ffa_get_ret_code(const struct arm= _smccc_1_2_regs *resp) { case FFA_ERROR: if ( resp->a2 ) - return resp->a2; + return resp->a2 & GENMASK_ULL(31, 0); else return FFA_RET_NOT_SUPPORTED; case FFA_SUCCESS_32: diff --git a/xen/arch/arm/tee/ffa_shm.c b/xen/arch/arm/tee/ffa_shm.c index b9022797c3bf..9db72269d1ea 100644 --- a/xen/arch/arm/tee/ffa_shm.c +++ b/xen/arch/arm/tee/ffa_shm.c @@ -624,14 +624,14 @@ static struct ffa_shm_mem *find_shm_mem(struct ffa_ct= x *ctx, uint64_t handle) return NULL; } =20 -int ffa_handle_mem_reclaim(uint64_t handle, uint32_t flags) +int32_t ffa_handle_mem_reclaim(uint64_t handle, uint32_t flags) { struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; struct ffa_shm_mem *shm; register_t handle_hi; register_t handle_lo; - int ret; + int32_t ret; =20 if ( !ffa_fw_supports_fid(FFA_MEM_RECLAIM) ) return FFA_RET_NOT_SUPPORTED; --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1764258808297882.744016478561; Thu, 27 Nov 2025 07:53:28 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174083.1499101 (Exim 4.92) (envelope-from ) id 1vOeIo-0005Nu-BS; Thu, 27 Nov 2025 15:53:02 +0000 Received: by outflank-mailman (output) from mailman id 1174083.1499101; Thu, 27 Nov 2025 15:53:02 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIo-0005Ng-7j; Thu, 27 Nov 2025 15:53:02 +0000 Received: by outflank-mailman (input) for mailman id 1174083; Thu, 27 Nov 2025 15:53:00 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIm-0003dB-Kf for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:53:00 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 25a56179-cba9-11f0-9d18-b5c5bf9af7f9; Thu, 27 Nov 2025 16:52:59 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 58BB1176A; Thu, 27 Nov 2025 07:52:51 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 652973F73B; Thu, 27 Nov 2025 07:52:57 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 25a56179-cba9-11f0-9d18-b5c5bf9af7f9 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 06/10] xen/arm: ffa: add UUID helpers for partition info Date: Thu, 27 Nov 2025 16:51:37 +0100 Message-ID: X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764258808856019200 Content-Type: text/plain; charset="utf-8" Introduce struct ffa_uuid together with nil/equality/set helpers, and use it end-to-end in the partition-info plumbing. The SP and VM enumeration paths now build UUIDs from the guest registers, call a new ffa_copy_info() helper and ensure non-nil UUID queries only return matching SP entries, relying on firmware UUID filtering. VM entries are skipped because we do not track per-VM UUIDs. Count requests and subscriber initialisation are updated accordingly so firmware is always called with an explicit UUID. This keeps count and listing requests aligned with the FF-A v1.1 rules while preserving the Linux compatibility workaround for v1.2 requesters. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- xen/arch/arm/tee/ffa_partinfo.c | 206 ++++++++++++++++++++------------ xen/arch/arm/tee/ffa_private.h | 21 ++++ 2 files changed, 152 insertions(+), 75 deletions(-) diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinf= o.c index 3f4a779f4146..4adbe2736c94 100644 --- a/xen/arch/arm/tee/ffa_partinfo.c +++ b/xen/arch/arm/tee/ffa_partinfo.c @@ -33,7 +33,7 @@ static uint16_t subscr_vm_created_count __read_mostly; static uint16_t *subscr_vm_destroyed __read_mostly; static uint16_t subscr_vm_destroyed_count __read_mostly; =20 -static int32_t ffa_partition_info_get(uint32_t *uuid, uint32_t flags, +static int32_t ffa_partition_info_get(struct ffa_uuid uuid, uint32_t flags, uint32_t *count, uint32_t *fpi_size) { struct arm_smccc_1_2_regs arg =3D { @@ -41,15 +41,12 @@ static int32_t ffa_partition_info_get(uint32_t *uuid, u= int32_t flags, .a5 =3D flags, }; struct arm_smccc_1_2_regs resp; - uint32_t ret; + int32_t ret; =20 - if ( uuid ) - { - arg.a1 =3D uuid[0]; - arg.a2 =3D uuid[1]; - arg.a3 =3D uuid[2]; - arg.a4 =3D uuid[3]; - } + arg.a1 =3D uuid.val[0] & 0xFFFFFFFFU; + arg.a2 =3D (uuid.val[0] >> 32) & 0xFFFFFFFFU; + arg.a3 =3D uuid.val[1] & 0xFFFFFFFFU; + arg.a4 =3D (uuid.val[1] >> 32) & 0xFFFFFFFFU; =20 arm_smccc_1_2_smc(&arg, &resp); =20 @@ -63,7 +60,26 @@ static int32_t ffa_partition_info_get(uint32_t *uuid, ui= nt32_t flags, return ret; } =20 -static int32_t ffa_get_sp_count(uint32_t *uuid, uint32_t *sp_count) +static int32_t ffa_copy_info(void **dst, void *dst_end, const void *src, + uint32_t dst_size, uint32_t src_size) +{ + uint8_t *pos =3D *dst; + uint8_t *end =3D dst_end; + + if ( pos > end - dst_size ) + return FFA_RET_NO_MEMORY; + + memcpy(pos, src, MIN(dst_size, src_size)); + + if ( dst_size > src_size ) + memset(pos + src_size, 0, dst_size - src_size); + + *dst =3D pos + dst_size; + + return FFA_RET_OK; +} + +static int32_t ffa_get_sp_count(struct ffa_uuid uuid, uint32_t *sp_count) { uint32_t src_size; =20 @@ -71,8 +87,8 @@ static int32_t ffa_get_sp_count(uint32_t *uuid, uint32_t = *sp_count) sp_count, &src_size); } =20 -static int32_t ffa_get_sp_partinfo(uint32_t *uuid, uint32_t *sp_count, - void *dst_buf, void *end_buf, +static int32_t ffa_get_sp_partinfo(struct ffa_uuid uuid, uint32_t *sp_coun= t, + void **dst_buf, void *end_buf, uint32_t dst_size) { int32_t ret; @@ -120,17 +136,18 @@ static int32_t ffa_get_sp_partinfo(uint32_t *uuid, ui= nt32_t *sp_count, /* filter out SP not following bit 15 convention if any */ if ( FFA_ID_IS_SECURE(fpi->id) ) { - if ( dst_buf > (end_buf - dst_size) ) - { - ret =3D FFA_RET_NO_MEMORY; - goto out; - } + /* + * If VM is 1.0 but firmware is 1.1 we could have several entr= ies + * with the same ID but different UUIDs. In this case the VM w= ill + * get a list with several time the same ID. + * This is a non-compliance to the specification but 1.0 VMs s= hould + * handle that on their own to simplify Xen implementation. + */ =20 - memcpy(dst_buf, src_buf, MIN(src_size, dst_size)); - if ( dst_size > src_size ) - memset(dst_buf + src_size, 0, dst_size - src_size); + ret =3D ffa_copy_info(dst_buf, end_buf, src_buf, dst_size, src= _size); + if ( ret ) + goto out; =20 - dst_buf +=3D dst_size; count++; } =20 @@ -144,69 +161,89 @@ out: return ret; } =20 -static int32_t ffa_get_vm_partinfo(uint32_t *vm_count, void *dst_buf, - void *end_buf, uint32_t dst_size) +static int32_t ffa_get_vm_partinfo(struct ffa_uuid uuid, uint32_t *vm_coun= t, + void **dst_buf, void *end_buf, + uint32_t dst_size) { struct ffa_ctx *curr_ctx =3D current->domain->arch.tee; struct ffa_ctx *dest_ctx; uint32_t count =3D 0; int32_t ret =3D FFA_RET_OK; + /* + * We do not have UUID info for VMs so use the 1.0 structure so that w= e set + * UUIDs to zero using memset + */ + struct ffa_partition_info_1_0 info; =20 /* - * There could potentially be a lot of VMs in the system and we could - * hold the CPU for long here. - * Right now there is no solution in FF-A specification to split - * the work in this case. - * TODO: Check how we could delay the work or have preemption checks. + * We do not have protocol UUIDs for VMs so if a request has non Nil U= UID + * we must return an empty list. */ - read_lock(&ffa_ctx_list_rwlock); - list_for_each_entry(dest_ctx, &ffa_ctx_head, ctx_list) + if ( !ffa_uuid_is_nil(uuid) ) + { + *vm_count =3D 0; + return FFA_RET_OK; + } + + /* + * Workaround for Linux FF-A Driver not accepting to have its own + * entry in the list before FF-A v1.2 was supported. + * This workaround is generally acceptable for other implementations + * as the specification was not completely clear on wether or not + * the requester endpoint information should be included or not + */ + if ( curr_ctx->guest_vers >=3D FFA_VERSION_1_2 ) + { + /* Add caller VM information */ + info.id =3D curr_ctx->ffa_id; + info.execution_context =3D curr_ctx->num_vcpus; + info.partition_properties =3D FFA_PART_VM_PROP; + if ( curr_ctx->is_64bit ) + info.partition_properties |=3D FFA_PART_PROP_AARCH64_STATE; + + ret =3D ffa_copy_info(dst_buf, end_buf, &info, dst_size, sizeof(in= fo)); + if ( ret ) + return ret; + + count++; + } + + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) { /* - * Do not include an entry for the caller VM as the spec is not - * clearly mandating it and it is not supported by Linux. + * There could potentially be a lot of VMs in the system and we co= uld + * hold the CPU for long here. + * Right now there is no solution in FF-A specification to split + * the work in this case. + * TODO: Check how we could delay the work or have preemption chec= ks. */ - if ( dest_ctx !=3D curr_ctx ) + read_lock(&ffa_ctx_list_rwlock); + list_for_each_entry(dest_ctx, &ffa_ctx_head, ctx_list) { - /* - * We do not have UUID info for VMs so use - * the 1.0 structure so that we set UUIDs to - * zero using memset - */ - struct ffa_partition_info_1_0 info; - - if ( dst_buf > (end_buf - dst_size) ) - { - ret =3D FFA_RET_NO_MEMORY; - goto out; - } + /* Ignore the caller entry as it was already added */ + if ( dest_ctx =3D=3D curr_ctx ) + continue; =20 - /* - * Context might has been removed since we go it or being remo= ved - * right now so we might return information for a VM not exist= ing - * anymore. This is acceptable as we return a view of the syst= em - * which could change at any time. - */ info.id =3D dest_ctx->ffa_id; info.execution_context =3D dest_ctx->num_vcpus; info.partition_properties =3D FFA_PART_VM_PROP; if ( dest_ctx->is_64bit ) info.partition_properties |=3D FFA_PART_PROP_AARCH64_STATE; =20 - memcpy(dst_buf, &info, MIN(sizeof(info), dst_size)); - - if ( dst_size > sizeof(info) ) - memset(dst_buf + sizeof(info), 0, - dst_size - sizeof(info)); + ret =3D ffa_copy_info(dst_buf, end_buf, &info, dst_size, + sizeof(info)); + if ( ret ) + { + read_unlock(&ffa_ctx_list_rwlock); + return ret; + } =20 - dst_buf +=3D dst_size; count++; } + read_unlock(&ffa_ctx_list_rwlock); } - *vm_count =3D count; =20 -out: - read_unlock(&ffa_ctx_list_rwlock); + *vm_count =3D count; =20 return ret; } @@ -217,16 +254,17 @@ void ffa_handle_partition_info_get(struct cpu_user_re= gs *regs) struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; uint32_t flags =3D get_user_reg(regs, 5); - uint32_t uuid[4] =3D { - get_user_reg(regs, 1), - get_user_reg(regs, 2), - get_user_reg(regs, 3), - get_user_reg(regs, 4), - }; + struct ffa_uuid uuid; uint32_t dst_size =3D 0; void *dst_buf, *end_buf; uint32_t ffa_vm_count =3D 0, ffa_sp_count =3D 0; =20 + ffa_uuid_set(&uuid, + get_user_reg(regs, 1), + get_user_reg(regs, 2), + get_user_reg(regs, 3), + get_user_reg(regs, 4)); + /* * If the guest is v1.0, he does not get back the entry size so we must * use the v1.0 structure size in the destination buffer. @@ -259,10 +297,23 @@ void ffa_handle_partition_info_get(struct cpu_user_re= gs *regs) } =20 /* - * Do not count the caller VM as the spec is not clearly mandating= it - * and it is not supported by Linux. + * We do not have protocol UUIDs for VMs so if a request has non N= il + * UUID we must return a vm_count of 0 */ - ffa_vm_count =3D get_ffa_vm_count() - 1; + if ( ffa_uuid_is_nil(uuid) ) + { + ffa_vm_count =3D get_ffa_vm_count(); + + /* + * Workaround for Linux FF-A Driver not accepting to have its = own + * entry in the list before FF-A v1.2 was supported. + * This workaround is generally acceptable for other implement= ations + * as the specification was not completely clear on wether or = not + * the requester endpoint information should be included or not + */ + if ( ctx->guest_vers < FFA_VERSION_1_2 ) + ffa_vm_count -=3D 1; + } =20 goto out; } @@ -290,17 +341,15 @@ void ffa_handle_partition_info_get(struct cpu_user_re= gs *regs) =20 if ( ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) ) { - ret =3D ffa_get_sp_partinfo(uuid, &ffa_sp_count, dst_buf, end_buf, + ret =3D ffa_get_sp_partinfo(uuid, &ffa_sp_count, &dst_buf, end_buf, dst_size); =20 if ( ret ) goto out_rx_release; - - dst_buf +=3D ffa_sp_count * dst_size; } =20 - if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) - ret =3D ffa_get_vm_partinfo(&ffa_vm_count, dst_buf, end_buf, dst_s= ize); + ret =3D ffa_get_vm_partinfo(uuid, &ffa_vm_count, &dst_buf, end_buf, + dst_size); =20 out_rx_release: if ( ret ) @@ -309,7 +358,13 @@ out: if ( ret ) ffa_set_regs_error(regs, ret); else + { + /* Size should be 0 on count request and was not supported in 1.0 = */ + if ( flags || ctx->guest_vers =3D=3D FFA_VERSION_1_0 ) + dst_size =3D 0; + ffa_set_regs_success(regs, ffa_sp_count + ffa_vm_count, dst_size); + } } =20 static int32_t ffa_direct_req_send_vm(uint16_t sp_id, uint16_t vm_id, @@ -450,6 +505,7 @@ bool ffa_partinfo_init(void) uint32_t count; int32_t e; void *spmc_rx; + struct ffa_uuid nil_uuid =3D { .val =3D { 0ULL, 0ULL } }; =20 if ( !ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) || !ffa_fw_supports_fid(FFA_MSG_SEND_DIRECT_REQ_32)) @@ -459,7 +515,7 @@ bool ffa_partinfo_init(void) if (!spmc_rx) return false; =20 - e =3D ffa_partition_info_get(NULL, 0, &count, &fpi_size); + e =3D ffa_partition_info_get(nil_uuid, 0, &count, &fpi_size); if ( e ) { printk(XENLOG_ERR "ffa: Failed to get list of SPs: %d\n", e); diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 9cae238f972c..c1dac09c75ca 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -306,6 +306,10 @@ struct ffa_mem_region { struct ffa_address_range address_range_array[]; }; =20 +struct ffa_uuid { + uint64_t val[2]; +}; + struct ffa_ctx_notif { /* * True if domain is reported by FFA_NOTIFICATION_INFO_GET to have @@ -567,4 +571,21 @@ static inline bool ffa_fw_supports_fid(uint32_t fid) return test_bit(FFA_ABI_BITNUM(fid), ffa_fw_abi_supported); } =20 +static inline bool ffa_uuid_is_nil(struct ffa_uuid id) +{ + return id.val[0] =3D=3D 0 && id.val[1] =3D=3D 0; +} + +static inline bool ffa_uuid_equal(struct ffa_uuid id1, struct ffa_uuid id2) +{ + return id1.val[0] =3D=3D id2.val[0] && id1.val[1] =3D=3D id2.val[1]; +} + +static inline void ffa_uuid_set(struct ffa_uuid *id, uint32_t val0, + uint32_t val1, uint32_t val2, uint32_t val= 3) +{ + id->val[0] =3D ((uint64_t)val1 << 32U) | val0; + id->val[1] =3D ((uint64_t)val3 << 32U) | val2; +} + #endif /*__FFA_PRIVATE_H__*/ --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1764258807223757.4268755977514; Thu, 27 Nov 2025 07:53:27 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174084.1499111 (Exim 4.92) (envelope-from ) id 1vOeIp-0005dU-K6; Thu, 27 Nov 2025 15:53:03 +0000 Received: by outflank-mailman (output) from mailman id 1174084.1499111; Thu, 27 Nov 2025 15:53:03 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIp-0005ct-GP; Thu, 27 Nov 2025 15:53:03 +0000 Received: by outflank-mailman (input) for mailman id 1174084; Thu, 27 Nov 2025 15:53:01 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIn-0003dB-L0 for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:53:01 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 26a60dab-cba9-11f0-9d18-b5c5bf9af7f9; Thu, 27 Nov 2025 16:53:01 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id DF745176C; Thu, 27 Nov 2025 07:52:52 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 28A2C3F73B; Thu, 27 Nov 2025 07:52:58 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 26a60dab-cba9-11f0-9d18-b5c5bf9af7f9 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 07/10] xen/arm: ffa: refactor direct requests via RUN helper Date: Thu, 27 Nov 2025 16:51:38 +0100 Message-ID: X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764258808882019200 Content-Type: text/plain; charset="utf-8" Share the SMCCC plumbing used by SEND_DIRECT and RUN via a common ffa_finish_direct_req_run() helper so canonical success and error cases are handled in one place. The dispatcher now routes FFA_RUN through ffa_handle_run(), and direct requests bail out early if a guest targets itself or a non-secure endpoint. This simplifies the direct path and prepares the mediator for the wider v1.2 register ABI. Signed-off-by: Bertrand Marquis --- xen/arch/arm/tee/ffa.c | 3 + xen/arch/arm/tee/ffa_msg.c | 111 ++++++++++++++++++++++++--------- xen/arch/arm/tee/ffa_private.h | 1 + 3 files changed, 84 insertions(+), 31 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 7392bb6c3db9..92cb6ad7ec97 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -347,6 +347,9 @@ static bool ffa_handle_call(struct cpu_user_regs *regs) case FFA_MSG_SEND_DIRECT_REQ_64: ffa_handle_msg_send_direct_req(regs, fid); return true; + case FFA_RUN: + ffa_handle_run(regs, fid); + return true; case FFA_MSG_SEND2: e =3D ffa_handle_msg_send2(regs); break; diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c index dec429cbf160..8bb4bd93f724 100644 --- a/xen/arch/arm/tee/ffa_msg.c +++ b/xen/arch/arm/tee/ffa_msg.c @@ -21,42 +21,74 @@ struct ffa_part_msg_rxtx { uint32_t msg_size; }; =20 -void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t f= id) +static void ffa_finish_direct_req_run(struct cpu_user_regs *regs, + struct arm_smccc_1_2_regs *req) { - struct arm_smccc_1_2_regs arg =3D { .a0 =3D fid, }; struct arm_smccc_1_2_regs resp =3D { }; - struct domain *d =3D current->domain; - uint32_t src_dst; uint64_t mask; =20 - if ( smccc_is_conv_64(fid) ) + arm_smccc_1_2_smc(req, &resp); + + switch ( resp.a0 ) + { + case FFA_ERROR: + case FFA_SUCCESS_32: + case FFA_SUCCESS_64: + case FFA_MSG_SEND_DIRECT_RESP_32: + case FFA_MSG_SEND_DIRECT_RESP_64: + case FFA_MSG_YIELD: + case FFA_INTERRUPT: + break; + default: + /* Bad fid, report back to the caller. */ + ffa_set_regs_error(regs, FFA_RET_ABORTED); + return; + } + + if ( smccc_is_conv_64(resp.a0) ) mask =3D GENMASK_ULL(63, 0); else mask =3D GENMASK_ULL(31, 0); =20 + ffa_set_regs(regs, resp.a0, resp.a1 & mask, resp.a2 & mask, resp.a3 & = mask, + resp.a4 & mask, resp.a5 & mask, resp.a6 & mask, + resp.a7 & mask); +} + +void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t f= id) +{ + struct arm_smccc_1_2_regs arg =3D { .a0 =3D fid, }; + struct domain *d =3D current->domain; + uint32_t src_dst; + uint64_t mask; + int32_t ret; + if ( !ffa_fw_supports_fid(fid) ) { - resp.a0 =3D FFA_ERROR; - resp.a2 =3D FFA_RET_NOT_SUPPORTED; + ret =3D FFA_RET_NOT_SUPPORTED; goto out; } =20 src_dst =3D get_user_reg(regs, 1); - if ( (src_dst >> 16) !=3D ffa_get_vm_id(d) ) + if ( (src_dst >> 16) !=3D ffa_get_vm_id(d) || + (src_dst & GENMASK(15,0)) =3D=3D ffa_get_vm_id(d) ) { - resp.a0 =3D FFA_ERROR; - resp.a2 =3D FFA_RET_INVALID_PARAMETERS; + ret =3D FFA_RET_INVALID_PARAMETERS; goto out; } =20 /* we do not support direct messages to VMs */ if ( !FFA_ID_IS_SECURE(src_dst & GENMASK(15,0)) ) { - resp.a0 =3D FFA_ERROR; - resp.a2 =3D FFA_RET_NOT_SUPPORTED; + ret =3D FFA_RET_NOT_SUPPORTED; goto out; } =20 + if ( smccc_is_conv_64(fid) ) + mask =3D GENMASK_ULL(63, 0); + else + mask =3D GENMASK_ULL(31, 0); + arg.a1 =3D src_dst; arg.a2 =3D get_user_reg(regs, 2) & mask; arg.a3 =3D get_user_reg(regs, 3) & mask; @@ -65,27 +97,11 @@ void ffa_handle_msg_send_direct_req(struct cpu_user_reg= s *regs, uint32_t fid) arg.a6 =3D get_user_reg(regs, 6) & mask; arg.a7 =3D get_user_reg(regs, 7) & mask; =20 - arm_smccc_1_2_smc(&arg, &resp); - switch ( resp.a0 ) - { - case FFA_ERROR: - case FFA_SUCCESS_32: - case FFA_SUCCESS_64: - case FFA_MSG_SEND_DIRECT_RESP_32: - case FFA_MSG_SEND_DIRECT_RESP_64: - break; - default: - /* Bad fid, report back to the caller. */ - memset(&resp, 0, sizeof(resp)); - resp.a0 =3D FFA_ERROR; - resp.a1 =3D src_dst; - resp.a2 =3D FFA_RET_ABORTED; - } + ffa_finish_direct_req_run(regs, &arg); + return; =20 out: - ffa_set_regs(regs, resp.a0, resp.a1 & mask, resp.a2 & mask, resp.a3 & = mask, - resp.a4 & mask, resp.a5 & mask, resp.a6 & mask, - resp.a7 & mask); + ffa_set_regs_error(regs, ret); } =20 static int32_t ffa_msg_send2_vm(uint16_t dst_id, const void *src_buf, @@ -215,3 +231,36 @@ out: spin_unlock(&src_ctx->tx_lock); return ret; } + +void ffa_handle_run(struct cpu_user_regs *regs, uint32_t fid) +{ + struct arm_smccc_1_2_regs arg =3D { .a0 =3D fid, }; + uint32_t dst =3D get_user_reg(regs, 1); + int32_t ret; + + if ( !ffa_fw_supports_fid(fid) ) + { + ret =3D FFA_RET_NOT_SUPPORTED; + goto out; + } + + /* + * We do not support FFA_RUN to VMs. + * Destination endpoint ID is in bits [31:16], bits[15:0] contain the + * vCPU ID. + */ + if ( !FFA_ID_IS_SECURE(dst >> 16) ) + { + ret =3D FFA_RET_NOT_SUPPORTED; + goto out; + } + + arg.a1 =3D dst; + + ffa_finish_direct_req_run(regs, &arg); + + return; + +out: + ffa_set_regs_error(regs, ret); +} diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index c1dac09c75ca..a9a03c7c5d71 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -461,6 +461,7 @@ static inline void ffa_raise_rx_buffer_full(struct doma= in *d) =20 void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t f= id); int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs); +void ffa_handle_run(struct cpu_user_regs *regs, uint32_t fid); =20 #ifdef CONFIG_FFA_VM_TO_VM static inline uint16_t get_ffa_vm_count(void) --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1764259342165239.1493210430391; Thu, 27 Nov 2025 08:02:22 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174143.1499133 (Exim 4.92) (envelope-from ) id 1vOeQy-0001ZW-UD; Thu, 27 Nov 2025 16:01:28 +0000 Received: by outflank-mailman (output) from mailman id 1174143.1499133; Thu, 27 Nov 2025 16:01:28 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeQy-0001ZP-Ps; Thu, 27 Nov 2025 16:01:28 +0000 Received: by outflank-mailman (input) for mailman id 1174143; Thu, 27 Nov 2025 16:01:27 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIp-0003dB-LT for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:53:03 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 2795c4cd-cba9-11f0-9d18-b5c5bf9af7f9; Thu, 27 Nov 2025 16:53:02 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 761D219F6; Thu, 27 Nov 2025 07:52:54 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B0A853F73B; Thu, 27 Nov 2025 07:53:00 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 2795c4cd-cba9-11f0-9d18-b5c5bf9af7f9 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 08/10] xen/arm: ffa: add v1.2 SEND2 header layout Date: Thu, 27 Nov 2025 16:51:39 +0100 Message-ID: <769c7ad291abe47d7991b878b131f9b31d4f0954.1764254975.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764259343231019200 Content-Type: text/plain; charset="utf-8" Teach the SEND2 path about the distinct FF-A v1.1 and v1.2 RX/TX header layouts so we can propagate the 128-bit UUIDs introduced in v1.2. VM-to-VM SEND2 calls now build the larger v1.2 header, zeroing the UUID fields for v1.1 senders, and the dispatcher validates messages using the v1.1 header layout to keep legacy guests working. Signed-off-by: Bertrand Marquis --- xen/arch/arm/tee/ffa_msg.c | 55 +++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c index 8bb4bd93f724..472bfad79dd3 100644 --- a/xen/arch/arm/tee/ffa_msg.c +++ b/xen/arch/arm/tee/ffa_msg.c @@ -13,7 +13,7 @@ #include "ffa_private.h" =20 /* Encoding of partition message in RX/TX buffer */ -struct ffa_part_msg_rxtx { +struct ffa_part_msg_rxtx_1_1 { uint32_t flags; uint32_t reserved; uint32_t msg_offset; @@ -21,6 +21,16 @@ struct ffa_part_msg_rxtx { uint32_t msg_size; }; =20 +struct ffa_part_msg_rxtx_1_2 { + uint32_t flags; + uint32_t reserved; + uint32_t msg_offset; + uint32_t send_recv_id; + uint32_t msg_size; + uint32_t reserved2; + uint64_t uuid[2]; +}; + static void ffa_finish_direct_req_run(struct cpu_user_regs *regs, struct arm_smccc_1_2_regs *req) { @@ -104,12 +114,12 @@ out: ffa_set_regs_error(regs, ret); } =20 -static int32_t ffa_msg_send2_vm(uint16_t dst_id, const void *src_buf, - struct ffa_part_msg_rxtx *src_msg) +static int32_t ffa_msg_send2_vm(struct ffa_ctx *src_ctx, uint16_t dst_id, + struct ffa_part_msg_rxtx_1_2 *src_msg) { struct domain *dst_d; struct ffa_ctx *dst_ctx; - struct ffa_part_msg_rxtx *dst_msg; + struct ffa_part_msg_rxtx_1_2 *dst_msg; int err; int32_t ret; =20 @@ -142,7 +152,7 @@ static int32_t ffa_msg_send2_vm(uint16_t dst_id, const = void *src_buf, =20 /* we need to have enough space in the destination buffer */ if ( (dst_ctx->page_count * FFA_PAGE_SIZE - - sizeof(struct ffa_part_msg_rxtx)) < src_msg->msg_size ) + sizeof(struct ffa_part_msg_rxtx_1_2)) < src_msg->msg_size ) { ret =3D FFA_RET_NO_MEMORY; ffa_rx_release(dst_d); @@ -154,12 +164,24 @@ static int32_t ffa_msg_send2_vm(uint16_t dst_id, cons= t void *src_buf, /* prepare destination header */ dst_msg->flags =3D 0; dst_msg->reserved =3D 0; - dst_msg->msg_offset =3D sizeof(struct ffa_part_msg_rxtx); + dst_msg->msg_offset =3D sizeof(struct ffa_part_msg_rxtx_1_2); dst_msg->send_recv_id =3D src_msg->send_recv_id; dst_msg->msg_size =3D src_msg->msg_size; + dst_msg->reserved2 =3D 0; =20 - memcpy(dst_ctx->rx + sizeof(struct ffa_part_msg_rxtx), - src_buf + src_msg->msg_offset, src_msg->msg_size); + if ( src_ctx->guest_vers < FFA_VERSION_1_2 ) + { + dst_msg->uuid[0] =3D 0; + dst_msg->uuid[1] =3D 0; + } + else + { + dst_msg->uuid[0] =3D src_msg->uuid[0]; + dst_msg->uuid[1] =3D src_msg->uuid[1]; + } + + memcpy(dst_ctx->rx + sizeof(struct ffa_part_msg_rxtx_1_2), + src_ctx->tx + src_msg->msg_offset, src_msg->msg_size); =20 /* receiver rx buffer will be released by the receiver*/ =20 @@ -175,11 +197,17 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *re= gs) { struct domain *src_d =3D current->domain; struct ffa_ctx *src_ctx =3D src_d->arch.tee; - struct ffa_part_msg_rxtx src_msg; + /* + * src_msg is interpreted as v1.2 header, but: + * - for v1.1 guests, uuid[] is ignored and may contain payload bytes + * - for v1.2 guests, uuid[] carries the FF-A v1.2 UUID fields + */ + struct ffa_part_msg_rxtx_1_2 src_msg; uint16_t dst_id, src_id; int32_t ret; =20 - BUILD_BUG_ON(sizeof(struct ffa_part_msg_rxtx) >=3D FFA_PAGE_SIZE); + BUILD_BUG_ON(sizeof(struct ffa_part_msg_rxtx_1_1) >=3D FFA_PAGE_SIZE); + BUILD_BUG_ON(sizeof(struct ffa_part_msg_rxtx_1_2) >=3D FFA_PAGE_SIZE); =20 if ( !spin_trylock(&src_ctx->tx_lock) ) return FFA_RET_BUSY; @@ -190,14 +218,15 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *re= gs) src_id =3D src_msg.send_recv_id >> 16; dst_id =3D src_msg.send_recv_id & GENMASK(15,0); =20 - if ( src_id !=3D ffa_get_vm_id(src_d) ) + if ( src_id !=3D ffa_get_vm_id(src_d) || + dst_id =3D=3D ffa_get_vm_id(src_d) ) { ret =3D FFA_RET_INVALID_PARAMETERS; goto out; } =20 /* check source message fits in buffer */ - if ( src_msg.msg_offset < sizeof(struct ffa_part_msg_rxtx) || + if ( src_msg.msg_offset < sizeof(struct ffa_part_msg_rxtx_1_1) || src_msg.msg_size =3D=3D 0 || src_msg.msg_offset > src_ctx->page_count * FFA_PAGE_SIZE || src_msg.msg_size > (src_ctx->page_count * FFA_PAGE_SIZE - @@ -222,7 +251,7 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs) else if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) { /* Message for a VM */ - ret =3D ffa_msg_send2_vm(dst_id, src_ctx->tx, &src_msg); + ret =3D ffa_msg_send2_vm(src_ctx, dst_id, &src_msg); } else ret =3D FFA_RET_INVALID_PARAMETERS; --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1764259341254619.9272221650226; Thu, 27 Nov 2025 08:02:21 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174162.1499152 (Exim 4.92) (envelope-from ) id 1vOeRK-0002SN-Bz; Thu, 27 Nov 2025 16:01:50 +0000 Received: by outflank-mailman (output) from mailman id 1174162.1499152; Thu, 27 Nov 2025 16:01:50 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeRK-0002Rz-7G; Thu, 27 Nov 2025 16:01:50 +0000 Received: by outflank-mailman (input) for mailman id 1174162; Thu, 27 Nov 2025 16:01:48 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIr-0003dB-LP for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:53:05 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 28ae68e4-cba9-11f0-9d18-b5c5bf9af7f9; Thu, 27 Nov 2025 16:53:04 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 32E33176C; Thu, 27 Nov 2025 07:52:56 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4988E3F73B; Thu, 27 Nov 2025 07:53:02 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 28ae68e4-cba9-11f0-9d18-b5c5bf9af7f9 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 09/10] xen/arm: ffa: add MSG_SEND_DIRECT_REQ2 support Date: Thu, 27 Nov 2025 16:51:40 +0100 Message-ID: <06eae7d0caaf5379086d9a2efde8489448f14f39.1764254975.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764259343232019202 Extend the direct-request path so FF-A v1.2 guests can issue FFA_MSG_SEND_DIRECT_REQ2 and receive the matching RESP2. The handler now marshals registers x8=E2=80=93x17, and ffa_finish_direct_req_run() copies back the 17-register response used by FFA_MSG_SEND_DIRECT_RESP2. The new opcode is exposed via FFA_FEATURES and gated on guests that negotiated v1.2. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- xen/arch/arm/tee/ffa.c | 20 +++++++++++++++++++ xen/arch/arm/tee/ffa_msg.c | 39 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 92cb6ad7ec97..8b2f042287fc 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -234,6 +234,8 @@ out_continue: static void handle_features(struct cpu_user_regs *regs) { uint32_t a1 =3D get_user_reg(regs, 1); + struct domain *d =3D current->domain; + struct ffa_ctx *ctx =3D d->arch.tee; unsigned int n; =20 for ( n =3D 2; n <=3D 7; n++ ) @@ -262,6 +264,16 @@ static void handle_features(struct cpu_user_regs *regs) case FFA_MSG_SEND2: ffa_set_regs_success(regs, 0, 0); break; + case FFA_MSG_SEND_DIRECT_REQ2: + if ( ctx->guest_vers >=3D FFA_VERSION_1_2 ) + { + ffa_set_regs_success(regs, 0, 0); + } + else + { + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); + } + break; case FFA_MEM_SHARE_64: case FFA_MEM_SHARE_32: /* @@ -347,6 +359,14 @@ static bool ffa_handle_call(struct cpu_user_regs *regs) case FFA_MSG_SEND_DIRECT_REQ_64: ffa_handle_msg_send_direct_req(regs, fid); return true; + case FFA_MSG_SEND_DIRECT_REQ2: + if ( ctx->guest_vers >=3D FFA_VERSION_1_2 ) + { + ffa_handle_msg_send_direct_req(regs, fid); + return true; + } + e =3D FFA_RET_NOT_SUPPORTED; + break; case FFA_RUN: ffa_handle_run(regs, fid); return true; diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c index 472bfad79dd3..1f42aae1e0b6 100644 --- a/xen/arch/arm/tee/ffa_msg.c +++ b/xen/arch/arm/tee/ffa_msg.c @@ -49,6 +49,30 @@ static void ffa_finish_direct_req_run(struct cpu_user_re= gs *regs, case FFA_MSG_YIELD: case FFA_INTERRUPT: break; + case FFA_MSG_SEND_DIRECT_RESP2: + /* + * REQ2 / RESP2 use a 17-register payload (x1=E2=80=93x17). Copy a= ll of them + * back to the guest context. + */ + set_user_reg(regs, 0, resp.a0); + set_user_reg(regs, 1, resp.a1); + set_user_reg(regs, 2, resp.a2); + set_user_reg(regs, 3, resp.a3); + set_user_reg(regs, 4, resp.a4); + set_user_reg(regs, 5, resp.a5); + set_user_reg(regs, 6, resp.a6); + set_user_reg(regs, 7, resp.a7); + set_user_reg(regs, 8, resp.a8); + set_user_reg(regs, 9, resp.a9); + set_user_reg(regs, 10, resp.a10); + set_user_reg(regs, 11, resp.a11); + set_user_reg(regs, 12, resp.a12); + set_user_reg(regs, 13, resp.a13); + set_user_reg(regs, 14, resp.a14); + set_user_reg(regs, 15, resp.a15); + set_user_reg(regs, 16, resp.a16); + set_user_reg(regs, 17, resp.a17); + return; default: /* Bad fid, report back to the caller. */ ffa_set_regs_error(regs, FFA_RET_ABORTED); @@ -107,6 +131,21 @@ void ffa_handle_msg_send_direct_req(struct cpu_user_re= gs *regs, uint32_t fid) arg.a6 =3D get_user_reg(regs, 6) & mask; arg.a7 =3D get_user_reg(regs, 7) & mask; =20 + if ( fid =3D=3D FFA_MSG_SEND_DIRECT_REQ2 ) + { + /* 17 registers are used for REQ2 */ + arg.a8 =3D get_user_reg(regs, 8); + arg.a9 =3D get_user_reg(regs, 9); + arg.a10 =3D get_user_reg(regs, 10); + arg.a11 =3D get_user_reg(regs, 11); + arg.a12 =3D get_user_reg(regs, 12); + arg.a13 =3D get_user_reg(regs, 13); + arg.a14 =3D get_user_reg(regs, 14); + arg.a15 =3D get_user_reg(regs, 15); + arg.a16 =3D get_user_reg(regs, 16); + arg.a17 =3D get_user_reg(regs, 17); + } + ffa_finish_direct_req_run(regs, &arg); return; =20 --=20 2.51.2 From nobody Sun Dec 14 06:19:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1764258809489536.8489650661304; Thu, 27 Nov 2025 07:53:29 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1174086.1499123 (Exim 4.92) (envelope-from ) id 1vOeIu-0006DV-Uv; Thu, 27 Nov 2025 15:53:08 +0000 Received: by outflank-mailman (output) from mailman id 1174086.1499123; Thu, 27 Nov 2025 15:53:08 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIu-0006DI-Ow; Thu, 27 Nov 2025 15:53:08 +0000 Received: by outflank-mailman (input) for mailman id 1174086; Thu, 27 Nov 2025 15:53:07 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vOeIt-0004I5-U9 for xen-devel@lists.xenproject.org; Thu, 27 Nov 2025 15:53:07 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 29aa9348-cba9-11f0-980a-7dc792cee155; Thu, 27 Nov 2025 16:53:06 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E9435176A; Thu, 27 Nov 2025 07:52:57 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.89.94]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 026353F73B; Thu, 27 Nov 2025 07:53:03 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 29aa9348-cba9-11f0-980a-7dc792cee155 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 10/10] xen/arm: ffa: advertise FF-A v1.2 Date: Thu, 27 Nov 2025 16:51:41 +0100 Message-ID: <8ae9b12641301ecfafa7ddee3e60544d3fa45c40.1764254975.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1764258810813019200 Advertise RUN/YIELD/INTERRUPT via FFA_FEATURES now that the runtime helpers are in place, and expose the RX/TX MAP capacity field only once a guest has negotiated FF-A v1.2. While there, drop the stale include. To comply with the wider v1.2 register ABI, zero registers x8=E2=80=93x17 w= hen responding to a v1.2 VM. The dispatcher also rejects SMCCC64 calls from AArch32 guests. Finally, bump Xen's FF-A version to 1.2. Signed-off-by: Bertrand Marquis --- xen/arch/arm/tee/ffa.c | 25 ++++++++++++++++++++----- xen/arch/arm/tee/ffa_private.h | 28 +++++++++++++++++++--------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 8b2f042287fc..c8fe97856d06 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -24,9 +24,6 @@ * o FFA_MEM_DONATE_* and FFA_MEM_LEND_* - Used when tranferring ownership * or access of a memory region * o FFA_MSG_SEND2 and FFA_MSG_WAIT - Used for indirect messaging - * o FFA_MSG_YIELD - * o FFA_INTERRUPT - Used to report preemption - * o FFA_RUN * * Limitations in the implemented FF-A interfaces: * o FFA_RXTX_MAP_*: @@ -68,7 +65,6 @@ #include #include #include -#include #include =20 #include "ffa_private.h" @@ -262,6 +258,9 @@ static void handle_features(struct cpu_user_regs *regs) case FFA_MSG_SEND_DIRECT_REQ_32: case FFA_MSG_SEND_DIRECT_REQ_64: case FFA_MSG_SEND2: + case FFA_RUN: + case FFA_INTERRUPT: + case FFA_MSG_YIELD: ffa_set_regs_success(regs, 0, 0); break; case FFA_MSG_SEND_DIRECT_REQ2: @@ -290,7 +289,16 @@ static void handle_features(struct cpu_user_regs *regs) * differs from FFA_PAGE_SIZE (SZ_4K). */ BUILD_BUG_ON(PAGE_SIZE !=3D FFA_PAGE_SIZE); - ffa_set_regs_success(regs, 0, 0); + + /* + * From FFA v1.2, we can give the maximum number of pages we suppo= rt + * for the RX/TX buffers. + */ + if ( ctx->guest_vers < FFA_VERSION_1_2 ) + ffa_set_regs_success(regs, 0, 0); + else + ffa_set_regs_success(regs, FFA_MAX_RXTX_PAGE_COUNT << 16, 0); + break; case FFA_FEATURE_NOTIF_PEND_INTR: ffa_set_regs_success(regs, GUEST_FFA_NOTIF_PEND_INTR_ID, 0); @@ -323,6 +331,13 @@ static bool ffa_handle_call(struct cpu_user_regs *regs) if ( !ctx ) return false; =20 + if ( !is_64bit_domain(d) && smccc_is_conv_64(fid) ) + { + /* 32bit guests should only use 32bit convention calls */ + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); + return true; + } + /* A version must be negotiated first */ if ( !ctx->guest_vers_negotiated ) { diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index a9a03c7c5d71..6afca2ea07ef 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -53,7 +53,7 @@ * that particular guest or SP. */ #define FFA_MY_VERSION_MAJOR 1U -#define FFA_MY_VERSION_MINOR 1U +#define FFA_MY_VERSION_MINOR 2U #define FFA_MY_VERSION MAKE_FFA_VERSION(FFA_MY_VERSION_MAJOR, \ FFA_MY_VERSION_MINOR) =20 @@ -505,14 +505,24 @@ static inline void ffa_set_regs(struct cpu_user_regs = *regs, register_t v0, register_t v4, register_t v5, register_t v= 6, register_t v7) { - set_user_reg(regs, 0, v0); - set_user_reg(regs, 1, v1); - set_user_reg(regs, 2, v2); - set_user_reg(regs, 3, v3); - set_user_reg(regs, 4, v4); - set_user_reg(regs, 5, v5); - set_user_reg(regs, 6, v6); - set_user_reg(regs, 7, v7); + struct domain *d =3D current->domain; + struct ffa_ctx *ctx =3D d->arch.tee; + int i; + + set_user_reg(regs, 0, v0); + set_user_reg(regs, 1, v1); + set_user_reg(regs, 2, v2); + set_user_reg(regs, 3, v3); + set_user_reg(regs, 4, v4); + set_user_reg(regs, 5, v5); + set_user_reg(regs, 6, v6); + set_user_reg(regs, 7, v7); + + if ( ctx && ctx->guest_vers >=3D FFA_VERSION_1_2 && ctx->is_64bit ) + { + for (i =3D 8; i <=3D 17; i++) + set_user_reg(regs, i, 0); + } } =20 static inline void ffa_set_regs_error(struct cpu_user_regs *regs, --=20 2.51.2