From nobody Mon Apr 13 01:52:16 2026 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 1770830175309437.6837413912723; Wed, 11 Feb 2026 09:16:15 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1227992.1534356 (Exim 4.92) (envelope-from ) id 1vqDon-0004jN-9s; Wed, 11 Feb 2026 17:16:01 +0000 Received: by outflank-mailman (output) from mailman id 1227992.1534356; Wed, 11 Feb 2026 17:16:01 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vqDon-0004jG-79; Wed, 11 Feb 2026 17:16:01 +0000 Received: by outflank-mailman (input) for mailman id 1227992; Wed, 11 Feb 2026 17:15: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 1vqDol-0004U4-TD for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:15:59 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 54b4f057-076d-11f1-9ccf-f158ae23cfc8; Wed, 11 Feb 2026 18:15:58 +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 1DEE0339; Wed, 11 Feb 2026 09:15:51 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3A61E3F63F; Wed, 11 Feb 2026 09:15:56 -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: 54b4f057-076d-11f1-9ccf-f158ae23cfc8 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 01/12] xen/arm: ffa: Add endpoint lookup helper Date: Wed, 11 Feb 2026 18:15:25 +0100 Message-ID: <6f3d7c8a34c5bf9c0b860bbc86859aa658a6bc92.1770826406.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830176525154100 Content-Type: text/plain; charset="utf-8" Direct messaging paths duplicate endpoint validation and RCU domain lookup logic across multiple call sites, which makes the checks easy to drift and complicates maintenance. Introduce ffa_endpoint_domain_lookup() to centralize this logic. The helper validates the endpoint ID (rejecting ID 0 for the hypervisor), performs RCU domain lookup, ensures the domain is live and has an initialized FF-A context with a negotiated version, and returns the domain locked via RCU. Switch ffa_msg_send2_vm() to use the helper, replacing its open-coded validation sequence. This consolidates approximately 20 lines of duplicated checks into a single call. No functional changes. Reviewed-by: Jens Wiklander Signed-off-by: Bertrand Marquis --- Changes since v1: - add Jens R-b --- xen/arch/arm/tee/ffa.c | 45 ++++++++++++++++++++++++++++++++++ xen/arch/arm/tee/ffa_msg.c | 24 +++--------------- xen/arch/arm/tee/ffa_private.h | 3 +++ 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index ed18e76080d0..6de2b9f8ac8e 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -433,6 +433,51 @@ static bool ffa_handle_call(struct cpu_user_regs *regs) return true; } =20 +/* + * Look up a domain by its FF-A endpoint ID and validate it's ready for FF= -A. + * Returns FFA_RET_OK on success with domain locked via RCU. + * Caller must call rcu_unlock_domain() when done. + * + * Validates: + * - endpoint_id is not 0 (the hypervisor) + * - domain exists and is live + * - domain has FF-A context initialized + * - domain has negotiated an FF-A version + */ +int32_t ffa_endpoint_domain_lookup(uint16_t endpoint_id, struct domain **d= _out, + struct ffa_ctx **ctx_out) +{ + struct domain *d; + struct ffa_ctx *ctx; + int err; + + if ( endpoint_id =3D=3D 0 ) + return FFA_RET_INVALID_PARAMETERS; + + err =3D rcu_lock_live_remote_domain_by_id(endpoint_id - 1, &d); + if ( err ) + return FFA_RET_INVALID_PARAMETERS; + + if ( !d->arch.tee ) + { + rcu_unlock_domain(d); + return FFA_RET_INVALID_PARAMETERS; + } + + ctx =3D d->arch.tee; + if ( !ACCESS_ONCE(ctx->guest_vers) ) + { + rcu_unlock_domain(d); + return FFA_RET_INVALID_PARAMETERS; + } + + *d_out =3D d; + if ( ctx_out ) + *ctx_out =3D ctx; + + return FFA_RET_OK; +} + static int ffa_domain_init(struct domain *d) { struct ffa_ctx *ctx; diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c index 4e26596461a9..10856fddcbc4 100644 --- a/xen/arch/arm/tee/ffa_msg.c +++ b/xen/arch/arm/tee/ffa_msg.c @@ -161,30 +161,12 @@ static int32_t ffa_msg_send2_vm(uint16_t dst_id, cons= t void *src_buf, struct ffa_part_msg_rxtx_1_2 *dst_msg; void *rx_buf; size_t rx_size; - int err; int32_t ret; =20 - if ( dst_id =3D=3D 0 ) - /* FF-A ID 0 is the hypervisor, this is not valid */ - return FFA_RET_INVALID_PARAMETERS; - /* This is also checking that dest is not src */ - err =3D rcu_lock_live_remote_domain_by_id(dst_id - 1, &dst_d); - if ( err ) - return FFA_RET_INVALID_PARAMETERS; - - if ( dst_d->arch.tee =3D=3D NULL ) - { - ret =3D FFA_RET_INVALID_PARAMETERS; - goto out_unlock; - } - - dst_ctx =3D dst_d->arch.tee; - if ( !ACCESS_ONCE(dst_ctx->guest_vers) ) - { - ret =3D FFA_RET_INVALID_PARAMETERS; - goto out_unlock; - } + ret =3D ffa_endpoint_domain_lookup(dst_id, &dst_d, &dst_ctx); + if ( ret ) + return ret; =20 /* This also checks that destination has set a Rx buffer */ ret =3D ffa_rx_acquire(dst_ctx , &rx_buf, &rx_size); diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 282c105f3bce..cd7ecabc7eff 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -437,6 +437,9 @@ 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 +int32_t ffa_endpoint_domain_lookup(uint16_t endpoint_id, struct domain **d= _out, + struct ffa_ctx **ctx_out); + bool ffa_rxtx_spmc_init(void); void ffa_rxtx_spmc_destroy(void); void *ffa_rxtx_spmc_rx_acquire(void); --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830179311906.9306786719629; Wed, 11 Feb 2026 09:16:19 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1227993.1534366 (Exim 4.92) (envelope-from ) id 1vqDop-0004yg-Gz; Wed, 11 Feb 2026 17:16:03 +0000 Received: by outflank-mailman (output) from mailman id 1227993.1534366; Wed, 11 Feb 2026 17:16: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 1vqDop-0004yP-DP; Wed, 11 Feb 2026 17:16:03 +0000 Received: by outflank-mailman (input) for mailman id 1227993; Wed, 11 Feb 2026 17:16:01 +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 1vqDon-0004U4-AV for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:01 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 55995b5d-076d-11f1-9ccf-f158ae23cfc8; Wed, 11 Feb 2026 18:15: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 A21EB497; Wed, 11 Feb 2026 09:15:52 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BB1083F63F; Wed, 11 Feb 2026 09:15: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: 55995b5d-076d-11f1-9ccf-f158ae23cfc8 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 02/12] xen/arm: ffa: Fix MEM_SHARE NS attribute handling Date: Wed, 11 Feb 2026 18:15:26 +0100 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830179755158502 Content-Type: text/plain; charset="utf-8" The FF-A memory attribute encoding is currently a literal value (0x2f), which makes reviews and validation harder. In addition, MEM_SHARE accepts the NS (non-secure) attribute bit even though the normal world must not set it according to FF-A specification. Introduce named attribute bit masks and express FFA_NORMAL_MEM_REG_ATTR in terms of them for clarity. Reject MEM_SHARE descriptors with the NS bit set, returning INVALID_PARAMETERS to match FF-A v1.1 rules that prohibit normal world from setting this bit. Functional impact: MEM_SHARE now rejects descriptors with NS bit set with the right error code, INVALID_PARAMETER. Reviewed-by: Jens Wiklander Signed-off-by: Bertrand Marquis --- Changes since v1: - Fix functional impact to mention the error code fix as the case was already filtered before but with a non spec compliant code - Add Jens R-b --- xen/arch/arm/tee/ffa_private.h | 17 ++++++++++++++++- xen/arch/arm/tee/ffa_shm.c | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index cd7ecabc7eff..b625f1c72914 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -129,11 +129,26 @@ #define FFA_HANDLE_HYP_FLAG BIT(63, ULL) #define FFA_HANDLE_INVALID 0xffffffffffffffffULL =20 +/* NS attribute was introduced in v1.1 */ +#define FFA_MEM_ATTR_NS BIT(6, U) + +#define FFA_MEM_ATTR_TYPE_DEV (1U << 3) +#define FFA_MEM_ATTR_TYPE_MEM (2U << 4) + +#define FFA_MEM_ATTR_NC (1U << 2) +#define FFA_MEM_ATTR_WB (3U << 2) + +#define FFA_MEM_ATTR_NON_SHARE (0U) +#define FFA_MEM_ATTR_OUT_SHARE (2U) +#define FFA_MEM_ATTR_INN_SHARE (3U) + /* * Memory attributes: Normal memory, Write-Back cacheable, Inner shareable * Defined in FF-A-1.1-REL0 Table 10.18 at page 175. */ -#define FFA_NORMAL_MEM_REG_ATTR 0x2fU +#define FFA_NORMAL_MEM_REG_ATTR (FFA_MEM_ATTR_TYPE_MEM | \ + FFA_MEM_ATTR_WB | \ + FFA_MEM_ATTR_INN_SHARE) /* * Memory access permissions: Read-write * Defined in FF-A-1.1-REL0 Table 10.15 at page 168. diff --git a/xen/arch/arm/tee/ffa_shm.c b/xen/arch/arm/tee/ffa_shm.c index 8282bacf85d3..90800e44a86a 100644 --- a/xen/arch/arm/tee/ffa_shm.c +++ b/xen/arch/arm/tee/ffa_shm.c @@ -512,6 +512,12 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) if ( ret ) goto out_unlock; =20 + if ( trans.mem_reg_attr & FFA_MEM_ATTR_NS ) + { + ret =3D FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + if ( trans.mem_reg_attr !=3D FFA_NORMAL_MEM_REG_ATTR ) { ret =3D FFA_RET_NOT_SUPPORTED; --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830180643126.4267133284568; Wed, 11 Feb 2026 09:16:20 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1227994.1534373 (Exim 4.92) (envelope-from ) id 1vqDop-000528-Ui; Wed, 11 Feb 2026 17:16:03 +0000 Received: by outflank-mailman (output) from mailman id 1227994.1534373; Wed, 11 Feb 2026 17:16: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 1vqDop-00051c-MS; Wed, 11 Feb 2026 17:16:03 +0000 Received: by outflank-mailman (input) for mailman id 1227994; Wed, 11 Feb 2026 17:16:02 +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 1vqDoo-0004tt-CH for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:02 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 56820d96-076d-11f1-b162-2bf370ae4941; Wed, 11 Feb 2026 18:16: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 307D1339; Wed, 11 Feb 2026 09:15:54 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4BBCE3F63F; Wed, 11 Feb 2026 09:15:59 -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: 56820d96-076d-11f1-b162-2bf370ae4941 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 03/12] xen/arm: ffa: Harden shm page parsing Date: Wed, 11 Feb 2026 18:15:27 +0100 Message-ID: <5189cce4272700616ff5a39870566abc72a1acd2.1770826406.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830182044158500 Content-Type: text/plain; charset="utf-8" get_shm_pages() uses unchecked address arithmetic and does not enforce alignment, so malformed descriptors can cause overflow or slip through validation. The reclaim path also repeats handle-to-shm-mem conversion in multiple places, duplicating error handling. Harden page parsing and reclaim handling: - add ffa_safe_addr_add() and use it to detect address overflows - enforce alignment checks in get_shm_pages() and return FF-A errors - introduce ffa_secure_reclaim() and use it for MEM_RECLAIM and teardown - simplify ffa_mem_share() argument handling and allow max page count While there rename ffa_mem_share to ffa_spmc_share and ffa_mem_reclaim to ffa_spmc_reclaim to have coherent names with other parts of ffa implementation for SMC wrappers to the SPMC. Functional impact: invalid or misaligned memory ranges now fail earlier with proper error codes; behavior for valid descriptors is unchanged. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v1: - rename ffa_mem_share to ffa_spmc_share and ffa_mem_reclaim to ffa_spmc_reclaim - remove unused frag_len --- xen/arch/arm/tee/ffa_private.h | 11 +++++++ xen/arch/arm/tee/ffa_shm.c | 60 ++++++++++++++++------------------ 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index b625f1c72914..58562d8e733c 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -632,4 +632,15 @@ static inline void ffa_uuid_set(struct ffa_uuid *id, u= int32_t val0, id->val[1] =3D ((uint64_t)val3 << 32U) | val2; } =20 +/* + * Common overflow-safe helper to verify that adding a number of pages to = an + * address will not wrap around. + */ +static inline bool ffa_safe_addr_add(uint64_t addr, uint64_t pages) +{ + uint64_t off =3D pages * FFA_PAGE_SIZE; + + return (off / FFA_PAGE_SIZE) =3D=3D pages && addr <=3D UINT64_MAX - of= f; +} + #endif /*__FFA_PRIVATE_H__*/ diff --git a/xen/arch/arm/tee/ffa_shm.c b/xen/arch/arm/tee/ffa_shm.c index 90800e44a86a..adc7e645a1c7 100644 --- a/xen/arch/arm/tee/ffa_shm.c +++ b/xen/arch/arm/tee/ffa_shm.c @@ -96,16 +96,14 @@ struct ffa_shm_mem { struct page_info *pages[]; }; =20 -static int32_t ffa_mem_share(uint32_t tot_len, uint32_t frag_len, - register_t addr, uint32_t pg_count, - uint64_t *handle) +static int32_t ffa_spmc_share(uint32_t tot_len, uint64_t *handle) { struct arm_smccc_1_2_regs arg =3D { .a0 =3D FFA_MEM_SHARE_64, .a1 =3D tot_len, - .a2 =3D frag_len, - .a3 =3D addr, - .a4 =3D pg_count, + .a2 =3D tot_len, + .a3 =3D 0, + .a4 =3D 0, }; struct arm_smccc_1_2_regs resp; =20 @@ -131,12 +129,16 @@ static int32_t ffa_mem_share(uint32_t tot_len, uint32= _t frag_len, } } =20 -static int32_t ffa_mem_reclaim(uint32_t handle_lo, uint32_t handle_hi, - uint32_t flags) +static int32_t ffa_spmc_reclaim(struct ffa_shm_mem *shm, uint32_t flags) { + register_t handle_hi; + register_t handle_lo; + if ( !ffa_fw_supports_fid(FFA_MEM_RECLAIM) ) return FFA_RET_NOT_SUPPORTED; =20 + uint64_to_regpair(&handle_hi, &handle_lo, shm->handle); + return ffa_simple_call(FFA_MEM_RECLAIM, handle_lo, handle_hi, flags, 0= ); } =20 @@ -145,7 +147,7 @@ static int32_t ffa_mem_reclaim(uint32_t handle_lo, uint= 32_t handle_hi, * this function fails then the caller is still expected to call * put_shm_pages() as a cleanup. */ -static int get_shm_pages(struct domain *d, struct ffa_shm_mem *shm, +static int32_t get_shm_pages(struct domain *d, struct ffa_shm_mem *shm, const struct ffa_address_range *range, uint32_t range_count) { @@ -156,17 +158,26 @@ static int get_shm_pages(struct domain *d, struct ffa= _shm_mem *shm, p2m_type_t t; uint64_t addr; uint64_t page_count; + uint64_t gaddr; =20 for ( n =3D 0; n < range_count; n++ ) { page_count =3D ACCESS_ONCE(range[n].page_count); addr =3D ACCESS_ONCE(range[n].address); + + if ( !IS_ALIGNED(addr, FFA_PAGE_SIZE) ) + return FFA_RET_INVALID_PARAMETERS; + for ( m =3D 0; m < page_count; m++ ) { if ( pg_idx >=3D shm->page_count ) return FFA_RET_INVALID_PARAMETERS; =20 - gfn =3D gaddr_to_gfn(addr + m * FFA_PAGE_SIZE); + if ( !ffa_safe_addr_add(addr, m) ) + return FFA_RET_INVALID_PARAMETERS; + + gaddr =3D addr + m * FFA_PAGE_SIZE; + gfn =3D gaddr_to_gfn(gaddr); shm->pages[pg_idx] =3D get_page_from_gfn(d, gfn_x(gfn), &t, P2M_ALLOC); if ( !shm->pages[pg_idx] ) @@ -180,7 +191,7 @@ static int get_shm_pages(struct domain *d, struct ffa_s= hm_mem *shm, =20 /* The ranges must add up */ if ( pg_idx < shm->page_count ) - return FFA_RET_INVALID_PARAMETERS; + return FFA_RET_INVALID_PARAMETERS; =20 return FFA_RET_OK; } @@ -198,15 +209,11 @@ static void put_shm_pages(struct ffa_shm_mem *shm) =20 static bool inc_ctx_shm_count(struct domain *d, struct ffa_ctx *ctx) { - bool ret =3D true; + bool ret =3D false; =20 spin_lock(&ctx->lock); =20 - if ( ctx->shm_count >=3D FFA_MAX_SHM_COUNT ) - { - ret =3D false; - } - else + if ( ctx->shm_count < FFA_MAX_SHM_COUNT ) { /* * If this is the first shm added, increase the domain reference @@ -217,6 +224,7 @@ static bool inc_ctx_shm_count(struct domain *d, struct = ffa_ctx *ctx) get_knownalive_domain(d); =20 ctx->shm_count++; + ret =3D true; } =20 spin_unlock(&ctx->lock); @@ -251,7 +259,7 @@ static struct ffa_shm_mem *alloc_ffa_shm_mem(struct dom= ain *d, struct ffa_ctx *ctx =3D d->arch.tee; struct ffa_shm_mem *shm; =20 - if ( page_count >=3D FFA_MAX_SHM_PAGE_COUNT ) + if ( page_count > FFA_MAX_SHM_PAGE_COUNT ) return NULL; if ( !inc_ctx_shm_count(d, ctx) ) return NULL; @@ -297,7 +305,6 @@ 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; - uint32_t frag_len; uint32_t tot_len; paddr_t last_pa; unsigned int n; @@ -350,7 +357,6 @@ static int share_shm(struct ffa_shm_mem *shm) } =20 addr_range =3D region_descr->address_range_array; - frag_len =3D ADDR_RANGE_OFFSET(descr->mem_access_count, region_count, = 1); last_pa =3D page_to_maddr(shm->pages[0]); init_range(addr_range, last_pa); for ( n =3D 1; n < shm->page_count; last_pa =3D pa, n++ ) @@ -362,12 +368,11 @@ static int share_shm(struct ffa_shm_mem *shm) continue; } =20 - frag_len +=3D sizeof(*addr_range); addr_range++; init_range(addr_range, pa); } =20 - ret =3D ffa_mem_share(tot_len, frag_len, 0, 0, &shm->handle); + ret =3D ffa_spmc_share(tot_len, &shm->handle); =20 out: ffa_rxtx_spmc_tx_release(); @@ -637,8 +642,6 @@ 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; int32_t ret; =20 if ( !ffa_fw_supports_fid(FFA_MEM_RECLAIM) ) @@ -652,8 +655,7 @@ int32_t ffa_handle_mem_reclaim(uint64_t handle, uint32_= t flags) if ( !shm ) return FFA_RET_INVALID_PARAMETERS; =20 - uint64_to_regpair(&handle_hi, &handle_lo, handle); - ret =3D ffa_mem_reclaim(handle_lo, handle_hi, flags); + ret =3D ffa_spmc_reclaim(shm, flags); =20 if ( ret ) { @@ -677,11 +679,7 @@ bool ffa_shm_domain_destroy(struct domain *d) =20 list_for_each_entry_safe(shm, tmp, &ctx->shm_list, list) { - register_t handle_hi; - register_t handle_lo; - - uint64_to_regpair(&handle_hi, &handle_lo, shm->handle); - res =3D ffa_mem_reclaim(handle_lo, handle_hi, 0); + res =3D ffa_spmc_reclaim(shm, 0); switch ( res ) { case FFA_RET_OK: printk(XENLOG_G_DEBUG "%pd: ffa: Reclaimed handle %#lx\n", --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830188199274.2876039535513; Wed, 11 Feb 2026 09:16:28 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1227996.1534386 (Exim 4.92) (envelope-from ) id 1vqDos-0005TZ-3a; Wed, 11 Feb 2026 17:16:06 +0000 Received: by outflank-mailman (output) from mailman id 1227996.1534386; Wed, 11 Feb 2026 17:16:06 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vqDos-0005TL-0k; Wed, 11 Feb 2026 17:16:06 +0000 Received: by outflank-mailman (input) for mailman id 1227996; Wed, 11 Feb 2026 17:16:04 +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 1vqDoq-0004U4-JT for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:04 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 576c8058-076d-11f1-9ccf-f158ae23cfc8; Wed, 11 Feb 2026 18:16: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 BBD89497; Wed, 11 Feb 2026 09:15:55 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D0E933F63F; Wed, 11 Feb 2026 09:16: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: 576c8058-076d-11f1-9ccf-f158ae23cfc8 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 04/12] xen/arm: ffa: Add FF-A 1.2 endpoint memory access descriptors Date: Wed, 11 Feb 2026 18:15:28 +0100 Message-ID: <8ddb97095d8f7f4140e660d2ff13ec2ccc82cc62.1770826406.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830189904158500 Content-Type: text/plain; charset="utf-8" FF-A 1.2 extends the endpoint memory access descriptor (EMAD) from 16 to 32 bytes, adding implementation-defined (IMPDEF) fields and reserved space. The MEM_SHARE path currently assumes the 1.1 EMAD size and rejects the 1.2 layout. Add FF-A 1.2 EMAD support to MEM_SHARE: - define ffa_mem_access_1_2 and store IMPDEF payload in ffa_shm_mem - emit 1.2 EMADs to the SPMC for FF-A 1.2 guests, forwarding IMPDEF - refactor header parsing into read_mem_transaction() for 1.0/1.1+ - detect EMAD format by mem_access_size to allow 1.1 on 1.2 guests Export ffa_fw_version to build memory descriptors according to the firware version to relay share memory requests and remove unused offset macros. Functional impact: MEM_SHARE supports FF-A 1.2 EMADs. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v1: - export ffa_fw_version and use it to construct descriptors according to firmware version - remove unused offset macros --- xen/arch/arm/tee/ffa.c | 2 +- xen/arch/arm/tee/ffa_private.h | 1 + xen/arch/arm/tee/ffa_shm.c | 121 +++++++++++++++++++++++---------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 6de2b9f8ac8e..23e1f408485b 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -70,7 +70,7 @@ #include "ffa_private.h" =20 /* Negotiated FF-A version to use with the SPMC, 0 if not there or support= ed */ -static uint32_t __ro_after_init ffa_fw_version; +uint32_t __ro_after_init ffa_fw_version; =20 /* Features supported by the SPMC or secure world when present */ DECLARE_BITMAP(ffa_fw_abi_supported, FFA_ABI_BITMAP_SIZE); diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 58562d8e733c..ccef2f7631f6 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -436,6 +436,7 @@ struct ffa_ctx { }; =20 extern DECLARE_BITMAP(ffa_fw_abi_supported, FFA_ABI_BITMAP_SIZE); +extern uint32_t __ro_after_init ffa_fw_version; =20 extern struct list_head ffa_ctx_head; extern rwlock_t ffa_ctx_list_rwlock; diff --git a/xen/arch/arm/tee/ffa_shm.c b/xen/arch/arm/tee/ffa_shm.c index adc7e645a1c7..070babce9627 100644 --- a/xen/arch/arm/tee/ffa_shm.c +++ b/xen/arch/arm/tee/ffa_shm.c @@ -30,6 +30,14 @@ struct ffa_mem_access { uint64_t reserved; }; =20 +/* Endpoint memory access descriptor (FF-A 1.2) */ +struct ffa_mem_access_1_2 { + struct ffa_mem_access_perm access_perm; + uint32_t region_offs; + uint8_t impdef[16]; + uint8_t reserved[8]; +}; + /* Lend, donate or share memory transaction descriptor */ struct ffa_mem_transaction_1_0 { uint16_t sender_id; @@ -55,25 +63,10 @@ struct ffa_mem_transaction_1_1 { uint8_t reserved[12]; }; =20 -/* Calculate offset of struct ffa_mem_access from start of buffer */ -#define MEM_ACCESS_OFFSET(access_idx) \ - ( sizeof(struct ffa_mem_transaction_1_1) + \ - ( access_idx ) * sizeof(struct ffa_mem_access) ) - -/* Calculate offset of struct ffa_mem_region from start of buffer */ -#define REGION_OFFSET(access_count, region_idx) \ - ( MEM_ACCESS_OFFSET(access_count) + \ - ( region_idx ) * sizeof(struct ffa_mem_region) ) - -/* Calculate offset of struct ffa_address_range from start of buffer */ -#define ADDR_RANGE_OFFSET(access_count, region_count, range_idx) \ - ( REGION_OFFSET(access_count, region_count) + \ - ( range_idx ) * sizeof(struct ffa_address_range) ) - /* * The parts needed from struct ffa_mem_transaction_1_0 or struct * ffa_mem_transaction_1_1, used to provide an abstraction of difference in - * data structures between version 1.0 and 1.1. This is just an internal + * data structures between version 1.0 and 1.2. This is just an internal * interface and can be changed without changing any ABI. */ struct ffa_mem_transaction_int { @@ -92,6 +85,8 @@ struct ffa_shm_mem { uint16_t sender_id; uint16_t ep_id; /* endpoint, the one lending */ uint64_t handle; /* FFA_HANDLE_INVALID if not set yet */ + /* Endpoint memory access descriptor IMPDEF value (FF-A 1.2). */ + uint64_t impdef[2]; unsigned int page_count; struct page_info *pages[]; }; @@ -297,16 +292,20 @@ static void init_range(struct ffa_address_range *addr= _range, * This function uses the ffa_spmc tx buffer to transmit the memory transa= ction * descriptor. */ -static int share_shm(struct ffa_shm_mem *shm) +static int share_shm(struct ffa_shm_mem *shm, uint32_t ffa_vers) { const uint32_t max_frag_len =3D FFA_RXTX_PAGE_COUNT * FFA_PAGE_SIZE; struct ffa_mem_access *mem_access_array; + struct ffa_mem_access_1_2 *mem_access_array_1_2; struct ffa_mem_transaction_1_1 *descr; struct ffa_address_range *addr_range; struct ffa_mem_region *region_descr; - const unsigned int region_count =3D 1; uint32_t tot_len; + uint32_t mem_access_size; + uint32_t mem_access_offs; + uint32_t region_offs; paddr_t last_pa; + uint32_t range_count; unsigned int n; paddr_t pa; int32_t ret; @@ -325,16 +324,35 @@ static int share_shm(struct ffa_shm_mem *shm) descr->handle =3D shm->handle; descr->mem_reg_attr =3D FFA_NORMAL_MEM_REG_ATTR; descr->mem_access_count =3D 1; - descr->mem_access_size =3D sizeof(*mem_access_array); - descr->mem_access_offs =3D MEM_ACCESS_OFFSET(0); + if ( ffa_vers >=3D FFA_VERSION_1_2 ) + mem_access_size =3D sizeof(struct ffa_mem_access_1_2); + else + mem_access_size =3D sizeof(struct ffa_mem_access); + mem_access_offs =3D sizeof(struct ffa_mem_transaction_1_1); + region_offs =3D mem_access_offs + mem_access_size; + descr->mem_access_size =3D mem_access_size; + descr->mem_access_offs =3D mem_access_offs; =20 - mem_access_array =3D buf + descr->mem_access_offs; - memset(mem_access_array, 0, sizeof(*mem_access_array)); - mem_access_array[0].access_perm.endpoint_id =3D shm->ep_id; - mem_access_array[0].access_perm.perm =3D FFA_MEM_ACC_RW; - mem_access_array[0].region_offs =3D REGION_OFFSET(descr->mem_access_co= unt, 0); + if ( ffa_vers >=3D FFA_VERSION_1_2 ) + { + mem_access_array_1_2 =3D buf + mem_access_offs; + memset(mem_access_array_1_2, 0, sizeof(*mem_access_array_1_2)); + mem_access_array_1_2[0].access_perm.endpoint_id =3D shm->ep_id; + mem_access_array_1_2[0].access_perm.perm =3D FFA_MEM_ACC_RW; + mem_access_array_1_2[0].region_offs =3D region_offs; + memcpy(mem_access_array_1_2[0].impdef, shm->impdef, + sizeof(mem_access_array_1_2[0].impdef)); + } + else + { + mem_access_array =3D buf + mem_access_offs; + memset(mem_access_array, 0, sizeof(*mem_access_array)); + mem_access_array[0].access_perm.endpoint_id =3D shm->ep_id; + mem_access_array[0].access_perm.perm =3D FFA_MEM_ACC_RW; + mem_access_array[0].region_offs =3D region_offs; + } =20 - region_descr =3D buf + mem_access_array[0].region_offs; + region_descr =3D buf + region_offs; memset(region_descr, 0, sizeof(*region_descr)); region_descr->total_page_count =3D shm->page_count; =20 @@ -348,8 +366,9 @@ static int share_shm(struct ffa_shm_mem *shm) region_descr->address_range_count++; } =20 - tot_len =3D ADDR_RANGE_OFFSET(descr->mem_access_count, region_count, - region_descr->address_range_count); + range_count =3D region_descr->address_range_count; + tot_len =3D region_offs + sizeof(*region_descr) + + range_count * sizeof(struct ffa_address_range); if ( tot_len > max_frag_len ) { ret =3D FFA_RET_NOT_SUPPORTED; @@ -445,6 +464,12 @@ static int read_mem_transaction(uint32_t ffa_vers, con= st void *buf, size_t blen, if ( size * count + offs > blen ) return FFA_RET_INVALID_PARAMETERS; =20 + if ( size < sizeof(struct ffa_mem_access) ) + return FFA_RET_INVALID_PARAMETERS; + + if ( offs & 0xF ) + return FFA_RET_INVALID_PARAMETERS; + trans->mem_reg_attr =3D mem_reg_attr; trans->flags =3D flags; trans->mem_access_size =3D size; @@ -461,7 +486,7 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) uint64_t addr =3D get_user_reg(regs, 3); uint32_t page_count =3D get_user_reg(regs, 4); const struct ffa_mem_region *region_descr; - const struct ffa_mem_access *mem_access; + const struct ffa_mem_access_1_2 *mem_access; struct ffa_mem_transaction_int trans; struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; @@ -471,9 +496,12 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) register_t handle_hi =3D 0; register_t handle_lo =3D 0; int ret =3D FFA_RET_DENIED; + uint32_t ffa_vers; uint32_t range_count; uint32_t region_offs; uint16_t dst_id; + uint8_t perm; + uint64_t impdef[2]; =20 if ( !ffa_fw_supports_fid(FFA_MEM_SHARE_64) ) { @@ -512,8 +540,8 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) if ( frag_len > tx_size ) goto out_unlock; =20 - ret =3D read_mem_transaction(ACCESS_ONCE(ctx->guest_vers), tx_buf, - frag_len, &trans); + ffa_vers =3D ACCESS_ONCE(ctx->guest_vers); + ret =3D read_mem_transaction(ffa_vers, tx_buf, frag_len, &trans); if ( ret ) goto out_unlock; =20 @@ -542,13 +570,35 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) goto out_unlock; } =20 + if ( trans.mem_access_size < sizeof(struct ffa_mem_access) ) + { + ret =3D FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + /* Check that it fits in the supplied data */ if ( trans.mem_access_offs + trans.mem_access_size > frag_len ) goto out_unlock; =20 mem_access =3D tx_buf + trans.mem_access_offs; - dst_id =3D ACCESS_ONCE(mem_access->access_perm.endpoint_id); + perm =3D ACCESS_ONCE(mem_access->access_perm.perm); + region_offs =3D ACCESS_ONCE(mem_access->region_offs); + + /* + * FF-A 1.2 introduced an extended mem_access descriptor with impdef + * fields, but guests can still use the 1.1 format if they don't need + * implementation-defined data. Detect which format is used based on + * the mem_access_size field rather than the negotiated FF-A version. + */ + if ( trans.mem_access_size >=3D sizeof(struct ffa_mem_access_1_2) ) + memcpy(impdef, mem_access->impdef, sizeof(impdef)); + else + { + impdef[0] =3D 0; + impdef[1] =3D 0; + } + if ( !FFA_ID_IS_SECURE(dst_id) ) { /* we do not support sharing with VMs */ @@ -556,13 +606,11 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) goto out_unlock; } =20 - if ( ACCESS_ONCE(mem_access->access_perm.perm) !=3D FFA_MEM_ACC_RW ) + if ( perm !=3D FFA_MEM_ACC_RW ) { ret =3D FFA_RET_NOT_SUPPORTED; goto out_unlock; } - - region_offs =3D ACCESS_ONCE(mem_access->region_offs); if ( sizeof(*region_descr) + region_offs > frag_len ) { ret =3D FFA_RET_NOT_SUPPORTED; @@ -587,6 +635,7 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) } shm->sender_id =3D trans.sender_id; shm->ep_id =3D dst_id; + memcpy(shm->impdef, impdef, sizeof(shm->impdef)); =20 /* * Check that the Composite memory region descriptor fits. @@ -602,7 +651,7 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) if ( ret ) goto out; =20 - ret =3D share_shm(shm); + ret =3D share_shm(shm, ffa_fw_version); if ( ret ) goto out; =20 --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830187944891.9346842226241; Wed, 11 Feb 2026 09:16:27 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1227997.1534396 (Exim 4.92) (envelope-from ) id 1vqDot-0005l5-H1; Wed, 11 Feb 2026 17:16:07 +0000 Received: by outflank-mailman (output) from mailman id 1227997.1534396; Wed, 11 Feb 2026 17:16:07 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vqDot-0005kL-Ch; Wed, 11 Feb 2026 17:16:07 +0000 Received: by outflank-mailman (input) for mailman id 1227997; Wed, 11 Feb 2026 17:16:04 +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 1vqDoq-0004tt-My for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:04 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 583ec24c-076d-11f1-b162-2bf370ae4941; Wed, 11 Feb 2026 18:16: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 1F660339; Wed, 11 Feb 2026 09:15:57 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 63DC63F63F; Wed, 11 Feb 2026 09:16: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: 583ec24c-076d-11f1-b162-2bf370ae4941 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 05/12] xen/arm: ffa: Fix PARTINFO RX release errors Date: Wed, 11 Feb 2026 18:15:29 +0100 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830189825158500 Content-Type: text/plain; charset="utf-8" On PARTITION_INFO_GET error paths, Xen unconditionally called FFA_RX_RELEASE for the SPMC RX buffer. If the SPMC didn't grant RX ownership (i.e., the call failed early), this issues a spurious release that returns DENIED and produces warnings. Modify ffa_rxtx_spmc_rx_release() to return the release status and let callers choose whether to log it. Only issue FFA_RX_RELEASE after a successful PARTINFO SMC, while always releasing the local RX lock to avoid deadlocks. Update handle_partition_info_get() to only release the SPMC RX buffer after successful fw_ret checks, and ignore release errors during the error path. Functional impact: eliminates spurious FFA_RX_RELEASE calls and associated DENIED warnings when PARTITION_INFO_GET fails before obtaining SPMC RX buffer ownership. Reviewed-by: Jens Wiklander Signed-off-by: Bertrand Marquis --- Changes since v1: - Rename spmc_ok to notify_fw - Add Jens R-b --- xen/arch/arm/tee/ffa_partinfo.c | 14 ++++++++++++-- xen/arch/arm/tee/ffa_private.h | 2 +- xen/arch/arm/tee/ffa_rxtx.c | 14 +++++++++----- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinf= o.c index bf906ed0c88f..015097bd4d2a 100644 --- a/xen/arch/arm/tee/ffa_partinfo.c +++ b/xen/arch/arm/tee/ffa_partinfo.c @@ -92,9 +92,11 @@ static int32_t ffa_get_sp_partinfo(struct ffa_uuid uuid,= uint32_t *sp_count, uint32_t dst_size) { int32_t ret; + int32_t release_ret; uint32_t src_size, real_sp_count; void *src_buf; uint32_t count =3D 0; + bool notify_fw =3D false; =20 /* We need to use the RX buffer to receive the list */ src_buf =3D ffa_rxtx_spmc_rx_acquire(); @@ -104,6 +106,7 @@ static int32_t ffa_get_sp_partinfo(struct ffa_uuid uuid= , uint32_t *sp_count, ret =3D ffa_partition_info_get(uuid, 0, &real_sp_count, &src_size); if ( ret ) goto out; + notify_fw =3D true; =20 /* Validate the src_size we got */ if ( src_size < sizeof(struct ffa_partition_info_1_0) || @@ -157,7 +160,10 @@ static int32_t ffa_get_sp_partinfo(struct ffa_uuid uui= d, uint32_t *sp_count, *sp_count =3D count; =20 out: - ffa_rxtx_spmc_rx_release(); + release_ret =3D ffa_rxtx_spmc_rx_release(notify_fw); + if ( release_ret ) + gprintk(XENLOG_WARNING, + "ffa: Error releasing SPMC RX buffer: %d\n", release_ret); return ret; } =20 @@ -507,6 +513,7 @@ bool ffa_partinfo_init(void) int32_t e; void *spmc_rx; struct ffa_uuid nil_uuid =3D { .val =3D { 0ULL, 0ULL } }; + bool notify_fw =3D false; =20 if ( !ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) || !ffa_fw_supports_fid(FFA_MSG_SEND_DIRECT_REQ_32)) @@ -522,6 +529,7 @@ bool ffa_partinfo_init(void) printk(XENLOG_ERR "ffa: Failed to get list of SPs: %d\n", e); goto out; } + notify_fw =3D true; =20 if ( count >=3D FFA_MAX_NUM_SP ) { @@ -533,7 +541,9 @@ bool ffa_partinfo_init(void) ret =3D init_subscribers(spmc_rx, count, fpi_size); =20 out: - ffa_rxtx_spmc_rx_release(); + e =3D ffa_rxtx_spmc_rx_release(notify_fw); + if ( e ) + printk(XENLOG_WARNING "ffa: Error releasing SPMC RX buffer: %d\n",= e); return ret; } =20 diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index ccef2f7631f6..1a632983c860 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -459,7 +459,7 @@ int32_t ffa_endpoint_domain_lookup(uint16_t endpoint_id= , struct domain **d_out, 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); +int32_t ffa_rxtx_spmc_rx_release(bool notify_fw); void *ffa_rxtx_spmc_tx_acquire(void); void ffa_rxtx_spmc_tx_release(void); =20 diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c index 7d8bb4f4d031..50758fb57cdf 100644 --- a/xen/arch/arm/tee/ffa_rxtx.c +++ b/xen/arch/arm/tee/ffa_rxtx.c @@ -375,18 +375,22 @@ void *ffa_rxtx_spmc_rx_acquire(void) return NULL; } =20 -void ffa_rxtx_spmc_rx_release(void) +int32_t ffa_rxtx_spmc_rx_release(bool notify_fw) { int32_t ret; =20 ASSERT(spin_is_locked(&ffa_spmc_rx_lock)); =20 - /* 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); + if ( notify_fw ) + { + /* Inform the SPMC that we are done with our RX buffer */ + ret =3D ffa_simple_call(FFA_RX_RELEASE, 0, 0, 0, 0); + } + else + ret =3D FFA_RET_OK; =20 spin_unlock(&ffa_spmc_rx_lock); + return ret; } =20 void *ffa_rxtx_spmc_tx_acquire(void) --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830190129201.62809467180887; Wed, 11 Feb 2026 09:16:30 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1227998.1534406 (Exim 4.92) (envelope-from ) id 1vqDou-00061R-RU; Wed, 11 Feb 2026 17:16:08 +0000 Received: by outflank-mailman (output) from mailman id 1227998.1534406; Wed, 11 Feb 2026 17:16: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 1vqDou-0005zv-MQ; Wed, 11 Feb 2026 17:16:08 +0000 Received: by outflank-mailman (input) for mailman id 1227998; Wed, 11 Feb 2026 17:16: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 1vqDot-0004U4-1Z for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:07 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 590bddd8-076d-11f1-9ccf-f158ae23cfc8; Wed, 11 Feb 2026 18:16:05 +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 7DD33143D; Wed, 11 Feb 2026 09:15:58 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id CC05D3F63F; Wed, 11 Feb 2026 09:16: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: 590bddd8-076d-11f1-9ccf-f158ae23cfc8 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 06/12] xen/arm: ffa: Fix RX/TX map layout and errors Date: Wed, 11 Feb 2026 18:15:30 +0100 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830192620154100 Content-Type: text/plain; charset="utf-8" FFA_RXTX_MAP builds a descriptor for the SPMC and the composite region offsets must be 8-byte aligned. Xen currently uses a 12-byte header size, which produces misaligned RX/TX offsets. Mapping failures also return INVALID_PARAMETERS even when the failure is due to resource exhaustion, which misreports the error condition. Round the descriptor header size up to 8 bytes before placing the RX region and derive the TX offset from the aligned RX offset. Return FFA_RET_NO_MEMORY when the TX or RX buffer mapping fails before the error paths unwind. Functional impact: RXTX_MAP now returns NO_MEMORY on mapping failures and the SPMC receives an aligned RX/TX descriptor layout. Reviewed-by: Jens Wiklander Signed-off-by: Bertrand Marquis --- Changes since v1: - add Jens R-b --- xen/arch/arm/tee/ffa_rxtx.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c index 50758fb57cdf..eff95a7955d7 100644 --- a/xen/arch/arm/tee/ffa_rxtx.c +++ b/xen/arch/arm/tee/ffa_rxtx.c @@ -119,11 +119,17 @@ int32_t ffa_handle_rxtx_map(uint32_t fid, register_t = tx_addr, =20 tx =3D __map_domain_page_global(tx_pg); if ( !tx ) + { + ret =3D FFA_RET_NO_MEMORY; goto err_put_rx_pg; + } =20 rx =3D __map_domain_page_global(rx_pg); if ( !rx ) + { + ret =3D FFA_RET_NO_MEMORY; goto err_unmap_tx; + } =20 /* * Transmit the RX/TX buffer information to the SPM if acquire is supp= orted @@ -136,7 +142,8 @@ int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx= _addr, struct ffa_mem_region *mem_reg; =20 /* All must fit in our TX buffer */ - BUILD_BUG_ON(sizeof(*rxtx_desc) + sizeof(*mem_reg) * 2 + + BUILD_BUG_ON(ROUNDUP(sizeof(*rxtx_desc), 8) + + sizeof(*mem_reg) * 2 + sizeof(struct ffa_address_range) * 2 > FFA_MAX_RXTX_PAGE_COUNT * FFA_PAGE_SIZE); =20 @@ -153,8 +160,8 @@ int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx= _addr, */ rxtx_desc->sender_id =3D ffa_get_vm_id(d); rxtx_desc->reserved =3D 0; - rxtx_desc->rx_region_offs =3D sizeof(*rxtx_desc); - rxtx_desc->tx_region_offs =3D sizeof(*rxtx_desc) + + rxtx_desc->rx_region_offs =3D ROUNDUP(sizeof(*rxtx_desc), 8); + rxtx_desc->tx_region_offs =3D rxtx_desc->rx_region_offs + offsetof(struct ffa_mem_region, address_range_array[1]); =20 --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830186428324.09478975019704; Wed, 11 Feb 2026 09:16:26 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1227999.1534411 (Exim 4.92) (envelope-from ) id 1vqDov-00065O-6i; Wed, 11 Feb 2026 17:16:09 +0000 Received: by outflank-mailman (output) from mailman id 1227999.1534411; Wed, 11 Feb 2026 17:16:09 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vqDou-00063n-Us; Wed, 11 Feb 2026 17:16:08 +0000 Received: by outflank-mailman (input) for mailman id 1227999; Wed, 11 Feb 2026 17:16:07 +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 1vqDot-0004tt-Jc for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:07 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 59f2c27a-076d-11f1-b162-2bf370ae4941; Wed, 11 Feb 2026 18:16: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 030DF339; Wed, 11 Feb 2026 09:16:00 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2857D3F63F; Wed, 11 Feb 2026 09:16:05 -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: 59f2c27a-076d-11f1-b162-2bf370ae4941 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 07/12] xen/arm: ffa: Fix RXTX_UNMAP ownership race Date: Wed, 11 Feb 2026 18:15:31 +0100 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830188689154100 Content-Type: text/plain; charset="utf-8" rxtx_unmap() checks RX ownership without holding the RX/TX locks and only enforces the ownership rule when FFA_RX_ACQUIRE is supported. This allows a vCPU to acquire RX between the check and unmap, and it lets RXTX_UNMAP proceed while RX is owned when buffers are not forwarded to firmware. Hold rx_lock/tx_lock across the ownership check and unmap, and deny RXTX_UNMAP whenever RX is owned, independent of RX_ACQUIRE support. For teardown, release RX ownership under the same lock window; use FFA_RX_RELEASE directly because rx_lock is held, and clear the local flag when the firmware path is unavailable. Functional impact: RXTX_UNMAP now reliably returns DENIED while RX is owned, and teardown releases/clears ownership without a race. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v1: - Remove marking rx buffer as free during teardown as it is useless - Add a comment when calling rxtx_unmap during teardown to remind code readers that true is for teardown mode --- xen/arch/arm/tee/ffa_rxtx.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c index eff95a7955d7..c4fc4c4934af 100644 --- a/xen/arch/arm/tee/ffa_rxtx.c +++ b/xen/arch/arm/tee/ffa_rxtx.c @@ -220,7 +220,7 @@ err_unlock_rxtx: return ret; } =20 -static int32_t rxtx_unmap(struct domain *d) +static int32_t rxtx_unmap(struct domain *d, bool teardown) { struct ffa_ctx *ctx =3D d->arch.tee; int32_t ret =3D FFA_RET_OK; @@ -234,6 +234,32 @@ static int32_t rxtx_unmap(struct domain *d) goto err_unlock_rxtx; } =20 + if ( !ctx->rx_is_free ) + { + if ( teardown ) + { + if ( ffa_fw_supports_fid(FFA_RX_ACQUIRE) ) + { + int32_t rel_ret; + + /* Can't use ffa_rx_release() while holding rx_lock. */ + rel_ret =3D ffa_simple_call(FFA_RX_RELEASE, ctx->ffa_id, + 0, 0, 0); + if ( rel_ret ) + gdprintk(XENLOG_DEBUG, + "ffa: RX release during teardown failed: %d\n= ", + rel_ret); + } + } + else + { + gdprintk(XENLOG_DEBUG, + "ffa: RXTX_UNMAP denied, RX buffer owned by VM\n"); + ret =3D FFA_RET_DENIED; + goto err_unlock_rxtx; + } + } + if ( ffa_fw_supports_fid(FFA_RX_ACQUIRE) ) { ret =3D ffa_rxtx_unmap(ffa_get_vm_id(d)); @@ -261,7 +287,7 @@ err_unlock_rxtx: =20 int32_t ffa_handle_rxtx_unmap(void) { - return rxtx_unmap(current->domain); + return rxtx_unmap(current->domain, false); } =20 int32_t ffa_rx_acquire(struct ffa_ctx *ctx, void **buf, size_t *buf_size) @@ -369,7 +395,7 @@ int32_t ffa_rxtx_domain_init(struct domain *d) =20 void ffa_rxtx_domain_destroy(struct domain *d) { - rxtx_unmap(d); + rxtx_unmap(d, true /* teardown */); } =20 void *ffa_rxtx_spmc_rx_acquire(void) --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830191270318.7697840926148; Wed, 11 Feb 2026 09:16:31 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1228001.1534424 (Exim 4.92) (envelope-from ) id 1vqDow-0006TW-Jn; Wed, 11 Feb 2026 17:16:10 +0000 Received: by outflank-mailman (output) from mailman id 1228001.1534424; Wed, 11 Feb 2026 17:16:10 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vqDow-0006T2-Fd; Wed, 11 Feb 2026 17:16:10 +0000 Received: by outflank-mailman (input) for mailman id 1228001; Wed, 11 Feb 2026 17:16:09 +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 1vqDov-0004tt-KN for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:09 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 5aecf9a9-076d-11f1-b162-2bf370ae4941; Wed, 11 Feb 2026 18:16:08 +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 88A52143D; Wed, 11 Feb 2026 09:16:01 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A31B43F63F; Wed, 11 Feb 2026 09:16:06 -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: 5aecf9a9-076d-11f1-b162-2bf370ae4941 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 08/12] xen/arm: ffa: Fix FFA_FEATURES validation Date: Wed, 11 Feb 2026 18:15:32 +0100 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830191868158500 Content-Type: text/plain; charset="utf-8" FFA_FEATURES advertises several ABIs unconditionally, even when firmware support is missing or when the ABI is physical-instance-only. This can mislead guests about what Xen can actually provide and violates FF-A calling conventions. Some SPMCs (Hafnium v2.14 or earlier) also fail to report FFA_RX_ACQUIRE despite supporting it. Update FFA_FEATURES validation to match spec and firmware support: - do no check w2-w7 input registers during FFA_FEATURES as they are flagged Should Be Zero by the FF-A specification or are not used by the calls we support. - reject 64-bit calling conventions from 32-bit guests with NOT_SUPPORTED - return NOT_SUPPORTED for physical-instance-only ABIs (FFA_NOTIFICATION_BITMAP_{CREATE,DESTROY}, FFA_RX_ACQUIRE) - advertise FFA_INTERRUPT as supported - gate message ABIs on firmware support: - FFA_MSG_SEND_DIRECT_REQ_{32,64} - FFA_MSG_SEND_DIRECT_REQ2 (also requires FF-A 1.2 negotiation) - FFA_MSG_SEND2 (or VM-to-VM enabled) - report MEM_SHARE_{32,64} only when FFA_MEM_SHARE_64 is supported - stop advertising FFA_MSG_YIELD (not implemented) Update firmware probing: drop FFA_MEM_SHARE_32 checks (deprecated) and add FFA_RX_ACQUIRE to the probed set. If FFA_MSG_SEND2 is reported but FFA_RX_ACQUIRE is not, assume RX_ACQUIRE support and warn to work around the Hafnium bug. Functional impact: guests now see ABI support that reflects firmware capabilities and Xen implementation status. When SEND2 is present but RX_ACQUIRE is not reported, Xen assumes RX_ACQUIRE support. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v1: - remove completely w2-w7 checking as those are SBZ in the spec or unused by xen --- xen/arch/arm/tee/ffa.c | 63 +++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 23e1f408485b..cb8cd95fdafa 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -91,10 +91,10 @@ static const struct ffa_fw_abi ffa_fw_abi_needed[] =3D { FW_ABI(FFA_PARTITION_INFO_GET), FW_ABI(FFA_NOTIFICATION_INFO_GET_64), FW_ABI(FFA_NOTIFICATION_GET), + FW_ABI(FFA_RX_ACQUIRE), FW_ABI(FFA_RX_RELEASE), FW_ABI(FFA_RXTX_MAP_64), FW_ABI(FFA_RXTX_UNMAP), - FW_ABI(FFA_MEM_SHARE_32), FW_ABI(FFA_MEM_SHARE_64), FW_ABI(FFA_MEM_RECLAIM), FW_ABI(FFA_MSG_SEND_DIRECT_REQ_32), @@ -238,21 +238,30 @@ static void handle_features(struct cpu_user_regs *reg= s) 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++ ) + /* + * FFA_FEATURES defines w2 as input properties only for specific + * function IDs and reserves w3-w7 as SBZ. Xen does not currently + * implement any feature that consumes w2, so ignore extra inputs. + */ + if ( !is_64bit_domain(d) && smccc_is_conv_64(a1) ) { - if ( get_user_reg(regs, n) ) - { - ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); - return; - } + /* 32bit guests should only use 32bit convention calls */ + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); + return; } =20 switch ( a1 ) { + case FFA_NOTIFICATION_BITMAP_CREATE: + case FFA_NOTIFICATION_BITMAP_DESTROY: + case FFA_RX_ACQUIRE: + /* Physical-instance-only ABIs are not exposed to VMs. */ + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); + break; case FFA_ERROR: case FFA_VERSION: + case FFA_INTERRUPT: case FFA_SUCCESS_32: case FFA_SUCCESS_64: case FFA_FEATURES: @@ -261,16 +270,25 @@ static void handle_features(struct cpu_user_regs *reg= s) case FFA_RXTX_UNMAP: case FFA_MEM_RECLAIM: case FFA_PARTITION_INFO_GET: + ffa_set_regs_success(regs, 0, 0); + break; 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); + if ( ffa_fw_supports_fid(a1) ) + ffa_set_regs_success(regs, 0, 0); + else + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); + break; + case FFA_MSG_SEND2: + if ( ffa_fw_supports_fid(a1) || IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + ffa_set_regs_success(regs, 0, 0); + else + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); break; case FFA_MSG_SEND_DIRECT_REQ2: - if ( ACCESS_ONCE(ctx->guest_vers) >=3D FFA_VERSION_1_2 ) + if ( ACCESS_ONCE(ctx->guest_vers) >=3D FFA_VERSION_1_2 && + ffa_fw_supports_fid(FFA_MSG_SEND_DIRECT_REQ2) ) { ffa_set_regs_success(regs, 0, 0); } @@ -281,6 +299,11 @@ static void handle_features(struct cpu_user_regs *regs) break; case FFA_MEM_SHARE_64: case FFA_MEM_SHARE_32: + if ( !ffa_fw_supports_fid(FFA_MEM_SHARE_64) ) + { + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); + break; + } /* * We currently don't support dynamically allocated buffers. Report * that with 0 in bit[0] of w2. @@ -688,6 +711,20 @@ static bool ffa_probe_fw(void) ffa_fw_abi_needed[i].name); } =20 + /* + * Hafnium v2.14 or earlier does not report FFA_RX_ACQUIRE in + * FFA_FEATURES even though it supports it. + */ + if ( !ffa_fw_supports_fid(FFA_RX_ACQUIRE) && + ffa_fw_supports_fid(FFA_MSG_SEND2) ) + { + printk(XENLOG_WARNING + "ARM FF-A Firmware reports FFA_MSG_SEND2 without FFA_RX_ACQ= UIRE\n"); + printk(XENLOG_WARNING + "ffa: assuming RX_ACQUIRE support (workaround)\n"); + set_bit(FFA_ABI_BITNUM(FFA_RX_ACQUIRE), ffa_fw_abi_supported); + } + if ( !ffa_rxtx_spmc_init() ) { printk(XENLOG_ERR "ffa: Error during RXTX buffer init\n"); --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 17708301861861017.257812506949; Wed, 11 Feb 2026 09:16:26 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1228002.1534435 (Exim 4.92) (envelope-from ) id 1vqDoy-0006pk-1C; Wed, 11 Feb 2026 17:16:12 +0000 Received: by outflank-mailman (output) from mailman id 1228002.1534435; Wed, 11 Feb 2026 17:16:11 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vqDox-0006of-Sb; Wed, 11 Feb 2026 17:16:11 +0000 Received: by outflank-mailman (input) for mailman id 1228002; Wed, 11 Feb 2026 17:16:10 +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 1vqDow-0004tt-K6 for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:10 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 5bcb4448-076d-11f1-b162-2bf370ae4941; Wed, 11 Feb 2026 18:16:10 +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 17284339; Wed, 11 Feb 2026 09:16:03 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 455793F63F; Wed, 11 Feb 2026 09:16:08 -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: 5bcb4448-076d-11f1-b162-2bf370ae4941 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 09/12] xen/arm: ffa: Fix SEND2 SP support gating Date: Wed, 11 Feb 2026 18:15:33 +0100 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830188689154101 Content-Type: text/plain; charset="utf-8" Xen only maps a VM RX/TX buffer into the SPMC when firmware supports FFA_RX_ACQUIRE. Without that mapping, the SPMC cannot access the VM TX buffer to relay FFA_MSG_SEND2 to a secure partition. Advertise FFA_MSG_SEND2 to guests only when VM-to-VM is enabled or when the firmware supports both FFA_MSG_SEND2 and FFA_RX_ACQUIRE, and reject SEND2 to a secure partition otherwise. Add comments to document the mapping/ownership dependency. Functional impact: SEND2 to a secure partition is reported as NOT_SUPPORTED when FFA_RX_ACQUIRE is absent. Reviewed-by: Jens Wiklander Signed-off-by: Bertrand Marquis --- Changes since v1: - Add Jens R-b --- xen/arch/arm/tee/ffa.c | 8 +++++++- xen/arch/arm/tee/ffa_msg.c | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index cb8cd95fdafa..ab02eafdb376 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -281,7 +281,13 @@ static void handle_features(struct cpu_user_regs *regs) ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); break; case FFA_MSG_SEND2: - if ( ffa_fw_supports_fid(a1) || IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + /* + * Forwarding SEND2 to an SP requires the SPMC to see the VM TX bu= ffer. + * We only map VM RX/TX into the SPMC when RX_ACQUIRE is supported. + */ + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) || + (ffa_fw_supports_fid(FFA_MSG_SEND2) && + ffa_fw_supports_fid(FFA_RX_ACQUIRE)) ) ffa_set_regs_success(regs, 0, 0); else ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c index 10856fddcbc4..928f269f6c3a 100644 --- a/xen/arch/arm/tee/ffa_msg.c +++ b/xen/arch/arm/tee/ffa_msg.c @@ -274,6 +274,17 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *reg= s) ret =3D FFA_RET_NOT_SUPPORTED; goto out; } + /* + * The SPMC needs access to the VM TX buffer to relay SEND2. + * We only map VM RX/TX into the SPMC when RX_ACQUIRE is supported. + */ + if ( !ffa_fw_supports_fid(FFA_RX_ACQUIRE) ) + { + ret =3D FFA_RET_NOT_SUPPORTED; + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 to SP requires RX_ACQUIRE\n"); + goto out; + } =20 ret =3D ffa_simple_call(FFA_MSG_SEND2, ((uint32_t)ffa_get_vm_id(src_d)) << 16, 0, 0= , 0); --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830202901757.3957339400002; Wed, 11 Feb 2026 09:16:42 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1228006.1534446 (Exim 4.92) (envelope-from ) id 1vqDp0-0007JR-MD; Wed, 11 Feb 2026 17:16:14 +0000 Received: by outflank-mailman (output) from mailman id 1228006.1534446; Wed, 11 Feb 2026 17:16:14 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vqDp0-0007J7-I1; Wed, 11 Feb 2026 17:16:14 +0000 Received: by outflank-mailman (input) for mailman id 1228006; Wed, 11 Feb 2026 17:16:13 +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 1vqDoz-0004U4-Au for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:13 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 5c99d597-076d-11f1-9ccf-f158ae23cfc8; Wed, 11 Feb 2026 18:16:11 +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 65924497; Wed, 11 Feb 2026 09:16:04 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B11743F63F; Wed, 11 Feb 2026 09:16:09 -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: 5c99d597-076d-11f1-9ccf-f158ae23cfc8 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 10/12] xen/arm: ffa: Reduce logging noise Date: Wed, 11 Feb 2026 18:15:34 +0100 Message-ID: <95e4051cbf4f3e1ba1a23273521407da5733a174.1770826406.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830203926158500 Content-Type: text/plain; charset="utf-8" Several FF-A paths log warnings for expected or recoverable conditions, leading to noisy logs during normal operation. Reduce log noise by: - demoting unhandled FID warnings to debug - ratelimiting notification and VM teardown failures - printing the bit-15 convention warning once per boot - adjusting log prefixes for hypervisor-only events - adding debug diagnostics for RX/TX acquire failures, with busy cases ratelimited No functional changes. Reviewed-by: Jens Wiklander Signed-off-by: Bertrand Marquis --- Changes since v1: - Add Jens R-b --- xen/arch/arm/tee/ffa.c | 11 ++++++----- xen/arch/arm/tee/ffa_notif.c | 11 ++++++----- xen/arch/arm/tee/ffa_partinfo.c | 15 ++++++++------- xen/arch/arm/tee/ffa_rxtx.c | 21 +++++++++++++++++++-- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index ab02eafdb376..aa43ae2595d7 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -450,7 +450,7 @@ static bool ffa_handle_call(struct cpu_user_regs *regs) break; =20 default: - gprintk(XENLOG_ERR, "ffa: unhandled fid 0x%x\n", fid); + gdprintk(XENLOG_DEBUG, "ffa: unhandled fid 0x%x\n", fid); e =3D FFA_RET_NOT_SUPPORTED; break; } @@ -570,7 +570,8 @@ static void ffa_domain_teardown_continue(struct ffa_ctx= *ctx, bool first_time) =20 if ( retry ) { - printk(XENLOG_G_INFO "%pd: ffa: Remaining cleanup, retrying\n", ct= x->teardown_d); + printk(XENLOG_G_DEBUG "%pd: ffa: Remaining cleanup, retrying\n", + ctx->teardown_d); =20 ctx->teardown_expire =3D NOW() + FFA_CTX_TEARDOWN_DELAY; =20 @@ -611,7 +612,7 @@ static void ffa_teardown_timer_callback(void *arg) if ( ctx ) ffa_domain_teardown_continue(ctx, false /* !first_time */); else - printk(XENLOG_G_ERR "%s: teardown list is empty\n", __func__); + printk(XENLOG_ERR "%s: teardown list is empty\n", __func__); } =20 /* This function is supposed to undo what ffa_domain_init() has done */ @@ -673,7 +674,7 @@ static bool ffa_probe_fw(void) =20 if ( !ffa_get_version(&vers) ) { - gprintk(XENLOG_ERR, "Cannot retrieve the FFA version\n"); + printk(XENLOG_ERR "ffa: Cannot retrieve the FFA version\n"); goto err_no_fw; } =20 @@ -713,7 +714,7 @@ static bool ffa_probe_fw(void) set_bit(FFA_ABI_BITNUM(ffa_fw_abi_needed[i].id), ffa_fw_abi_supported); else - printk(XENLOG_INFO "ARM FF-A Firmware does not support %s\n", + printk(XENLOG_WARNING "ARM FF-A Firmware does not support %s\n= ", ffa_fw_abi_needed[i].name); } =20 diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 37b05747cd21..186e72641237 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -292,8 +292,9 @@ static void notif_vm_pend_intr(uint16_t vm_id) break; } } - if ( !v ) - printk(XENLOG_ERR "ffa: can't inject NPI, all vCPUs offline\n"); + if ( !v && printk_ratelimit() ) + printk(XENLOG_G_DEBUG "%pd: ffa: can't inject NPI, all vCPUs offli= ne\n", + d); =20 out_unlock: rcu_unlock_domain(d); @@ -316,9 +317,9 @@ static void notif_sri_action(void *unused) res =3D ffa_get_ret_code(&resp); if ( res ) { - if ( res !=3D FFA_RET_NO_DATA ) - printk(XENLOG_ERR "ffa: notification info get failed: erro= r %d\n", - res); + if ( res !=3D FFA_RET_NO_DATA && printk_ratelimit() ) + printk(XENLOG_WARNING + "ffa: notification info get failed: error %d\n", re= s); return; } =20 diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinf= o.c index 015097bd4d2a..fdb03dae9a0c 100644 --- a/xen/arch/arm/tee/ffa_partinfo.c +++ b/xen/arch/arm/tee/ffa_partinfo.c @@ -461,9 +461,11 @@ static bool init_subscribers(void *buf, uint16_t count= , uint32_t fpi_size) */ if ( !FFA_ID_IS_SECURE(fpi->id) ) { - printk(XENLOG_ERR "ffa: Firmware is not using bit 15 conventio= n for IDs !!\n" - "ffa: Secure partition with id 0x%04x cannot= be used\n", - fpi->id); + printk_once(XENLOG_ERR + "ffa: Firmware is not using bit 15 convention for = IDs !!\n"); + printk(XENLOG_ERR + "ffa: Secure partition with id 0x%04x cannot be used\n", + fpi->id); } else { @@ -632,11 +634,10 @@ bool ffa_partinfo_domain_destroy(struct domain *d) res =3D ffa_direct_req_send_vm(subscr_vm_destroyed[n], ffa_get_vm_= id(d), FFA_MSG_SEND_VM_DESTROYED); =20 - if ( res ) - { - printk(XENLOG_ERR "%pd: ffa: Failed to report destruction of v= m_id %u to %u: res %d\n", + if ( res && printk_ratelimit() ) + printk(XENLOG_WARNING + "%pd: ffa: Failed to report destruction of vm_id %u to = %u: res %d\n", d, ffa_get_vm_id(d), subscr_vm_destroyed[n], res); - } =20 /* * For these two error codes the hypervisor is expected to resend diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c index c4fc4c4934af..26a04f056f7b 100644 --- a/xen/arch/arm/tee/ffa_rxtx.c +++ b/xen/arch/arm/tee/ffa_rxtx.c @@ -4,6 +4,7 @@ */ =20 #include +#include #include #include #include @@ -82,8 +83,9 @@ int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_a= ddr, =20 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); + gdprintk(XENLOG_DEBUG, + "ffa: RXTX_MAP: error: %u pages requested (limit %u)\n", + page_count, FFA_MAX_RXTX_PAGE_COUNT); return FFA_RET_INVALID_PARAMETERS; } =20 @@ -299,12 +301,15 @@ int32_t ffa_rx_acquire(struct ffa_ctx *ctx, void **bu= f, size_t *buf_size) if ( !ctx->page_count ) { ret =3D FFA_RET_DENIED; + gdprintk(XENLOG_DEBUG, "ffa: RX acquire denied, no RX/TX mapped\n"= ); goto out; } =20 if ( !ctx->rx_is_free ) { ret =3D FFA_RET_BUSY; + if ( printk_ratelimit() ) + gdprintk(XENLOG_DEBUG, "ffa: RX acquire busy\n"); goto out; } =20 @@ -312,7 +317,10 @@ int32_t ffa_rx_acquire(struct ffa_ctx *ctx, void **buf= , size_t *buf_size) { ret =3D ffa_simple_call(FFA_RX_ACQUIRE, ctx->ffa_id, 0, 0, 0); if ( ret !=3D FFA_RET_OK ) + { + gdprintk(XENLOG_DEBUG, "ffa: RX acquire failed: %d\n", ret); goto out; + } } ctx->rx_is_free =3D false; *buf =3D ctx->rx; @@ -351,13 +359,22 @@ int32_t ffa_tx_acquire(struct ffa_ctx *ctx, const voi= d **buf, size_t *buf_size) int32_t ret =3D FFA_RET_DENIED; =20 if ( !spin_trylock(&ctx->tx_lock) ) + { + gdprintk(XENLOG_DEBUG, "ffa: TX acquire busy\n"); return FFA_RET_BUSY; + } =20 if ( !ctx->page_count ) + { + gdprintk(XENLOG_DEBUG, "ffa: TX acquire denied, no RX/TX mapped\n"= ); goto err_unlock; + } =20 if ( !ctx->tx ) + { + gdprintk(XENLOG_DEBUG, "ffa: TX acquire denied, TX buffer missing\= n"); goto err_unlock; + } =20 *buf =3D ctx->tx; *buf_size =3D ctx->page_count * FFA_PAGE_SIZE; --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 177083026557591.64607039074667; Wed, 11 Feb 2026 09:17:45 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1228066.1534456 (Exim 4.92) (envelope-from ) id 1vqDqD-0001hZ-0C; Wed, 11 Feb 2026 17:17:29 +0000 Received: by outflank-mailman (output) from mailman id 1228066.1534456; Wed, 11 Feb 2026 17:17: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 1vqDqC-0001hS-SP; Wed, 11 Feb 2026 17:17:28 +0000 Received: by outflank-mailman (input) for mailman id 1228066; Wed, 11 Feb 2026 17:17: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 1vqDp1-0004tt-Lr for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:15 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 5d6d71a8-076d-11f1-b162-2bf370ae4941; Wed, 11 Feb 2026 18:16:12 +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 BA4F0339; Wed, 11 Feb 2026 09:16:05 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 12D563F63F; Wed, 11 Feb 2026 09:16:10 -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: 5d6d71a8-076d-11f1-b162-2bf370ae4941 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 11/12] xen/arm: ffa: Add MEM_SHARE page diagnostics Date: Wed, 11 Feb 2026 18:15:35 +0100 Message-ID: <4fa6736cbe35b060cf34b2978bbf9b3481d9266a.1770826406.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830266267158500 Content-Type: text/plain; charset="utf-8" MEM_SHARE failures in get_shm_pages() are silent, which makes malformed ranges and page mapping failures hard to diagnose. Add debug logging for page validation failures: - descriptor validation failures (unaligned, range short/overflow) - per-page mapping failures (unmapped GFN, wrong p2m type) - address overflow detection in range walks Ratelimit temporary reclaim failures and log permanent reclaim failures as errors. No functional changes. Signed-off-by: Bertrand Marquis --- Changes since v1: - use one print per error case instead of the previous system using variables to classify and a single print site. --- xen/arch/arm/tee/ffa_shm.c | 39 +++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/tee/ffa_shm.c b/xen/arch/arm/tee/ffa_shm.c index 070babce9627..3d61caaeba78 100644 --- a/xen/arch/arm/tee/ffa_shm.c +++ b/xen/arch/arm/tee/ffa_shm.c @@ -161,32 +161,62 @@ static int32_t get_shm_pages(struct domain *d, struct= ffa_shm_mem *shm, addr =3D ACCESS_ONCE(range[n].address); =20 if ( !IS_ALIGNED(addr, FFA_PAGE_SIZE) ) + { + gdprintk(XENLOG_DEBUG, + "ffa: mem share pages invalid: unaligned range %u add= ress %#lx\n", + n, (unsigned long)addr); return FFA_RET_INVALID_PARAMETERS; + } =20 for ( m =3D 0; m < page_count; m++ ) { if ( pg_idx >=3D shm->page_count ) + { + gdprintk(XENLOG_DEBUG, + "ffa: mem share pages invalid: range overflow rg = %u pg %u\n", + n, m); return FFA_RET_INVALID_PARAMETERS; + } =20 if ( !ffa_safe_addr_add(addr, m) ) + { + gdprintk(XENLOG_DEBUG, + "ffa: mem share pages invalid: addr overflow rg %= u pg %u base %#lx\n", + n, m, (unsigned long)addr); return FFA_RET_INVALID_PARAMETERS; + } =20 gaddr =3D addr + m * FFA_PAGE_SIZE; gfn =3D gaddr_to_gfn(gaddr); shm->pages[pg_idx] =3D get_page_from_gfn(d, gfn_x(gfn), &t, P2M_ALLOC); if ( !shm->pages[pg_idx] ) + { + gdprintk(XENLOG_DEBUG, + "ffa: mem share pages invalid: gfn unmapped rg %u= pg %u addr %#lx\n", + n, m, (unsigned long)gaddr); return FFA_RET_DENIED; + } /* Only normal RW RAM for now */ if ( t !=3D p2m_ram_rw ) + { + gdprintk(XENLOG_DEBUG, + "ffa: mem share pages invalid: p2m type %u rg %u = pg %u addr %#lx\n", + t, n, m, (unsigned long)gaddr); return FFA_RET_DENIED; + } pg_idx++; } } =20 /* The ranges must add up */ if ( pg_idx < shm->page_count ) + { + gdprintk(XENLOG_DEBUG, + "ffa: mem share pages invalid: range short pg %u\n", + pg_idx); return FFA_RET_INVALID_PARAMETERS; + } =20 return FFA_RET_OK; } @@ -741,8 +771,10 @@ bool ffa_shm_domain_destroy(struct domain *d) * A temporary error that may get resolved a bit later, it's * worth retrying. */ - printk(XENLOG_G_INFO "%pd: ffa: Failed to reclaim handle %#lx = : %d\n", - d, shm->handle, res); + if ( printk_ratelimit() ) + printk(XENLOG_G_WARNING + "%pd: ffa: Failed to reclaim handle %#lx : %d\n", + d, shm->handle, res); break; /* We will retry later */ default: /* @@ -754,7 +786,8 @@ bool ffa_shm_domain_destroy(struct domain *d) * FFA_RET_NO_MEMORY might be a temporary error as it it could * succeed if retried later, but treat it as permanent for now. */ - printk(XENLOG_G_INFO "%pd: ffa: Permanent failure to reclaim h= andle %#lx : %d\n", + printk(XENLOG_G_ERR + "%pd: ffa: Permanent failure to reclaim handle %#lx : %= d\n", d, shm->handle, res); =20 /* --=20 2.52.0 From nobody Mon Apr 13 01:52:16 2026 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 1770830261176219.8366937649747; Wed, 11 Feb 2026 09:17:41 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1228068.1534463 (Exim 4.92) (envelope-from ) id 1vqDqD-0001km-A4; Wed, 11 Feb 2026 17:17:29 +0000 Received: by outflank-mailman (output) from mailman id 1228068.1534463; Wed, 11 Feb 2026 17:17:29 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vqDqD-0001kd-4H; Wed, 11 Feb 2026 17:17:29 +0000 Received: by outflank-mailman (input) for mailman id 1228068; Wed, 11 Feb 2026 17:17:28 +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 1vqDp4-0004tt-MH for xen-devel@lists.xenproject.org; Wed, 11 Feb 2026 17:16:18 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 5e4c111b-076d-11f1-b162-2bf370ae4941; Wed, 11 Feb 2026 18:16:14 +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 4C73E497; Wed, 11 Feb 2026 09:16:07 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.53.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 67B8C3F63F; Wed, 11 Feb 2026 09:16:12 -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: 5e4c111b-076d-11f1-b162-2bf370ae4941 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 12/12] xen/arm: ffa: Add message parameter diagnostics Date: Wed, 11 Feb 2026 18:15:36 +0100 Message-ID: X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1770830262246158500 Content-Type: text/plain; charset="utf-8" MSG_SEND2 and direct request validation failures are silent, making it hard to diagnose invalid IDs, oversized messages, or unsupported destination types. Add debug logs for parameter validation failures: - invalid endpoint IDs - oversized messages - unsupported destination types - invalid sender/receiver combinations - ratelimit MSG_SEND2 busy failures to avoid log flooding No functional changes. Signed-off-by: Bertrand Marquis --- Changes since v1: - add a comment to explain ratelimit for BUSY in send2 --- xen/arch/arm/tee/ffa_msg.c | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c index 928f269f6c3a..1eadc62870f2 100644 --- a/xen/arch/arm/tee/ffa_msg.c +++ b/xen/arch/arm/tee/ffa_msg.c @@ -4,6 +4,7 @@ */ =20 #include +#include #include #include =20 @@ -100,6 +101,7 @@ void ffa_handle_msg_send_direct_req(struct cpu_user_reg= s *regs, uint32_t fid) if ( !ffa_fw_supports_fid(fid) ) { ret =3D FFA_RET_NOT_SUPPORTED; + gdprintk(XENLOG_DEBUG, "ffa: direct req fid %#x not supported\n", = fid); goto out; } =20 @@ -108,6 +110,9 @@ void ffa_handle_msg_send_direct_req(struct cpu_user_reg= s *regs, uint32_t fid) (src_dst & GENMASK(15,0)) =3D=3D ffa_get_vm_id(d) ) { ret =3D FFA_RET_INVALID_PARAMETERS; + gdprintk(XENLOG_DEBUG, + "ffa: direct req invalid src/dst %#x\n", + (uint32_t)src_dst); goto out; } =20 @@ -115,6 +120,9 @@ void ffa_handle_msg_send_direct_req(struct cpu_user_reg= s *regs, uint32_t fid) if ( !FFA_ID_IS_SECURE(src_dst & GENMASK(15,0)) ) { ret =3D FFA_RET_NOT_SUPPORTED; + gdprintk(XENLOG_DEBUG, + "ffa: direct req to non-secure dst %#x\n", + (uint32_t)(src_dst & GENMASK(15, 0))); goto out; } =20 @@ -166,7 +174,12 @@ static int32_t ffa_msg_send2_vm(uint16_t dst_id, const= void *src_buf, /* This is also checking that dest is not src */ ret =3D ffa_endpoint_domain_lookup(dst_id, &dst_d, &dst_ctx); if ( ret ) + { + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 lookup failed: dst %#x ret %d\n", + dst_id, ret); return ret; + } =20 /* This also checks that destination has set a Rx buffer */ ret =3D ffa_rx_acquire(dst_ctx , &rx_buf, &rx_size); @@ -199,6 +212,16 @@ static int32_t ffa_msg_send2_vm(uint16_t dst_id, const= void *src_buf, /* receiver rx buffer will be released by the receiver*/ =20 out_unlock: + if ( ret ) + { + /** + * Always print other errors than BUSY but ratelimit BUSY prints + * to prevent large number of prints when sender retries on BUSY. + */ + if ( ret !=3D FFA_RET_BUSY || printk_ratelimit() ) + gdprintk(XENLOG_DEBUG, "ffa: msg_send2 to %#x failed: %d\n", + dst_id, ret); + } rcu_unlock_domain(dst_d); if ( !ret ) ffa_raise_rx_buffer_full(dst_d); @@ -226,7 +249,11 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *reg= s) =20 ret =3D ffa_tx_acquire(src_ctx, &tx_buf, &tx_size); if ( ret !=3D FFA_RET_OK ) + { + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 TX acquire failed: %d\n", ret); return ret; + } =20 /* create a copy of the message header */ memcpy(&src_msg, tx_buf, sizeof(src_msg)); @@ -238,6 +265,9 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs) dst_id =3D=3D ffa_get_vm_id(src_d) ) { ret =3D FFA_RET_INVALID_PARAMETERS; + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 invalid src/dst src %#x dst %#x\n", + src_id, dst_id); goto out; } =20 @@ -246,6 +276,9 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs) if (src_msg.msg_offset < sizeof(struct ffa_part_msg_rxtx_1_1)) { ret =3D FFA_RET_INVALID_PARAMETERS; + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 invalid msg_offset %u (v1.1)\n", + src_msg.msg_offset); goto out; } /* Set uuid to Nil UUID for v1.1 guests */ @@ -255,6 +288,9 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs) else if ( src_msg.msg_offset < sizeof(struct ffa_part_msg_rxtx_1_2) ) { ret =3D FFA_RET_INVALID_PARAMETERS; + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 invalid msg_offset %u (v1.2)\n", + src_msg.msg_offset); goto out; } =20 @@ -263,6 +299,9 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs) src_msg.msg_size > (tx_size - src_msg.msg_offset) ) { ret =3D FFA_RET_INVALID_PARAMETERS; + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 invalid msg_size %u offset %u tx %zu\n", + src_msg.msg_size, src_msg.msg_offset, tx_size); goto out; } =20 @@ -272,6 +311,8 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs) if ( !ffa_fw_supports_fid(FFA_MSG_SEND2) ) { ret =3D FFA_RET_NOT_SUPPORTED; + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 to SP not supported\n"); goto out; } /* @@ -288,6 +329,8 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs) =20 ret =3D ffa_simple_call(FFA_MSG_SEND2, ((uint32_t)ffa_get_vm_id(src_d)) << 16, 0, 0= , 0); + if ( ret ) + gdprintk(XENLOG_DEBUG, "ffa: msg_send2 to SP failed: %d\n", re= t); } else if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) { @@ -295,7 +338,11 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *reg= s) ret =3D ffa_msg_send2_vm(dst_id, tx_buf, &src_msg); } else + { ret =3D FFA_RET_INVALID_PARAMETERS; + gdprintk(XENLOG_DEBUG, + "ffa: msg_send2 to VM disabled (dst %#x)\n", dst_id); + } =20 out: ffa_tx_release(src_ctx); @@ -311,6 +358,7 @@ void ffa_handle_run(struct cpu_user_regs *regs, uint32_= t fid) if ( !ffa_fw_supports_fid(fid) ) { ret =3D FFA_RET_NOT_SUPPORTED; + gdprintk(XENLOG_DEBUG, "ffa: run fid %#x not supported\n", fid); goto out; } =20 @@ -322,6 +370,7 @@ void ffa_handle_run(struct cpu_user_regs *regs, uint32_= t fid) if ( !FFA_ID_IS_SECURE(dst >> 16) ) { ret =3D FFA_RET_NOT_SUPPORTED; + gdprintk(XENLOG_DEBUG, "ffa: run to non-secure dst %#x\n", dst); goto out; } =20 --=20 2.52.0