From patchwork Wed Apr 16 07:39:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bertrand Marquis X-Patchwork-Id: 14053416 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4E54EC369BA for ; Wed, 16 Apr 2025 07:40:29 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.955184.1348999 (Exim 4.92) (envelope-from ) id 1u4xNc-00068K-5i; Wed, 16 Apr 2025 07:40:20 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 955184.1348999; Wed, 16 Apr 2025 07:40:20 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1u4xNc-00068D-36; Wed, 16 Apr 2025 07:40:20 +0000 Received: by outflank-mailman (input) for mailman id 955184; Wed, 16 Apr 2025 07:40:19 +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 1u4xNb-00065X-2O for xen-devel@lists.xenproject.org; Wed, 16 Apr 2025 07:40:19 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 0a474548-1a96-11f0-9ffb-bf95429c2676; Wed, 16 Apr 2025 09:40:17 +0200 (CEST) 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 7D823152B; Wed, 16 Apr 2025 00:40:14 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.44.175]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id AF4DB3F66E; Wed, 16 Apr 2025 00:40:14 -0700 (PDT) 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: 0a474548-1a96-11f0-9ffb-bf95429c2676 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , Stefano Stabellini , Volodymyr Babchuk Subject: [PATCH v5 1/6] xen/arm: Create tee command line parameter Date: Wed, 16 Apr 2025 09:39:42 +0200 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Add a new command line parameter "tee=" to be used to explicitly select what tee mediator is to be used by Xen and fail if it does not exist or the probe function for it failed. Without specifying which tee is to be used, Xen will use the first one for which the probe function succeeds which depends on the order of the mediator list which depends on the compiler. Using the command line argument, it is now possible to explicit request a specific TEE mediator and panic on boot if it is not available. Signed-off-by: Bertrand Marquis --- Changes in v5: - Typo fix and rewording in command line doc (Julien) - fix include order in tee.c (Julien) - use a local bool instead of retesting the string each time in tee_init (Julien) Changes in v4: - None Changes in v3: - Properly classify tee as arm specific (Jan) Changes in v2: - Patch introduced to add a command line selection of the TEE --- docs/misc/xen-command-line.pandoc | 14 +++++++++++++ xen/arch/arm/include/asm/tee/tee.h | 4 ++++ xen/arch/arm/tee/tee.c | 32 ++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index 89db6e83be66..472de1911363 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -2651,6 +2651,20 @@ Specify the per-cpu trace buffer size in pages. Flag to enable TSC deadline as the APIC timer mode. +### tee (arm) +> `= ` + +Specify the TEE mediator to be probed and use. + +The default behaviour is to probe all TEEs supported by Xen and use +the first one successfully probed. When this parameter is passed, Xen will +probe only the TEE mediator passed as argument and boot will fail if this +mediator is not properly probed or if the requested TEE is not supported by +Xen. + +This parameter can be set to `optee` or `ffa` if the corresponding mediators +are compiled in. + ### tevt_mask > `= ` diff --git a/xen/arch/arm/include/asm/tee/tee.h b/xen/arch/arm/include/asm/tee/tee.h index 0169fd746bcd..15d664e28dce 100644 --- a/xen/arch/arm/include/asm/tee/tee.h +++ b/xen/arch/arm/include/asm/tee/tee.h @@ -55,6 +55,9 @@ struct tee_mediator_desc { /* Printable name of the TEE. */ const char *name; + /* Command line name of the TEE (to be used with tee= cmdline option) */ + const char *cmdline_name; + /* Mediator callbacks as described above. */ const struct tee_mediator_ops *ops; @@ -77,6 +80,7 @@ void tee_free_domain_ctx(struct domain *d); static const struct tee_mediator_desc __tee_desc_##_name __used \ __section(".teemediator.info") = { \ .name = _namestr, \ + .cmdline_name = #_name, \ .ops = _ops, \ .tee_type = _type \ } diff --git a/xen/arch/arm/tee/tee.c b/xen/arch/arm/tee/tee.c index 3f65e45a7892..8501443c8e57 100644 --- a/xen/arch/arm/tee/tee.c +++ b/xen/arch/arm/tee/tee.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -25,6 +26,10 @@ extern const struct tee_mediator_desc _steemediator[], _eteemediator[]; static const struct tee_mediator_desc __read_mostly *cur_mediator; +/* Select the TEE mediator using a name on command line. */ +static char __initdata opt_mediator[16] = ""; +string_param("tee", opt_mediator); + /* * TODO: Add function to alter Dom0 DTB, so we can properly describe * present TEE. @@ -80,15 +85,42 @@ uint16_t tee_get_type(void) static int __init tee_init(void) { const struct tee_mediator_desc *desc; + bool select_mediator = strcmp(opt_mediator, ""); + + if ( select_mediator ) + printk(XENLOG_INFO "TEE Mediator %s selected from command line\n", + opt_mediator); + /* + * When a specific TEE is selected using the 'tee=' command line + * argument, we panic if the probe fails or if the requested TEE is not + * supported. + */ for ( desc = _steemediator; desc != _eteemediator; desc++ ) { + if ( select_mediator && + strncmp(opt_mediator, desc->cmdline_name, sizeof(opt_mediator)) ) + continue; + if ( desc->ops->probe() ) { printk(XENLOG_INFO "Using TEE mediator for %s\n", desc->name); cur_mediator = desc; return 0; } + else if ( select_mediator ) + { + panic("TEE mediator %s from command line probe failed\n", + opt_mediator); + return -EFAULT; + } + } + + if ( select_mediator ) + { + panic("TEE Mediator %s from command line not supported\n", + opt_mediator); + return -EINVAL; } return 0; From patchwork Wed Apr 16 07:39:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bertrand Marquis X-Patchwork-Id: 14053415 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B7876C369B1 for ; Wed, 16 Apr 2025 07:40:27 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.955185.1349005 (Exim 4.92) (envelope-from ) id 1u4xNc-0006Bd-GQ; Wed, 16 Apr 2025 07:40:20 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 955185.1349005; Wed, 16 Apr 2025 07:40:20 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1u4xNc-0006AS-AF; Wed, 16 Apr 2025 07:40:20 +0000 Received: by outflank-mailman (input) for mailman id 955185; Wed, 16 Apr 2025 07:40:19 +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 1u4xNb-0004tR-Bh for xen-devel@lists.xenproject.org; Wed, 16 Apr 2025 07:40:19 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 0b323349-1a96-11f0-9eaf-5ba50f476ded; Wed, 16 Apr 2025 09:40:18 +0200 (CEST) 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 1FAA41595; Wed, 16 Apr 2025 00:40:16 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.44.175]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D68063F66E; Wed, 16 Apr 2025 00:40:16 -0700 (PDT) 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: 0b323349-1a96-11f0-9eaf-5ba50f476ded From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v5 2/6] xen/arm: ffa: Rework partinfo_get implementation Date: Wed, 16 Apr 2025 09:39:43 +0200 Message-ID: <7784969bf79154363ac3479b9489778d03349c77.1744787720.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 This patch is in preparation for VM to VM support in order to do the changes on the SP handling part of partinfo_get before adding support for the VM part. This patches is doing the following changes: - split partinfo_get into 3 functions to have the locking handling and proper exit on error handled more clearly - add some potential overflow checks to validate the offset and sizes passed by the VM on partinfo call. - Introduce a maximum number of SPs (for now set to 64) to prevent holding the CPU for too long in case there would be a lot of partitions in the secure world. The limit currently set is thought to be realistic for most use cases as 64 secure partitions is a very high number compared to current seen usage (more 3 or 4). - fix include ordering in ffa_private.h to be in alphabetic order Signed-off-by: Bertrand Marquis --- Changes in v5: - patch added --- xen/arch/arm/tee/ffa_partinfo.c | 201 +++++++++++++++++++------------- xen/arch/arm/tee/ffa_private.h | 18 ++- 2 files changed, 131 insertions(+), 88 deletions(-) diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinfo.c index c0510ceb8338..e524445c6fb8 100644 --- a/xen/arch/arm/tee/ffa_partinfo.c +++ b/xen/arch/arm/tee/ffa_partinfo.c @@ -63,9 +63,95 @@ static int32_t ffa_partition_info_get(uint32_t *uuid, uint32_t flags, return ret; } -void ffa_handle_partition_info_get(struct cpu_user_regs *regs) +static int32_t ffa_get_sp_count(uint32_t *uuid, uint32_t *sp_count) +{ + uint32_t src_size; + + return ffa_partition_info_get(uuid, FFA_PARTITION_INFO_GET_COUNT_FLAG, + sp_count, &src_size); +} + +static int32_t ffa_get_sp_partinfo(uint32_t *uuid, uint32_t *sp_count, + void *dst_buf, void *end_buf, + uint32_t dst_size) { int32_t ret; + uint32_t src_size, real_sp_count; + void *src_buf = ffa_rx; + uint32_t count = 0; + + /* 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); + + ret = ffa_partition_info_get(uuid, 0, &real_sp_count, &src_size); + if ( ret ) + goto out; + + /* We now own the RX buffer */ + + /* Validate the src_size we got */ + if ( src_size < sizeof(struct ffa_partition_info_1_0) || + src_size >= FFA_PAGE_SIZE ) + { + ret = FFA_RET_NOT_SUPPORTED; + goto out_release; + } + + /* + * Limit the maximum time we hold the CPU by limiting the number of SPs. + * We just ignore the extra ones as this is tested during init in + * ffa_partinfo_init so the only possible reason is SP have been added + * since boot. + */ + if ( real_sp_count > FFA_MAX_NUM_SP ) + real_sp_count = FFA_MAX_NUM_SP; + + /* Make sure the data fits in our buffer */ + if ( real_sp_count > (FFA_RXTX_PAGE_COUNT * FFA_PAGE_SIZE) / src_size ) + { + ret = FFA_RET_NOT_SUPPORTED; + goto out_release; + } + + for ( uint32_t sp_num = 0; sp_num < real_sp_count; sp_num++ ) + { + struct ffa_partition_info_1_1 *fpi = src_buf; + + /* 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 = FFA_RET_NO_MEMORY; + goto out_release; + } + + 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); + + dst_buf += dst_size; + count++; + } + + src_buf += src_size; + } + + *sp_count = count; + +out_release: + ffa_hyp_rx_release(); +out: + spin_unlock(&ffa_rx_buffer_lock); + return ret; +} +void ffa_handle_partition_info_get(struct cpu_user_regs *regs) +{ + int32_t ret = FFA_RET_OK; struct domain *d = current->domain; struct ffa_ctx *ctx = d->arch.tee; uint32_t flags = get_user_reg(regs, 5); @@ -75,8 +161,8 @@ void ffa_handle_partition_info_get(struct cpu_user_regs *regs) get_user_reg(regs, 3), get_user_reg(regs, 4), }; - uint32_t src_size, dst_size; - void *dst_buf; + uint32_t dst_size = 0; + void *dst_buf, *end_buf; uint32_t ffa_sp_count = 0; /* @@ -89,31 +175,26 @@ void ffa_handle_partition_info_get(struct cpu_user_regs *regs) else dst_size = sizeof(struct ffa_partition_info_1_1); - /* - * FF-A v1.0 has w5 MBZ while v1.1 allows - * FFA_PARTITION_INFO_GET_COUNT_FLAG to be non-zero. - * - * FFA_PARTITION_INFO_GET_COUNT is only using registers and not the - * rxtx buffer so do the partition_info_get directly. - */ - if ( flags == FFA_PARTITION_INFO_GET_COUNT_FLAG && - ctx->guest_vers == FFA_VERSION_1_1 ) + /* Only count requested */ + if ( flags ) { + /* + * FF-A v1.0 has w5 MBZ while v1.1 allows + * FFA_PARTITION_INFO_GET_COUNT_FLAG to be non-zero. + */ + if ( ctx->guest_vers == FFA_VERSION_1_0 || + flags != FFA_PARTITION_INFO_GET_COUNT_FLAG ) + { + ret = FFA_RET_INVALID_PARAMETERS; + goto out; + } + if ( ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) ) - ret = ffa_partition_info_get(uuid, flags, &ffa_sp_count, - &src_size); - else - ret = FFA_RET_OK; + ret = ffa_get_sp_count(uuid, &ffa_sp_count); goto out; } - if ( flags ) - { - ret = FFA_RET_INVALID_PARAMETERS; - goto out; - } - if ( !ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) ) { /* Just give an empty partition list to the caller */ @@ -121,80 +202,33 @@ void ffa_handle_partition_info_get(struct cpu_user_regs *regs) goto out; } + /* Get the RX buffer to write the list of partitions */ ret = ffa_rx_acquire(d); if ( ret != FFA_RET_OK ) goto out; dst_buf = ctx->rx; + end_buf = ctx->rx + ctx->page_count * FFA_PAGE_SIZE; - if ( !ffa_rx ) - { - ret = FFA_RET_DENIED; - goto out_rx_release; - } - - spin_lock(&ffa_rx_buffer_lock); - - ret = ffa_partition_info_get(uuid, 0, &ffa_sp_count, &src_size); - - if ( ret ) - goto out_rx_hyp_unlock; + /* An entry should be smaller than a page */ + BUILD_BUG_ON(sizeof(struct ffa_partition_info_1_1) > FFA_PAGE_SIZE); /* - * ffa_partition_info_get() succeeded so we now own the RX buffer we - * share with the SPMC. We must give it back using ffa_hyp_rx_release() - * once we've copied the content. + * Check for overflow and that we can at least store one entry. + * page_count cannot be 0 so we have at least one page. */ - - /* we cannot have a size smaller than 1.0 structure */ - if ( src_size < sizeof(struct ffa_partition_info_1_0) ) - { - ret = FFA_RET_NOT_SUPPORTED; - goto out_rx_hyp_release; - } - - if ( ctx->page_count * FFA_PAGE_SIZE < ffa_sp_count * dst_size ) + if ( dst_buf >= end_buf || dst_buf > (end_buf - dst_size) ) { - ret = FFA_RET_NO_MEMORY; - goto out_rx_hyp_release; + ret = FFA_RET_INVALID_PARAMETERS; + goto out_rx_release; } - if ( ffa_sp_count > 0 ) - { - uint32_t n, n_limit = ffa_sp_count; - void *src_buf = ffa_rx; - - /* copy the secure partitions info */ - for ( n = 0; n < n_limit; n++ ) - { - struct ffa_partition_info_1_1 *fpi = src_buf; - - /* filter out SP not following bit 15 convention if any */ - if ( FFA_ID_IS_SECURE(fpi->id) ) - { - memcpy(dst_buf, src_buf, dst_size); - dst_buf += dst_size; - } - else - ffa_sp_count--; + ret = ffa_get_sp_partinfo(uuid, &ffa_sp_count, dst_buf, end_buf, + dst_size); - src_buf += src_size; - } - } -out_rx_hyp_release: - ffa_hyp_rx_release(); -out_rx_hyp_unlock: - spin_unlock(&ffa_rx_buffer_lock); out_rx_release: - /* - * The calling VM RX buffer only contains data to be used by the VM if the - * call was successful, in which case the VM has to release the buffer - * once it has used the data. - * If something went wrong during the call, we have to release the RX - * buffer back to the SPMC as the VM will not do it. - */ - if ( ret != FFA_RET_OK ) + if ( ret ) ffa_rx_release(d); out: if ( ret ) @@ -353,9 +387,10 @@ bool ffa_partinfo_init(void) goto out; } - if ( count >= UINT16_MAX ) + if ( count >= FFA_MAX_NUM_SP ) { - printk(XENLOG_ERR "ffa: Impossible number of SPs: %u\n", count); + printk(XENLOG_ERR "ffa: More SPs than the maximum supported: %u - %u\n", + count, FFA_MAX_NUM_SP); goto out; } diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index c4cd65538908..0a9c1082db28 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -6,15 +6,15 @@ #ifndef __FFA_PRIVATE_H__ #define __FFA_PRIVATE_H__ +#include #include -#include -#include -#include #include -#include +#include #include +#include +#include #include -#include +#include /* Error codes */ #define FFA_RET_OK 0 @@ -108,6 +108,14 @@ */ #define FFA_CTX_TEARDOWN_DELAY SECONDS(1) +/* + * The maximum number of Secure partitions we support for partinfo_get. + * This prevents holding the CPU during potentially to long time during + * a partinfo_get call. Value choosen seems realistic for any configuration + * but can be incremented here if needed. + */ +#define FFA_MAX_NUM_SP 64 + /* * We rely on the convention suggested but not mandated by the FF-A * specification that secure world endpoint identifiers have the bit 15 From patchwork Wed Apr 16 07:39:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bertrand Marquis X-Patchwork-Id: 14053420 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 05BCFC369B1 for ; Wed, 16 Apr 2025 07:40:37 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.955187.1349024 (Exim 4.92) (envelope-from ) id 1u4xNg-0006iQ-0o; Wed, 16 Apr 2025 07:40:24 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 955187.1349024; Wed, 16 Apr 2025 07:40:23 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1u4xNf-0006hY-Q4; Wed, 16 Apr 2025 07:40:23 +0000 Received: by outflank-mailman (input) for mailman id 955187; Wed, 16 Apr 2025 07:40:22 +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 1u4xNe-00065X-De for xen-devel@lists.xenproject.org; Wed, 16 Apr 2025 07:40:22 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 0c2d0cc6-1a96-11f0-9ffb-bf95429c2676; Wed, 16 Apr 2025 09:40:20 +0200 (CEST) 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 AA52616F2; Wed, 16 Apr 2025 00:40:17 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.44.175]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7A6C43F66E; Wed, 16 Apr 2025 00:40:18 -0700 (PDT) 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: 0c2d0cc6-1a96-11f0-9ffb-bf95429c2676 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v5 3/6] xen/arm: ffa: Introduce VM to VM support Date: Wed, 16 Apr 2025 09:39:44 +0200 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Create a CONFIG_FFA_VM_TO_VM parameter to activate FFA communication between VMs. When activated list VMs in the system with FF-A support in part_info_get. When VM to VM is activated, Xen will be tainted as Insecure and a message is displayed to the user during the boot as there is no filtering of VMs in FF-A so any VM can communicate or see any other VM in the system. WARNING: There is no filtering for now and all VMs are listed !! This patch is reorganizing the ffa_ctx structure to make clear which lock is protecting what parts. This patch is introducing a chain list of the ffa_ctx with a FFA Version negociated allowing to create the partinfo results for VMs without taking a lock on the global domain list in Xen. Signed-off-by: Bertrand Marquis --- Changes in v5: - remove invalid comment about 1.1 firmware support - rename variables from d and dom to curr_d and dest_d (Julien) - add a TODO in the code for potential holding for long of the CPU (Julien) - use an atomic global variable to store the number of VMs instead of recomputing the value each time (Julien) - add partinfo information in ffa_ctx (id, cpus and 64bit) and create a chain list of ctx. Use this chain list to create the partinfo result without holding a global lock to prevent concurrency issues. - Move some changes in a preparation patch modifying partinfo for sps to reduce this patch size and make the review easier Changes in v4: - properly handle SPMC version 1.0 header size case in partinfo_get - switch to local counting variables instead of *pointer += 1 form - coding style issue with missing spaces in if () Changes in v3: - break partinfo_get in several sub functions to make the implementation easier to understand and lock handling easier - rework implementation to check size along the way and prevent previous implementation limits which had to check that the number of VMs or SPs did not change - taint Xen as INSECURE when VM to VM is enabled Changes in v2: - Switch ifdef to IS_ENABLED - dom was not switched to d as requested by Jan because there is already a variable d pointing to the current domain and it must not be shadowed. --- xen/arch/arm/tee/Kconfig | 11 ++++ xen/arch/arm/tee/ffa.c | 47 +++++++++++++- xen/arch/arm/tee/ffa_partinfo.c | 95 ++++++++++++++++++++++++--- xen/arch/arm/tee/ffa_private.h | 112 ++++++++++++++++++++++++++------ 4 files changed, 233 insertions(+), 32 deletions(-) diff --git a/xen/arch/arm/tee/Kconfig b/xen/arch/arm/tee/Kconfig index c5b0f88d7522..88a4c4c99154 100644 --- a/xen/arch/arm/tee/Kconfig +++ b/xen/arch/arm/tee/Kconfig @@ -28,5 +28,16 @@ config FFA [1] https://developer.arm.com/documentation/den0077/latest +config FFA_VM_TO_VM + bool "Enable FF-A between VMs (UNSUPPORTED)" if UNSUPPORTED + default n + depends on FFA + help + This option enables to use FF-A between VMs. + This is experimental and there is no access control so any + guest can communicate with any other guest. + + If unsure, say N. + endmenu diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 3bbdd7168a6b..c1c4c0957091 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -118,6 +118,13 @@ void *ffa_tx __read_mostly; DEFINE_SPINLOCK(ffa_rx_buffer_lock); DEFINE_SPINLOCK(ffa_tx_buffer_lock); +struct list_head ffa_ctx_head; +/* Lock to protect addition/removal in ffa_ctx_head */ +DEFINE_SPINLOCK(ffa_ctx_list_lock); + +#ifdef CONFIG_FFA_VM_TO_VM +atomic_t ffa_vm_count; +#endif /* Used to track domains that could not be torn down immediately. */ static struct timer ffa_teardown_timer; @@ -160,10 +167,21 @@ static void handle_version(struct cpu_user_regs *regs) */ if ( FFA_VERSION_MAJOR(vers) == FFA_MY_VERSION_MAJOR ) { + uint32_t old_vers = ACCESS_ONCE(ctx->guest_vers); + if ( FFA_VERSION_MINOR(vers) > FFA_MY_VERSION_MINOR ) - ctx->guest_vers = FFA_MY_VERSION; + ACCESS_ONCE(ctx->guest_vers) = FFA_MY_VERSION; else - ctx->guest_vers = vers; + ACCESS_ONCE(ctx->guest_vers) = vers; + + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !old_vers ) + { + /* One more VM with FF-A support available */ + inc_ffa_vm_count(); + spin_lock(&ffa_ctx_list_lock); + list_add_tail(&ctx->ctx_list, &ffa_ctx_head); + spin_unlock(&ffa_ctx_list_lock); + } } ffa_set_regs(regs, FFA_MY_VERSION, 0, 0, 0, 0, 0, 0, 0); } @@ -345,6 +363,10 @@ static int ffa_domain_init(struct domain *d) ctx->teardown_d = d; INIT_LIST_HEAD(&ctx->shm_list); + ctx->ffa_id = ffa_get_vm_id(d); + ctx->num_vcpus = d->max_vcpus; + ctx->is_64bit = is_64bit_domain(d); + /* * ffa_domain_teardown() will be called if ffa_domain_init() returns an * error, so no need for cleanup in this function. @@ -421,6 +443,14 @@ static int ffa_domain_teardown(struct domain *d) if ( !ctx ) return 0; + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) && ACCESS_ONCE(ctx->guest_vers) ) + { + dec_ffa_vm_count(); + spin_lock(&ffa_ctx_list_lock); + list_del(&ctx->ctx_list); + spin_unlock(&ffa_ctx_list_lock); + } + ffa_rxtx_domain_destroy(d); ffa_notif_domain_destroy(d); @@ -464,6 +494,18 @@ static bool ffa_probe(void) printk(XENLOG_INFO "ARM FF-A Mediator version %u.%u\n", FFA_MY_VERSION_MAJOR, FFA_MY_VERSION_MINOR); + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + { + /* + * When FFA VM to VM is enabled, the current implementation does not + * offer any way to limit which VM can communicate with which VM using + * FF-A. + * Signal this in the xen console and taint the system as insecure. + * TODO: Introduce a solution to limit what a VM can do through FFA. + */ + printk(XENLOG_ERR "ffa: VM to VM is enabled, system is insecure !!\n"); + add_taint(TAINT_MACHINE_INSECURE); + } /* * psci_init_smccc() updates this value with what's reported by EL-3 * or secure world. @@ -538,6 +580,7 @@ static bool ffa_probe(void) ffa_notif_init(); INIT_LIST_HEAD(&ffa_teardown_head); + INIT_LIST_HEAD(&ffa_ctx_head); init_timer(&ffa_teardown_timer, ffa_teardown_timer_callback, NULL, 0); return true; diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinfo.c index e524445c6fb8..66ea1860e97a 100644 --- a/xen/arch/arm/tee/ffa_partinfo.c +++ b/xen/arch/arm/tee/ffa_partinfo.c @@ -149,6 +149,68 @@ out: spin_unlock(&ffa_rx_buffer_lock); return ret; } + +static int32_t ffa_get_vm_partinfo(uint32_t *vm_count, void *dst_buf, + void *end_buf, uint32_t dst_size) +{ + struct ffa_ctx *curr_ctx = current->domain->arch.tee; + struct ffa_ctx *dest_ctx, *tmp; + uint32_t count = 0; + + /* + * 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. + */ + list_for_each_entry_safe(dest_ctx, tmp, &ffa_ctx_head, ctx_list) + { + /* + * Do not include an entry for the caller VM as the spec is not + * clearly mandating it and it is not supported by Linux. + */ + if ( dest_ctx != curr_ctx ) + { + /* + * 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) ) + { + return FFA_RET_NO_MEMORY; + } + + /* + * Context might has been removed since we go it or being removed + * right now so we might return information for a VM not existing + * anymore. This is acceptable as we return a view of the system + * which could change at any time. + */ + info.id = dest_ctx->ffa_id; + info.execution_context = dest_ctx->num_vcpus; + info.partition_properties = FFA_PART_VM_PROP; + if ( dest_ctx->is_64bit ) + info.partition_properties |= FFA_PART_PROP_AARCH64_STATE; + + memcpy(dst_buf, &info, MIN(sizeof(info), dst_size)); + + if ( dst_size > sizeof(info) ) + memset(dst_buf + sizeof(info), 0, + dst_size - sizeof(info)); + + dst_buf += dst_size; + count++; + } + } + *vm_count = count; + + return FFA_RET_OK; +} + void ffa_handle_partition_info_get(struct cpu_user_regs *regs) { int32_t ret = FFA_RET_OK; @@ -163,7 +225,7 @@ void ffa_handle_partition_info_get(struct cpu_user_regs *regs) }; uint32_t dst_size = 0; void *dst_buf, *end_buf; - uint32_t ffa_sp_count = 0; + uint32_t ffa_vm_count = 0, ffa_sp_count = 0; /* * If the guest is v1.0, he does not get back the entry size so we must @@ -190,15 +252,18 @@ void ffa_handle_partition_info_get(struct cpu_user_regs *regs) } if ( ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) ) + { ret = ffa_get_sp_count(uuid, &ffa_sp_count); + if ( ret ) + goto out; + } - goto out; - } + /* + * Do not count the caller VM as the spec is not clearly mandating it + * and it is not supported by Linux. + */ + ffa_vm_count = get_ffa_vm_count() - 1; - if ( !ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) ) - { - /* Just give an empty partition list to the caller */ - ret = FFA_RET_OK; goto out; } @@ -223,9 +288,19 @@ void ffa_handle_partition_info_get(struct cpu_user_regs *regs) goto out_rx_release; } - ret = ffa_get_sp_partinfo(uuid, &ffa_sp_count, dst_buf, end_buf, - dst_size); + if ( ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) ) + { + ret = ffa_get_sp_partinfo(uuid, &ffa_sp_count, dst_buf, end_buf, + dst_size); + + if ( ret ) + goto out_rx_release; + + dst_buf += ffa_sp_count * dst_size; + } + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + ret = ffa_get_vm_partinfo(&ffa_vm_count, dst_buf, end_buf, dst_size); out_rx_release: if ( ret ) @@ -234,7 +309,7 @@ out: if ( ret ) ffa_set_regs_error(regs, ret); else - ffa_set_regs_success(regs, ffa_sp_count, dst_size); + ffa_set_regs_success(regs, ffa_sp_count + ffa_vm_count, dst_size); } static int32_t ffa_direct_req_send_vm(uint16_t sp_id, uint16_t vm_id, diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 0a9c1082db28..52c1078b06f4 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -195,6 +195,18 @@ */ #define FFA_PARTITION_INFO_GET_COUNT_FLAG BIT(0, U) +/* + * Partition properties we give for a normal world VM: + * - can send direct message but not receive them + * - can handle indirect messages + * - can receive notifications + * 32/64 bit flag is set depending on the VM + */ +#define FFA_PART_VM_PROP (FFA_PART_PROP_DIRECT_REQ_SEND | \ + FFA_PART_PROP_INDIRECT_MSGS | \ + FFA_PART_PROP_RECV_NOTIF | \ + FFA_PART_PROP_IS_PE_ID) + /* Flags used in calls to FFA_NOTIFICATION_GET interface */ #define FFA_NOTIF_FLAG_BITMAP_SP BIT(0, U) #define FFA_NOTIF_FLAG_BITMAP_VM BIT(1, U) @@ -297,36 +309,66 @@ struct ffa_ctx_notif { }; struct ffa_ctx { - void *rx; - const void *tx; - struct page_info *rx_pg; - struct page_info *tx_pg; - /* Number of 4kB pages in each of rx/rx_pg and tx/tx_pg */ - unsigned int page_count; + /* + * Chain list of all FF-A contexts, to prevent locking access to this list, + * all "unlocked" data from the structure must be set before adding an + * entry in the list and an entry must be removed from the list before + * freeing a context. + */ + struct list_head ctx_list; /* chain list of all FF-A contexts */ + + /* + * Data access unlocked (mainly for part_info_get in VM to VM). + * Those should be set before the ctx is added in the list. + */ + /* FF-A Endpoint ID */ + uint16_t ffa_id; + uint16_t num_vcpus; + bool is_64bit; + + /* + * Global data accessed atomically or using ACCES_ONCE. + */ /* FF-A version used by the guest */ uint32_t guest_vers; - bool rx_is_free; - /* Used shared memory objects, struct ffa_shm_mem */ - struct list_head shm_list; + struct ffa_ctx_notif notif; + + /* + * Global data accessed with lock locked. + */ + spinlock_t lock; + /* Number of 4kB pages in each of rx/rx_pg and tx/tx_pg */ + unsigned int page_count; /* Number of allocated shared memory object */ unsigned int shm_count; - struct ffa_ctx_notif notif; + /* Used shared memory objects, struct ffa_shm_mem */ + struct list_head shm_list; + /* - * tx_lock is used to serialize access to tx - * rx_lock is used to serialize access to rx_is_free - * lock is used for the rest in this struct + * Rx buffer, accessed with rx_lock locked. + * rx_is_free is used to serialize access. */ - spinlock_t tx_lock; spinlock_t rx_lock; - spinlock_t lock; - /* Used if domain can't be torn down immediately */ + bool rx_is_free; + void *rx; + struct page_info *rx_pg; + + /* + * Tx buffer, access with tx_lock locked. + */ + spinlock_t tx_lock; + const void *tx; + struct page_info *tx_pg; + + + /* + * Domain teardown handling if data shared or used by other domains + * do not allow to teardown the domain immediately. + */ struct domain *teardown_d; struct list_head teardown_list; s_time_t teardown_expire; - /* - * Used for ffa_domain_teardown() to keep track of which SPs should be - * notified that this guest is being destroyed. - */ + /* Keep track of SPs that should be notified of VM destruction */ unsigned long *vm_destroy_bitmap; }; @@ -334,8 +376,15 @@ extern void *ffa_rx; extern void *ffa_tx; extern spinlock_t ffa_rx_buffer_lock; extern spinlock_t ffa_tx_buffer_lock; +extern spinlock_t ffa_ctx_list_lock; extern DECLARE_BITMAP(ffa_fw_abi_supported, FFA_ABI_BITMAP_SIZE); +extern struct list_head ffa_ctx_head; + +#ifdef CONFIG_FFA_VM_TO_VM +extern atomic_t ffa_vm_count; +#endif + 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); @@ -368,6 +417,29 @@ int ffa_handle_notification_set(struct cpu_user_regs *regs); void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid); int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs); +#ifdef CONFIG_FFA_VM_TO_VM +static inline uint16_t get_ffa_vm_count(void) +{ + return atomic_read(&ffa_vm_count); +} + +static inline void inc_ffa_vm_count(void) +{ + atomic_inc(&ffa_vm_count); +} + +static inline void dec_ffa_vm_count(void) +{ + ASSERT(atomic_read(&ffa_vm_count) > 0); + atomic_dec(&ffa_vm_count); +} +#else +/* Only count the caller VM */ +#define get_ffa_vm_count() ((uint16_t)1UL) +#define inc_ffa_vm_count() do {} while(0) +#define dec_ffa_vm_count() do {} while(0) +#endif + static inline uint16_t ffa_get_vm_id(const struct domain *d) { /* +1 since 0 is reserved for the hypervisor in FF-A */ From patchwork Wed Apr 16 07:39:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bertrand Marquis X-Patchwork-Id: 14053417 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 12973C369BD for ; Wed, 16 Apr 2025 07:40:31 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.955186.1349019 (Exim 4.92) (envelope-from ) id 1u4xNf-0006eE-LD; Wed, 16 Apr 2025 07:40:23 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 955186.1349019; Wed, 16 Apr 2025 07:40:23 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1u4xNf-0006e7-I4; Wed, 16 Apr 2025 07:40:23 +0000 Received: by outflank-mailman (input) for mailman id 955186; Wed, 16 Apr 2025 07:40:22 +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 1u4xNe-0004tR-Cc for xen-devel@lists.xenproject.org; Wed, 16 Apr 2025 07:40:22 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 0cfc9268-1a96-11f0-9eaf-5ba50f476ded; Wed, 16 Apr 2025 09:40:21 +0200 (CEST) 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 2FA0C152B; Wed, 16 Apr 2025 00:40:19 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.44.175]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0F4453F66E; Wed, 16 Apr 2025 00:40:19 -0700 (PDT) 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: 0cfc9268-1a96-11f0-9eaf-5ba50f476ded From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v5 4/6] xen/arm: ffa: Add buffer full notification support Date: Wed, 16 Apr 2025 09:39:45 +0200 Message-ID: <95b87ebec5ffa5e7200f6cc1ba8503c8d92c6f37.1744787720.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Add support to raise a Rx buffer full notification to a VM. This function will be used for indirect message support between VM and is only activated if CONFIG_FFA_VM_TO_VM is selected. Even if there are 32 framework notifications possible, right now only one is defined so the implementation is simplified to only handle the buffer full notification using a boolean. If other framework notifications have to be supported one day, the design will have to be modified to handle it properly. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes in v5: - None Changes in v4: - Add Jens R-b Changes in v3: - introduce a vm_pending boolean to track if VM notifications are pending and allow to decorelate pending secure notifications from pending vm ones - remove ifdef around boolean entries for notifications and make use of IS_ENABLED instead of ifdefs when possible - Fix notification number signaled to VMs for buffer full to use the proper GUEST_FFA_NOTIF_PEND_INTR_ID instead of the identifier received from the SPMC. - Move back into this patch ffa_private.h part which was wrongly in the patch for indirect messages between VM Changes in v2: - Switch ifdef to IS_ENABLED when possible --- xen/arch/arm/tee/ffa_notif.c | 36 ++++++++++++++++++++++++++++------ xen/arch/arm/tee/ffa_private.h | 23 +++++++++++++++++++++- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 00efaf8f7353..f6df2f15bb00 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -69,6 +69,7 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs) { struct domain *d = current->domain; struct ffa_ctx *ctx = d->arch.tee; + bool notif_pending; if ( !notif_enabled ) { @@ -76,7 +77,11 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs) return; } - if ( test_and_clear_bool(ctx->notif.secure_pending) ) + notif_pending = test_and_clear_bool(ctx->notif.secure_pending); + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + notif_pending |= test_and_clear_bool(ctx->notif.vm_pending); + + if ( notif_pending ) { /* A pending global notification for the guest */ ffa_set_regs(regs, FFA_SUCCESS_64, 0, @@ -93,6 +98,7 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs) void ffa_handle_notification_get(struct cpu_user_regs *regs) { struct domain *d = current->domain; + struct ffa_ctx *ctx = d->arch.tee; uint32_t recv = get_user_reg(regs, 1); uint32_t flags = get_user_reg(regs, 2); uint32_t w2 = 0; @@ -132,11 +138,7 @@ void ffa_handle_notification_get(struct cpu_user_regs *regs) */ if ( ( flags & FFA_NOTIF_FLAG_BITMAP_SP ) && ( flags & FFA_NOTIF_FLAG_BITMAP_SPM ) ) - { - struct ffa_ctx *ctx = d->arch.tee; - - ACCESS_ONCE(ctx->notif.secure_pending) = false; - } + ACCESS_ONCE(ctx->notif.secure_pending) = false; arm_smccc_1_2_smc(&arg, &resp); e = ffa_get_ret_code(&resp); @@ -156,6 +158,14 @@ void ffa_handle_notification_get(struct cpu_user_regs *regs) w6 = resp.a6; } + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) && + flags & FFA_NOTIF_FLAG_BITMAP_HYP && + test_and_clear_bool(ctx->notif.buff_full_pending) ) + { + ACCESS_ONCE(ctx->notif.vm_pending) = false; + w7 = FFA_NOTIF_RX_BUFFER_FULL; + } + ffa_set_regs(regs, FFA_SUCCESS_32, 0, w2, w3, w4, w5, w6, w7); } @@ -178,6 +188,20 @@ int ffa_handle_notification_set(struct cpu_user_regs *regs) bitmap_hi); } +#ifdef CONFIG_FFA_VM_TO_VM +void ffa_raise_rx_buffer_full(struct domain *d) +{ + struct ffa_ctx *ctx = d->arch.tee; + + if ( !ctx ) + return; + + ACCESS_ONCE(ctx->notif.buff_full_pending) = true; + if ( !test_and_set_bool(ctx->notif.vm_pending) ) + vgic_inject_irq(d, d->vcpu[0], GUEST_FFA_NOTIF_PEND_INTR_ID, true); +} +#endif + /* * Extract a 16-bit ID (index n) from the successful return value from * FFA_NOTIFICATION_INFO_GET_64 or FFA_NOTIFICATION_INFO_GET_32. IDs are diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 52c1078b06f4..63c21c1fc0f7 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -218,6 +218,8 @@ #define FFA_NOTIF_INFO_GET_ID_COUNT_SHIFT 7 #define FFA_NOTIF_INFO_GET_ID_COUNT_MASK 0x1F +#define FFA_NOTIF_RX_BUFFER_FULL BIT(0, U) + /* Feature IDs used with FFA_FEATURES */ #define FFA_FEATURE_NOTIF_PEND_INTR 0x1U #define FFA_FEATURE_SCHEDULE_RECV_INTR 0x2U @@ -303,9 +305,20 @@ struct ffa_mem_region { struct ffa_ctx_notif { /* * True if domain is reported by FFA_NOTIFICATION_INFO_GET to have - * pending global notifications. + * pending notifications from the secure world. */ bool secure_pending; + + /* + * True if domain is reported by FFA_NOTIFICATION_INFO_GET to have + * pending notifications from VMs (including framework ones). + */ + bool vm_pending; + + /* + * True if domain has buffer full notification pending + */ + bool buff_full_pending; }; struct ffa_ctx { @@ -414,6 +427,14 @@ 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); +#ifdef CONFIG_FFA_VM_TO_VM +void ffa_raise_rx_buffer_full(struct domain *d); +#else +static inline void ffa_raise_rx_buffer_full(struct domain *d) +{ +} +#endif + void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid); int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs); From patchwork Wed Apr 16 07:39:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bertrand Marquis X-Patchwork-Id: 14053418 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5EB7DC369BD for ; Wed, 16 Apr 2025 07:40:35 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.955191.1349039 (Exim 4.92) (envelope-from ) id 1u4xNi-0007Cn-EJ; Wed, 16 Apr 2025 07:40:26 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 955191.1349039; Wed, 16 Apr 2025 07:40:26 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1u4xNi-0007Cc-9f; Wed, 16 Apr 2025 07:40:26 +0000 Received: by outflank-mailman (input) for mailman id 955191; Wed, 16 Apr 2025 07:40:25 +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 1u4xNh-00065X-7N for xen-devel@lists.xenproject.org; Wed, 16 Apr 2025 07:40:25 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 0e082836-1a96-11f0-9ffb-bf95429c2676; Wed, 16 Apr 2025 09:40:23 +0200 (CEST) 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 BD4BF1595; Wed, 16 Apr 2025 00:40:20 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.44.175]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 889A33F66E; Wed, 16 Apr 2025 00:40:21 -0700 (PDT) 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: 0e082836-1a96-11f0-9ffb-bf95429c2676 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v5 5/6] xen/arm: ffa: Add indirect message between VM Date: Wed, 16 Apr 2025 09:39:46 +0200 Message-ID: <81ec9ce34c3990b02ec6427d95b6238445333b57.1744787720.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Add support for indirect messages between VMs. This is only enabled if CONFIG_FFA_VM_TO_VM is selected. Signed-off-by: Bertrand Marquis --- Changes in v5: - Prevent potential overflow in send2 handling (Julien) - Only use page_count with rx lock acquired - Fix an issue where send2 between VMs was not doing the copy from the tx buffer but from a wrong location in the stack. This bug was introduced in v4 when switching to a local copy for the header. Changes in v4: - Use a local copy of the message header to prevent a TOC/TOU possible issue when using the payload size Changes in v3: - Move vm to vm indirect message handling in a sub function to simplify lock handling and make implementation easier to read Changes in v2: - Switch ifdef to IS_ENABLED --- xen/arch/arm/tee/ffa_msg.c | 115 ++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 14 deletions(-) diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c index ee594e737fc7..35de260c013a 100644 --- a/xen/arch/arm/tee/ffa_msg.c +++ b/xen/arch/arm/tee/ffa_msg.c @@ -88,43 +88,130 @@ out: resp.a7 & mask); } +static int32_t ffa_msg_send2_vm(uint16_t dst_id, const void *src_buf, + struct ffa_part_msg_rxtx *src_msg) +{ + struct domain *dst_d; + struct ffa_ctx *dst_ctx; + struct ffa_part_msg_rxtx *dst_msg; + int err; + int32_t ret; + + if ( dst_id == 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 = rcu_lock_live_remote_domain_by_id(dst_id - 1, &dst_d); + if ( err ) + return FFA_RET_INVALID_PARAMETERS; + + if ( dst_d->arch.tee == NULL ) + { + ret = FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + + dst_ctx = dst_d->arch.tee; + if ( !dst_ctx->guest_vers ) + { + ret = FFA_RET_INVALID_PARAMETERS; + goto out_unlock; + } + + /* This also checks that destination has set a Rx buffer */ + ret = ffa_rx_acquire(dst_d); + if ( ret ) + goto out_unlock; + + /* 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 ) + { + ret = FFA_RET_NO_MEMORY; + ffa_rx_release(dst_d); + goto out_unlock; + } + + dst_msg = dst_ctx->rx; + + /* prepare destination header */ + dst_msg->flags = 0; + dst_msg->reserved = 0; + dst_msg->msg_offset = sizeof(struct ffa_part_msg_rxtx); + dst_msg->send_recv_id = src_msg->send_recv_id; + dst_msg->msg_size = src_msg->msg_size; + + memcpy(dst_ctx->rx + sizeof(struct ffa_part_msg_rxtx), + src_buf + src_msg->msg_offset, src_msg->msg_size); + + /* receiver rx buffer will be released by the receiver*/ + +out_unlock: + rcu_unlock_domain(dst_d); + if ( !ret ) + ffa_raise_rx_buffer_full(dst_d); + + return ret; +} + int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs) { struct domain *src_d = current->domain; struct ffa_ctx *src_ctx = src_d->arch.tee; - const struct ffa_part_msg_rxtx *src_msg; + struct ffa_part_msg_rxtx src_msg; uint16_t dst_id, src_id; int32_t ret; - if ( !ffa_fw_supports_fid(FFA_MSG_SEND2) ) - return FFA_RET_NOT_SUPPORTED; + BUILD_BUG_ON(sizeof(struct ffa_part_msg_rxtx) >= FFA_PAGE_SIZE); if ( !spin_trylock(&src_ctx->tx_lock) ) return FFA_RET_BUSY; - src_msg = src_ctx->tx; - src_id = src_msg->send_recv_id >> 16; - dst_id = src_msg->send_recv_id & GENMASK(15,0); + /* create a copy of the message header */ + memcpy(&src_msg, src_ctx->tx, sizeof(src_msg)); - if ( src_id != ffa_get_vm_id(src_d) || !FFA_ID_IS_SECURE(dst_id) ) + src_id = src_msg.send_recv_id >> 16; + dst_id = src_msg.send_recv_id & GENMASK(15,0); + + if ( src_id != ffa_get_vm_id(src_d) ) { ret = FFA_RET_INVALID_PARAMETERS; - goto out_unlock_tx; + goto out; } /* check source message fits in buffer */ - if ( src_ctx->page_count * FFA_PAGE_SIZE < - src_msg->msg_offset + src_msg->msg_size || - src_msg->msg_offset < sizeof(struct ffa_part_msg_rxtx) ) + if ( src_msg.msg_offset < sizeof(struct ffa_part_msg_rxtx) || + src_msg.msg_size == 0 || + src_msg.msg_offset > src_ctx->page_count * FFA_PAGE_SIZE || + src_msg.msg_size > (src_ctx->page_count * FFA_PAGE_SIZE - + src_msg.msg_offset) ) { ret = FFA_RET_INVALID_PARAMETERS; - goto out_unlock_tx; + goto out; } - ret = ffa_simple_call(FFA_MSG_SEND2, + if ( FFA_ID_IS_SECURE(dst_id) ) + { + /* Message for a secure partition */ + if ( !ffa_fw_supports_fid(FFA_MSG_SEND2) ) + { + ret = FFA_RET_NOT_SUPPORTED; + goto out; + } + + ret = ffa_simple_call(FFA_MSG_SEND2, ((uint32_t)ffa_get_vm_id(src_d)) << 16, 0, 0, 0); + } + else if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + { + /* Message for a VM */ + ret = ffa_msg_send2_vm(dst_id, src_ctx->tx, &src_msg); + } + else + ret = FFA_RET_INVALID_PARAMETERS; -out_unlock_tx: +out: spin_unlock(&src_ctx->tx_lock); return ret; } From patchwork Wed Apr 16 07:39:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bertrand Marquis X-Patchwork-Id: 14053419 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1C459C369BA for ; Wed, 16 Apr 2025 07:40:36 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.955192.1349044 (Exim 4.92) (envelope-from ) id 1u4xNi-0007FT-PT; Wed, 16 Apr 2025 07:40:26 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 955192.1349044; Wed, 16 Apr 2025 07:40:26 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1u4xNi-0007Du-JI; Wed, 16 Apr 2025 07:40:26 +0000 Received: by outflank-mailman (input) for mailman id 955192; Wed, 16 Apr 2025 07:40:25 +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 1u4xNh-0004tR-NT for xen-devel@lists.xenproject.org; Wed, 16 Apr 2025 07:40:25 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-sth1.inumbo.com (Halon) with ESMTP id 0eecce15-1a96-11f0-9eaf-5ba50f476ded; Wed, 16 Apr 2025 09:40:24 +0200 (CEST) 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 68E091E32; Wed, 16 Apr 2025 00:40:22 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.44.175]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2C8F73F66E; Wed, 16 Apr 2025 00:40:23 -0700 (PDT) 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: 0eecce15-1a96-11f0-9eaf-5ba50f476ded From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v5 6/6] xen/arm: ffa: Enable VM to VM without firmware Date: Wed, 16 Apr 2025 09:39:47 +0200 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 When VM to VM support is activated and there is no suitable FF-A support in the firmware, enable FF-A support for VMs to allow using it for VM to VM communications. If there is OP-TEE running in the secure world and using the non FF-A communication system, having CONFIG_FFA_VM_TO_VM could be non functional (if optee is probed first) or OP-TEE could be non functional (if FF-A is probed first) so it is not recommended to activate the configuration option for such systems. To make buffer full notification work between VMs when there is no firmware, rework the notification handling and modify the global flag to only be used as check for firmware notification support instead. Signed-off-by: Bertrand Marquis --- Changes in v5: - init ctx list when there is no firmware - rework init a bit to prevent duplicates - Remove Jens R-b due to changes done Changes in v4: - Fix Optee to OP-TEE in commit message - Add Jens R-b Changes in v3: - fix typos in commit message - add spaces around << - move notification id fix back into buffer full patch - fix | position in if Changes in v2: - replace ifdef with IS_ENABLED when possible --- xen/arch/arm/tee/ffa.c | 24 ++++++-- xen/arch/arm/tee/ffa_notif.c | 104 ++++++++++++++++------------------- 2 files changed, 67 insertions(+), 61 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index c1c4c0957091..b86c88cefa8c 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -342,8 +342,9 @@ static int ffa_domain_init(struct domain *d) struct ffa_ctx *ctx; int ret; - if ( !ffa_fw_version ) + if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !ffa_fw_version ) return -ENODEV; + /* * We are using the domain_id + 1 as the FF-A ID for VMs as FF-A ID 0 is * reserved for the hypervisor and we only support secure endpoints using @@ -579,11 +580,8 @@ static bool ffa_probe(void) goto err_rxtx_destroy; ffa_notif_init(); - INIT_LIST_HEAD(&ffa_teardown_head); - INIT_LIST_HEAD(&ffa_ctx_head); - init_timer(&ffa_teardown_timer, ffa_teardown_timer_callback, NULL, 0); - return true; + goto exit; err_rxtx_destroy: ffa_rxtx_destroy(); @@ -592,6 +590,22 @@ err_no_fw: bitmap_zero(ffa_fw_abi_supported, FFA_ABI_BITMAP_SIZE); printk(XENLOG_WARNING "ARM FF-A No firmware support\n"); +exit: + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) || ffa_fw_version ) + { + INIT_LIST_HEAD(&ffa_teardown_head); + INIT_LIST_HEAD(&ffa_ctx_head); + init_timer(&ffa_teardown_timer, ffa_teardown_timer_callback, NULL, 0); + } + + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + { + printk(XENLOG_INFO "ARM FF-A only available between VMs\n"); + return true; + } + else if ( ffa_fw_version ) + return true; + return false; } diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index f6df2f15bb00..86bef6b3b2ab 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -16,7 +16,7 @@ #include "ffa_private.h" -static bool __ro_after_init notif_enabled; +static bool __ro_after_init fw_notif_enabled; static unsigned int __ro_after_init notif_sri_irq; int ffa_handle_notification_bind(struct cpu_user_regs *regs) @@ -27,21 +27,17 @@ int ffa_handle_notification_bind(struct cpu_user_regs *regs) uint32_t bitmap_lo = get_user_reg(regs, 3); uint32_t bitmap_hi = get_user_reg(regs, 4); - if ( !notif_enabled ) - return FFA_RET_NOT_SUPPORTED; - if ( (src_dst & 0xFFFFU) != ffa_get_vm_id(d) ) return FFA_RET_INVALID_PARAMETERS; if ( flags ) /* Only global notifications are supported */ return FFA_RET_DENIED; - /* - * We only support notifications from SP so no need to check the sender - * endpoint ID, the SPMC will take care of that for us. - */ - return ffa_simple_call(FFA_NOTIFICATION_BIND, src_dst, flags, bitmap_lo, - bitmap_hi); + if ( FFA_ID_IS_SECURE(src_dst >> 16) && fw_notif_enabled ) + return ffa_simple_call(FFA_NOTIFICATION_BIND, src_dst, flags, + bitmap_lo, bitmap_hi); + + return FFA_RET_NOT_SUPPORTED; } int ffa_handle_notification_unbind(struct cpu_user_regs *regs) @@ -51,18 +47,14 @@ int ffa_handle_notification_unbind(struct cpu_user_regs *regs) uint32_t bitmap_lo = get_user_reg(regs, 3); uint32_t bitmap_hi = get_user_reg(regs, 4); - if ( !notif_enabled ) - return FFA_RET_NOT_SUPPORTED; - if ( (src_dst & 0xFFFFU) != ffa_get_vm_id(d) ) return FFA_RET_INVALID_PARAMETERS; - /* - * We only support notifications from SP so no need to check the - * destination endpoint ID, the SPMC will take care of that for us. - */ - return ffa_simple_call(FFA_NOTIFICATION_UNBIND, src_dst, 0, bitmap_lo, - bitmap_hi); + if ( FFA_ID_IS_SECURE(src_dst >> 16) && fw_notif_enabled ) + return ffa_simple_call(FFA_NOTIFICATION_UNBIND, src_dst, 0, bitmap_lo, + bitmap_hi); + + return FFA_RET_NOT_SUPPORTED; } void ffa_handle_notification_info_get(struct cpu_user_regs *regs) @@ -71,7 +63,7 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs) struct ffa_ctx *ctx = d->arch.tee; bool notif_pending; - if ( !notif_enabled ) + if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !fw_notif_enabled ) { ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); return; @@ -108,7 +100,7 @@ void ffa_handle_notification_get(struct cpu_user_regs *regs) uint32_t w6 = 0; uint32_t w7 = 0; - if ( !notif_enabled ) + if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !fw_notif_enabled ) { ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); return; @@ -120,7 +112,8 @@ void ffa_handle_notification_get(struct cpu_user_regs *regs) return; } - if ( flags & ( FFA_NOTIF_FLAG_BITMAP_SP | FFA_NOTIF_FLAG_BITMAP_SPM ) ) + if ( fw_notif_enabled && (flags & ( FFA_NOTIF_FLAG_BITMAP_SP | + FFA_NOTIF_FLAG_BITMAP_SPM )) ) { struct arm_smccc_1_2_regs arg = { .a0 = FFA_NOTIFICATION_GET, @@ -177,15 +170,14 @@ int ffa_handle_notification_set(struct cpu_user_regs *regs) uint32_t bitmap_lo = get_user_reg(regs, 3); uint32_t bitmap_hi = get_user_reg(regs, 4); - if ( !notif_enabled ) - return FFA_RET_NOT_SUPPORTED; - if ( (src_dst >> 16) != ffa_get_vm_id(d) ) return FFA_RET_INVALID_PARAMETERS; - /* Let the SPMC check the destination of the notification */ - return ffa_simple_call(FFA_NOTIFICATION_SET, src_dst, flags, bitmap_lo, - bitmap_hi); + if ( FFA_ID_IS_SECURE(src_dst >> 16) && fw_notif_enabled ) + return ffa_simple_call(FFA_NOTIFICATION_SET, src_dst, flags, bitmap_lo, + bitmap_hi); + + return FFA_RET_NOT_SUPPORTED; } #ifdef CONFIG_FFA_VM_TO_VM @@ -371,7 +363,7 @@ void ffa_notif_init_interrupt(void) { int ret; - if ( notif_enabled && notif_sri_irq < NR_GIC_SGI ) + if ( fw_notif_enabled && notif_sri_irq < NR_GIC_SGI ) { /* * An error here is unlikely since the primary CPU has already @@ -402,41 +394,41 @@ void ffa_notif_init(void) int ret; /* Only enable fw notification if all ABIs we need are supported */ - if ( !(ffa_fw_supports_fid(FFA_NOTIFICATION_BITMAP_CREATE) && - ffa_fw_supports_fid(FFA_NOTIFICATION_BITMAP_DESTROY) && - ffa_fw_supports_fid(FFA_NOTIFICATION_GET) && - ffa_fw_supports_fid(FFA_NOTIFICATION_INFO_GET_64)) ) - return; - - arm_smccc_1_2_smc(&arg, &resp); - if ( resp.a0 != FFA_SUCCESS_32 ) - return; - - irq = resp.a2; - notif_sri_irq = irq; - if ( irq >= NR_GIC_SGI ) - irq_set_type(irq, IRQ_TYPE_EDGE_RISING); - ret = request_irq(irq, 0, notif_irq_handler, "FF-A notif", NULL); - if ( ret ) + if ( ffa_fw_supports_fid(FFA_NOTIFICATION_BITMAP_CREATE) && + ffa_fw_supports_fid(FFA_NOTIFICATION_BITMAP_DESTROY) && + ffa_fw_supports_fid(FFA_NOTIFICATION_GET) && + ffa_fw_supports_fid(FFA_NOTIFICATION_INFO_GET_64) ) { - printk(XENLOG_ERR "ffa: request_irq irq %u failed: error %d\n", - irq, ret); - return; - } + arm_smccc_1_2_smc(&arg, &resp); + if ( resp.a0 != FFA_SUCCESS_32 ) + return; - notif_enabled = true; + irq = resp.a2; + notif_sri_irq = irq; + if ( irq >= NR_GIC_SGI ) + irq_set_type(irq, IRQ_TYPE_EDGE_RISING); + ret = request_irq(irq, 0, notif_irq_handler, "FF-A notif", NULL); + if ( ret ) + { + printk(XENLOG_ERR "ffa: request_irq irq %u failed: error %d\n", + irq, ret); + return; + } + fw_notif_enabled = true; + } } int ffa_notif_domain_init(struct domain *d) { int32_t res; - if ( !notif_enabled ) - return 0; + if ( fw_notif_enabled ) + { - res = ffa_notification_bitmap_create(ffa_get_vm_id(d), d->max_vcpus); - if ( res ) - return -ENOMEM; + res = ffa_notification_bitmap_create(ffa_get_vm_id(d), d->max_vcpus); + if ( res ) + return -ENOMEM; + } return 0; } @@ -447,6 +439,6 @@ void ffa_notif_domain_destroy(struct domain *d) * Call bitmap_destroy even if bitmap create failed as the SPMC will * return a DENIED error that we will ignore. */ - if ( notif_enabled ) + if ( fw_notif_enabled ) ffa_notification_bitmap_destroy(ffa_get_vm_id(d)); }