From nobody Mon Sep 21 19:53:42 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; dkim=pass; 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=pass(p=none dis=none) header.from=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1788446644; cv=none; d=zohomail.com; s=zohoarc; b=SjNx0DasFqRgGcI0oPDLzx0HvBZvj/cdnZXgqVAWIWizeBRH9P+20RgYKeTwEvcQPPCGO/0l3UoReODRUDIB3sfFNa8tqU4+HeuTrsSrdYDk56JlVMagYXNoZrLH1TTsCafrCKLPzNqe5c9WWXldrwg0p+ghoS30c0XR3AmsLoo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788446644; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=cGeuZycUhkahlagTfOqD4n18Yiy3QhhUlKKduB0Xn+c=; b=fJvKJ3JMemXn+MN7ZOSn1T67ng3qG16jU7sKp5tnjax9EEDnK+XhUQiYr5ccOudzTldl34LgqkK5HnD+dP7roTTmLtT2hhayz8afoGZ/C8siARUz/37s+J9gCznKuaYo1NqoS2rHw8de6tBpqO3IswILViEgdxYCgK9Ljy8ck5o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1788446644008215.01925673290032; Thu, 3 Sep 2026 07:44:04 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1407371.1640471 (Exim 4.92) (envelope-from ) id 1x28fL-0000WE-7U; Thu, 03 Sep 2026 14:43:47 +0000 Received: by outflank-mailman (output) from mailman id 1407371.1640471; Thu, 03 Sep 2026 14:43:47 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fL-0000W2-33; Thu, 03 Sep 2026 14:43:47 +0000 Received: by outflank-mailman (input) for mailman id 1407371; Thu, 03 Sep 2026 14:43:46 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fK-0000JR-5X for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 14:43:46 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1x28fJ-0045Cl-Ii for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 16:43:45 +0200 Received: from [10.42.69.8] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a998799-bab6-0a2a0a5309dd-0a2a4508ed7e-24 for ; Thu, 03 Sep 2026 16:43:45 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-c1860d.mxtls.expurgate.net with ESMTP (eXpurgate 4.57.1) (envelope-from ) id 6a9987a0-f659-0a2a45080019-d98c6eacc8ea-1 for ; Thu, 03 Sep 2026 16:43:45 +0200 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 927F41596; Thu, 3 Sep 2026 07:43:40 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.7.135]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0EE593F673; Thu, 3 Sep 2026 07:43:42 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=foss header.d=arm.com header.i="@arm.com" header.h="From:To:Cc:Subject:Date:In-Reply-To:References" DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1788446624; bh=sExkGKD2p+tZsm+iivyfrVTc3F00OPetQljT4c3dyFA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lMcGCeFd7vQgkbkyPQr0YNxNKPZbjqbpViXvFqfydaBwJoaJWf0H10lan6sAXx9DI UGl9ZJ15dAUBqKhLTxhn+0M2YUyxS9OClykoytWExH+FDaT5u3noPrl35uhZLbJp9/ LYXCWvh4snqp5Nm+dAitouAG/l0a1p2CNCsHLtHg= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel , Jens Wiklander Subject: [PATCH v3 1/6] xen/arm: ffa: Fix NPI injection when vcpu0 is offline Date: Thu, 3 Sep 2026 16:43:26 +0200 Message-ID: <5c332672f58b0f2280d28a1682d53e91f576df17.1788268510.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c1860d/1788446625-CD34D87B-10FC8884/0/0 X-purgate-type: clean X-purgate-size: 3431 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1788446645620158500 Content-Type: text/plain; charset="utf-8" RX-buffer-full notifications currently inject the notification pending interrupt through vcpu0 only. Secure notification delivery already walks the domain's online vCPUs, but the RX-buffer-full path does not. When vcpu0 is offline, the notification remains pending and the guest never receives it. Extract the common notification injection path and reuse it from ffa_raise_rx_buffer_full(). The shared helper delivers the global notification to the first online vCPU and keeps the existing ratelimited debug message when none are online. Functional impact: RX-buffer-full notifications are delivered even when vcpu0 is offline. Fixes: 3935c705688e ("xen/arm: ffa: Add buffer full notification support") Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v2: - none Changes since v1: - add R-b from Jens --- xen/arch/arm/tee/ffa_notif.c | 45 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 186e72641237..07bc5cb3a430 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -19,6 +19,29 @@ static bool __ro_after_init fw_notif_enabled; static unsigned int __ro_after_init notif_sri_irq; =20 +static void inject_notif_pending(struct domain *d) +{ + struct vcpu *v; + + /* + * Since we're only delivering global notification, always + * deliver to the first online vCPU. It doesn't matter + * which we chose, as long as it's available. + */ + for_each_vcpu(d, v) + { + if ( is_vcpu_online(v) ) + { + vgic_inject_irq(d, v, GUEST_FFA_NOTIF_PEND_INTR_ID, true); + return; + } + } + + if ( printk_ratelimit() ) + printk(XENLOG_G_DEBUG "%pd: ffa: can't inject NPI, all vCPUs offli= ne\n", + d); +} + int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; @@ -190,7 +213,7 @@ void ffa_raise_rx_buffer_full(struct domain *d) =20 ACCESS_ONCE(ctx->notif.buff_full_pending) =3D true; if ( !test_and_set_bool(ctx->notif.vm_pending) ) - vgic_inject_irq(d, d->vcpu[0], GUEST_FFA_NOTIF_PEND_INTR_ID, true); + inject_notif_pending(d); } #endif =20 @@ -238,7 +261,6 @@ static void notif_vm_pend_intr(uint16_t vm_id) { struct ffa_ctx *ctx; struct domain *d; - struct vcpu *v; =20 /* * vm_id =3D=3D 0 means a notifications pending for Xen itself, but @@ -277,24 +299,7 @@ static void notif_vm_pend_intr(uint16_t vm_id) * it. */ ACCESS_ONCE(ctx->notif.secure_pending) =3D true; - - /* - * Since we're only delivering global notification, always - * deliver to the first online vCPU. It doesn't matter - * which we chose, as long as it's available. - */ - for_each_vcpu(d, v) - { - if ( is_vcpu_online(v) ) - { - vgic_inject_irq(d, v, GUEST_FFA_NOTIF_PEND_INTR_ID, - true); - break; - } - } - if ( !v && printk_ratelimit() ) - printk(XENLOG_G_DEBUG "%pd: ffa: can't inject NPI, all vCPUs offli= ne\n", - d); + inject_notif_pending(d); =20 out_unlock: rcu_unlock_domain(d); --=20 2.53.0 From nobody Mon Sep 21 19:53:42 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; dkim=pass; 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=pass(p=none dis=none) header.from=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1788446643; cv=none; d=zohomail.com; s=zohoarc; b=bvgklIcFFgxerK+qONC8XZXxFclRVAXHsZnN1DI7YFuGV2gERwrfaOEy9sD6BkN9XaAjEjs+wOWbuisxnDNltdHGV2JmOAV/LW/rra9G3u5N4SAzALMaXct3D48h80VZbgUmJ7uXt0aMHnJjHnSo5GJ5SndBaU9KWqgGPmlWe/0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788446643; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=lqh4+k3NTq/UIJkAi1vBNc0dxFFvp8RNWIWMGrh/sNk=; b=Inqmc7opeONlYvWlgxBqx9cYB0p+aVJsD9v37NIlTfhZzrlqe7llJLCv/lKtWvzmJlxUWXB8PE5YoKJUxbABhuhzKs4t7IukyQf3YmSJ4YUN32gJd7BQfLHPu2dE/J4NPIzZgFm89kyMLaw+a0Jhow64+omJhdkZGlzZd7ctr/k= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1788446643393475.1836277307234; Thu, 3 Sep 2026 07:44:03 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1407372.1640480 (Exim 4.92) (envelope-from ) id 1x28fN-0000kG-DS; Thu, 03 Sep 2026 14:43:49 +0000 Received: by outflank-mailman (output) from mailman id 1407372.1640480; Thu, 03 Sep 2026 14:43:49 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fN-0000k6-A6; Thu, 03 Sep 2026 14:43:49 +0000 Received: by outflank-mailman (input) for mailman id 1407372; Thu, 03 Sep 2026 14:43:48 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fL-0000eb-UI for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 14:43:48 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1x28fL-0045Cl-B3 for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 16:43:47 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a998796-bab6-0a2a0a5309dd-0a2a45079d14-36 for ; Thu, 03 Sep 2026 16:43:47 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTP (eXpurgate 4.57.1) (envelope-from ) id 6a9987a2-b4ea-0a2a45070019-d98c6eacd0ba-1 for ; Thu, 03 Sep 2026 16:43:47 +0200 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 440971650; Thu, 3 Sep 2026 07:43:42 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.7.135]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A96A53F673; Thu, 3 Sep 2026 07:43:44 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=foss header.d=arm.com header.i="@arm.com" header.h="From:To:Cc:Subject:Date:In-Reply-To:References" DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1788446626; bh=lKLze3b1RPc7u9ZAKqZaTJVfvYpzgKeUhZbYUNQQYiM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AUeLYaPCjKSvTIt75pPwHa8YZA8K0g0aqJpGoYnsSvfkamHmqY128/ioVj/1bWeGf batT3UNsLVcW9JdQxCVCNrV5sl0t+HeNHxwgwmwNxpGXfjH5LXeaimd91XXcFJyMsY GhvdEpMQhz95BhIwfIBBdBuHMDmBq7x/pwRjkSPA= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel , Jens Wiklander Subject: [PATCH v3 2/6] xen/arm: ffa: Track hypervisor notifications in a bitmap Date: Thu, 3 Sep 2026 16:43:27 +0200 Message-ID: <39cce5e806b7070da7d4a627bd739b7de711db4b.1788268510.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ef75cf/1788446627-35CC7AE4-A5EC4A42/0/0 X-purgate-type: clean X-purgate-size: 6900 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1788446645507158500 Content-Type: text/plain; charset="utf-8" Hypervisor notifications are currently tracked with a dedicated buff_full_pending boolean. The old RX-buffer-full path also exposed a pending indication indirectly via vm_pending, so FFA_NOTIFICATION_INFO_GET could clear that summary before the guest retrieved the Hypervisor notification bitmap with FFA_NOTIFICATION_GET. Replace the single boolean with a Hypervisor notification bitmap protected by notif_lock. INFO_GET reports pending when hyp_pending is non-zero, GET returns and clears the HYP bitmap under the lock, and RX-buffer-full now keeps notif_lock held across the local NPI decision. notif_irq_raised is only set when an NPI is actually injected, and is cleared once the local pending state is consumed. Initialize and clear the bitmap during domain lifecycle handling, and use ctx->ffa_id for bitmap create and destroy so the notification state stays tied to the cached FF-A endpoint ID. If the local injection attempt fails because no vCPU is online, hyp_pending remains set and notif_irq_raised remains clear. This keeps the RX-buffer-full notification pending until the guest retrieves it, without publishing a successful local IRQ state too early. Functional impact: RX-buffer-full remains pending in hyp_pending until FFA_NOTIFICATION_GET, and failed local NPI injection no longer leaves Xen thinking the interrupt was already raised. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v2: - add Jens R-b Changes since v1: - clarify that v1 exposed RX-buffer-full indirectly via vm_pending - document that v2 keeps the HYP pending indication until FFA_NOTIFICATION_GET - keep RX-buffer-full pending state stable across failed local NPI injection attempts --- xen/arch/arm/tee/ffa_notif.c | 56 ++++++++++++++++++++++++++-------- xen/arch/arm/tee/ffa_private.h | 15 +++++++-- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 07bc5cb3a430..a631481e3815 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -19,7 +19,7 @@ static bool __ro_after_init fw_notif_enabled; static unsigned int __ro_after_init notif_sri_irq; =20 -static void inject_notif_pending(struct domain *d) +static bool inject_notif_pending(struct domain *d) { struct vcpu *v; =20 @@ -33,13 +33,15 @@ static void inject_notif_pending(struct domain *d) if ( is_vcpu_online(v) ) { vgic_inject_irq(d, v, GUEST_FFA_NOTIF_PEND_INTR_ID, true); - return; + return true; } } =20 if ( printk_ratelimit() ) printk(XENLOG_G_DEBUG "%pd: ffa: can't inject NPI, all vCPUs offli= ne\n", d); + + return false; } =20 int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs) @@ -94,8 +96,15 @@ void ffa_handle_notification_info_get(struct cpu_user_re= gs *regs) =20 notif_pending =3D test_and_clear_bool(ctx->notif.secure_pending); if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + { notif_pending |=3D test_and_clear_bool(ctx->notif.vm_pending); =20 + spin_lock(&ctx->notif.notif_lock); + if ( ctx->notif.hyp_pending ) + notif_pending =3D true; + spin_unlock(&ctx->notif.notif_lock); + } + if ( notif_pending ) { /* A pending global notification for the guest */ @@ -174,12 +183,19 @@ void ffa_handle_notification_get(struct cpu_user_regs= *regs) w6 =3D resp.a6; } =20 - if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) && - flags & FFA_NOTIF_FLAG_BITMAP_HYP && - test_and_clear_bool(ctx->notif.buff_full_pending) ) + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) { - ACCESS_ONCE(ctx->notif.vm_pending) =3D false; - w7 =3D FFA_NOTIF_RX_BUFFER_FULL; + spin_lock(&ctx->notif.notif_lock); + + if ( (flags & FFA_NOTIF_FLAG_BITMAP_HYP) && ctx->notif.hyp_pending= ) + { + w7 =3D ctx->notif.hyp_pending; + ctx->notif.hyp_pending =3D 0; + if ( !ctx->notif.vm_pending ) + ctx->notif.notif_irq_raised =3D false; + } + + spin_unlock(&ctx->notif.notif_lock); } =20 ffa_set_regs(regs, FFA_SUCCESS_32, 0, w2, w3, w4, w5, w6, w7); @@ -211,9 +227,12 @@ void ffa_raise_rx_buffer_full(struct domain *d) if ( !ctx ) return; =20 - ACCESS_ONCE(ctx->notif.buff_full_pending) =3D true; - if ( !test_and_set_bool(ctx->notif.vm_pending) ) - inject_notif_pending(d); + spin_lock(&ctx->notif.notif_lock); + ctx->notif.hyp_pending |=3D FFA_NOTIF_RX_BUFFER_FULL; + if ( !ctx->notif.notif_irq_raised && + inject_notif_pending(d) ) + ctx->notif.notif_irq_raised =3D true; + spin_unlock(&ctx->notif.notif_lock); } #endif =20 @@ -426,12 +445,16 @@ void ffa_notif_init(void) =20 int ffa_notif_domain_init(struct domain *d) { + struct ffa_ctx *ctx =3D d->arch.tee; int32_t res; =20 + spin_lock_init(&ctx->notif.notif_lock); + ctx->notif.notif_irq_raised =3D false; + ctx->notif.hyp_pending =3D 0; + if ( fw_notif_enabled ) { - - res =3D ffa_notification_bitmap_create(ffa_get_vm_id(d), d->max_vc= pus); + res =3D ffa_notification_bitmap_create(ctx->ffa_id, d->max_vcpus); if ( res ) return -ENOMEM; } @@ -441,10 +464,17 @@ int ffa_notif_domain_init(struct domain *d) =20 void ffa_notif_domain_destroy(struct domain *d) { + struct ffa_ctx *ctx =3D d->arch.tee; + + spin_lock(&ctx->notif.notif_lock); + ctx->notif.notif_irq_raised =3D false; + ctx->notif.hyp_pending =3D 0; + spin_unlock(&ctx->notif.notif_lock); + /* * Call bitmap_destroy even if bitmap create failed as the SPMC will * return a DENIED error that we will ignore. */ if ( fw_notif_enabled ) - ffa_notification_bitmap_destroy(ffa_get_vm_id(d)); + ffa_notification_bitmap_destroy(ctx->ffa_id); } diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index e16bc0d83df3..025dfe6fed7b 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -340,9 +340,20 @@ struct ffa_ctx_notif { bool vm_pending; =20 /* - * True if domain has buffer full notification pending + * Lock protecting the hypervisor-managed notification state. */ - bool buff_full_pending; + spinlock_t notif_lock; + + /* + * Tracks whether a local notification pending interrupt was raised. + * Protected by notif_lock. + */ + bool notif_irq_raised; + + /* + * Bitmap of pending hypervisor notifications (for HYP bitmap queries). + */ + uint32_t hyp_pending; }; =20 struct ffa_ctx { --=20 2.53.0 From nobody Mon Sep 21 19:53:42 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; dkim=pass; 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=pass(p=none dis=none) header.from=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1788446651; cv=none; d=zohomail.com; s=zohoarc; b=TqdVs3enc61Pr+oue174qLMjVzQ0WR1pNiZ0gtjw63OdD9uWdiWOo/ukzQkBFC3krM0sUDqUeBOSELTXh81pXf7w5YVxR0DRgnaUTNDqusxXO6kbvn3LwJL8Fbvgmb1JRVdQlQXX42/RgHRiuRByMIRB0mfm1N6mPte64aKuOEg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788446651; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=raY0ZVBbRtKJAbMt7noSg9D1fw70/NvsLCmHMxGHMyc=; b=kYvMDu3DUwx3MuuBV2kGwHbqrDXU2YHQnEZ75A8HjaKzTUDCOEKgRdUMlRChWh34aaIDtTKZVbC+opnJuUI0n1UTazPMdpbDZdk9esMEg/FCiut4YuZKxf39VuFN1jGMVuijMMLmXR8knrJ8NTRW7FvkBdayWH18kTNDI2hLtic= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1788446651391167.47299209931919; Thu, 3 Sep 2026 07:44:11 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1407374.1640489 (Exim 4.92) (envelope-from ) id 1x28fP-0000z5-Ku; Thu, 03 Sep 2026 14:43:51 +0000 Received: by outflank-mailman (output) from mailman id 1407374.1640489; Thu, 03 Sep 2026 14:43:51 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fP-0000yr-H5; Thu, 03 Sep 2026 14:43:51 +0000 Received: by outflank-mailman (input) for mailman id 1407374; Thu, 03 Sep 2026 14:43:49 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fN-0000kY-Js for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 14:43:49 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1x28fN-0045Cl-0K for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 16:43:49 +0200 Received: from [10.42.69.8] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a998799-bab6-0a2a0a5309dd-0a2a4508ed7e-32 for ; Thu, 03 Sep 2026 16:43:48 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-c1860d.mxtls.expurgate.net with ESMTP (eXpurgate 4.57.1) (envelope-from ) id 6a9987a4-f659-0a2a45080019-d98c6eacd0c0-1 for ; Thu, 03 Sep 2026 16:43:48 +0200 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 EA32E1596; Thu, 3 Sep 2026 07:43:43 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.7.135]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6269A3F673; Thu, 3 Sep 2026 07:43:46 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=foss header.d=arm.com header.i="@arm.com" header.h="From:To:Cc:Subject:Date:In-Reply-To:References" DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1788446627; bh=1qC+KeWmCIuBxYNLKqeIe9W9yoXmdFcEs5sm74Rmt9Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CA6AvtqkAIE0H3PwHE+KDhP0lxFY63e/bqCYni+vjHqXGjOhHqO2/KE+eho2nOh5Z Gu4ZLmaxiVFWUReZZkehpC1/bFL2n6lcdD4bM6wV9apiT14j3t1pqZVATM1/kk8ZtY rsPekRlWrlFaohTbP6Rk6RVEvoaguYMOcBGt1K+I= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel , Jens Wiklander Subject: [PATCH v3 3/6] xen/arm: ffa: Tighten notification parameter validation Date: Thu, 3 Sep 2026 16:43:28 +0200 Message-ID: <980875f99fe01ea85f2e453ea447fd14f07c5f5a.1788268510.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-c1860d/1788446628-D4B7187B-4489A60F/0/0 X-purgate-type: clean X-purgate-size: 6058 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1788446653454158500 Content-Type: text/plain; charset="utf-8" The notification handlers still validate overlapping subsets of their inputs. BIND, UNBIND, and SET each decode caller and destination IDs locally, GET still accepts a non-zero receiver vCPU ID and reserved flag bits, and SET still accepts non-zero NS-virtual flags. BIND also treats unsupported non-zero flag encodings as a supported-feature failure instead of as malformed input. Add ffa_notif_validate_params() and use it to centralize the common caller/destination and non-zero bitmap checks for BIND, UNBIND, and SET. Also reject malformed GET and SET requests locally before touching cached state or forwarding anything to the SPMC. Keep BIND limited to global notifications and reject unsupported non-zero flag encodings with INVALID_PARAMETERS. - add a shared parameter validator for notification caller/destination checks - wire BIND and UNBIND through the shared helper and reject unsupported bind flag encodings with INVALID_PARAMETERS - reject non-zero receiver vCPU and reserved flag bits in FFA_NOTIFICATION_GET - reject non-zero flags in the NS-virtual FFA_NOTIFICATION_SET path Functional impact: malformed notification requests are rejected consistently earlier in the mediator. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v2: - none Changes since v1: - rename helper to ffa_notif_validate_params() - add R-b from Jens --- xen/arch/arm/tee/ffa_notif.c | 61 +++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index a631481e3815..1260f98a77e9 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -44,21 +44,40 @@ static bool inject_notif_pending(struct domain *d) return false; } =20 +static int32_t ffa_notif_validate_params(uint16_t dom_id, uint16_t caller_= id, + uint16_t dest_id, uint32_t bitmap= _lo, + uint32_t bitmap_hi) +{ + if ( caller_id !=3D dom_id || dest_id =3D=3D dom_id || !dest_id ) + return FFA_RET_INVALID_PARAMETERS; + + if ( !bitmap_lo && !bitmap_hi ) + return FFA_RET_INVALID_PARAMETERS; + + return FFA_RET_OK; +} + int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; + struct ffa_ctx *ctx =3D d->arch.tee; + int32_t ret; uint32_t src_dst =3D get_user_reg(regs, 1); uint32_t flags =3D get_user_reg(regs, 2); uint32_t bitmap_lo =3D get_user_reg(regs, 3); uint32_t bitmap_hi =3D get_user_reg(regs, 4); + uint16_t caller_id =3D src_dst & GENMASK(15, 0); + uint16_t dest_id =3D src_dst >> 16; =20 - if ( (src_dst & GENMASK(15, 0)) !=3D ffa_get_vm_id(d) ) + if ( flags ) /* Only global notifications are supported */ return FFA_RET_INVALID_PARAMETERS; =20 - if ( flags ) /* Only global notifications are supported */ - return FFA_RET_DENIED; + ret =3D ffa_notif_validate_params(ctx->ffa_id, caller_id, dest_id, + bitmap_lo, bitmap_hi); + if ( ret ) + return ret; =20 - if ( FFA_ID_IS_SECURE(src_dst >> 16) && fw_notif_enabled ) + if ( FFA_ID_IS_SECURE(dest_id) && fw_notif_enabled ) return ffa_simple_call(FFA_NOTIFICATION_BIND, src_dst, flags, bitmap_lo, bitmap_hi); =20 @@ -68,16 +87,22 @@ int32_t ffa_handle_notification_bind(struct cpu_user_re= gs *regs) int32_t ffa_handle_notification_unbind(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; + struct ffa_ctx *ctx =3D d->arch.tee; + int32_t ret; uint32_t src_dst =3D get_user_reg(regs, 1); uint32_t bitmap_lo =3D get_user_reg(regs, 3); uint32_t bitmap_hi =3D get_user_reg(regs, 4); + uint16_t caller_id =3D src_dst & GENMASK(15, 0); + uint16_t dest_id =3D src_dst >> 16; =20 - if ( (src_dst & GENMASK(15, 0)) !=3D ffa_get_vm_id(d) ) - return FFA_RET_INVALID_PARAMETERS; + ret =3D ffa_notif_validate_params(ctx->ffa_id, caller_id, dest_id, + bitmap_lo, bitmap_hi); + if ( ret ) + return ret; =20 - if ( FFA_ID_IS_SECURE(src_dst >> 16) && fw_notif_enabled ) - return ffa_simple_call(FFA_NOTIFICATION_UNBIND, src_dst, 0, bitma= p_lo, - bitmap_hi); + if ( FFA_ID_IS_SECURE(dest_id) && fw_notif_enabled ) + return ffa_simple_call(FFA_NOTIFICATION_UNBIND, src_dst, 0, bitmap= _lo, + bitmap_hi); =20 return FFA_RET_NOT_SUPPORTED; } @@ -144,6 +169,12 @@ void ffa_handle_notification_get(struct cpu_user_regs = *regs) return; } =20 + if ( recv >> 16 || (flags & GENMASK(31, 4)) ) + { + ffa_set_regs_error(regs, FFA_RET_INVALID_PARAMETERS); + return; + } + if ( fw_notif_enabled && (flags & ( FFA_NOTIF_FLAG_BITMAP_SP | FFA_NOTIF_FLAG_BITMAP_SPM )) ) { @@ -208,11 +239,19 @@ int32_t ffa_handle_notification_set(struct cpu_user_r= egs *regs) uint32_t flags =3D get_user_reg(regs, 2); uint32_t bitmap_lo =3D get_user_reg(regs, 3); uint32_t bitmap_hi =3D get_user_reg(regs, 4); + uint16_t caller_id =3D src_dst >> 16; + uint16_t dest_id =3D src_dst & GENMASK(15, 0); + int32_t ret; + + ret =3D ffa_notif_validate_params(ffa_get_vm_id(d), caller_id, dest_id, + bitmap_lo, bitmap_hi); + if ( ret ) + return ret; =20 - if ( (src_dst >> 16) !=3D ffa_get_vm_id(d) ) + if ( flags ) return FFA_RET_INVALID_PARAMETERS; =20 - if ( FFA_ID_IS_SECURE(src_dst & GENMASK(15, 0)) && fw_notif_enabled ) + if ( FFA_ID_IS_SECURE(dest_id) && fw_notif_enabled ) return ffa_simple_call(FFA_NOTIFICATION_SET, src_dst, flags, bitma= p_lo, bitmap_hi); =20 --=20 2.53.0 From nobody Mon Sep 21 19:53:42 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; dkim=pass; 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=pass(p=none dis=none) header.from=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1788446650; cv=none; d=zohomail.com; s=zohoarc; b=gu8V7ANRYp316m8elUJn00tJXHnGk3wgU3sBuDfVUdY+zSViPpsXXKMvvvHJ/pJJO9Nma9nQaYqTb3uyqSF91B4y67W99z4BUPcQ2hIwiX3fX9lOdU6BNPLVaYCBtQoVaLmmog06sAuEqFcDwmZI1M6nDlg6zpmbaJ6sV85RujI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788446650; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=WDYxZ23JlHtHU69stUUO79ZLAbsf3Ksj3/eehXQ3rnQ=; b=YHWRTtKri7suZeBAtdEuVj3ZUys4nr2iY2J8fgaHnd2MTjpyXYzn9+thkDih2DgmksK5gvuleu+R+zbHQB6CoCKDzzkyrbGrfmanrmzBPoG7hNgwEmuJJXOVbnxZQrJmlv9PqpiF+KIzsN1wZ3WmCL8pjMMbWhUympanJbaDb2E= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1788446649953871.0524565989557; Thu, 3 Sep 2026 07:44:09 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1407375.1640499 (Exim 4.92) (envelope-from ) id 1x28fR-0001Dj-36; Thu, 03 Sep 2026 14:43:53 +0000 Received: by outflank-mailman (output) from mailman id 1407375.1640499; Thu, 03 Sep 2026 14:43:53 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fQ-0001Db-UJ; Thu, 03 Sep 2026 14:43:52 +0000 Received: by outflank-mailman (input) for mailman id 1407375; Thu, 03 Sep 2026 14:43:51 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fP-0000yY-Eg for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 14:43:51 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1x28fO-007phI-Rd for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 16:43:50 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a9987a0-8faa-0a2a0a5109dd-0a2a4509a978-22 for ; Thu, 03 Sep 2026 16:43:50 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTP (eXpurgate 4.57.1) (envelope-from ) id 6a9987a6-be1a-0a2a45090019-d98c6eac8944-1 for ; Thu, 03 Sep 2026 16:43:50 +0200 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 E6D0E1D34; Thu, 3 Sep 2026 07:43:45 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.7.135]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 335423F673; Thu, 3 Sep 2026 07:43:47 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=foss header.d=arm.com header.i="@arm.com" header.h="From:To:Cc:Subject:Date:In-Reply-To:References" DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1788446629; bh=FIdh3x8TqhKm9Ak6XoWn7O6Wy2XrLZyhKI2PMzdoAio=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uc+XZYDJwzwQGdV5IBfpRcERfG2NYapspe9NV0I8nwm1avk1dMod5rLGJii06yXfl mwmv/U6vMu3lMK0xwZExilbPTVubydshkQGPchAWXgfq4K4AfZA5CoJsrlsgsjtyBP OvfshOMOKM2JiMxxnHH1IBdDp91zkBVqPqa9hqNA= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel , Jens Wiklander Subject: [PATCH v3 4/6] xen/arm: ffa: Preserve secure notification state when polling SPMC Date: Thu, 3 Sep 2026 16:43:29 +0200 Message-ID: <55fcc151f60b749e167e7cf4488bd315a22e5944.1788268510.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-bad1c0/1788446630-39EC6034-5813DE16/0/0 X-purgate-type: clean X-purgate-size: 7293 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1788446651635158500 Content-Type: text/plain; charset="utf-8" Secure pending state is latched when the SPMC raises the schedule receiver interrupt, but Xen currently clears that latch too aggressively. Guest FFA_NOTIFICATION_INFO_GET consumes secure_pending even though it only reports pending state, and secure FFA_NOTIFICATION_GET only clears the latch when both SP and SPM bitmaps are requested together. This can drop a pending indication before the receiver retrieves secure notifications, or keep INFO_GET reporting stale secure pending state after a successful GET. Keep secure_pending as a latched indication until secure notifications are actually retrieved. Guest FFA_NOTIFICATION_INFO_GET now reports the latched state without clearing it, while a successful secure FFA_NOTIFICATION_GET clears the latch regardless of which secure bitmap flags were requested. Also protect secure_pending with notif_lock, serialize SPMC INFO_GET polling behind notif_info_lock, and preserve the caller-visible INFO_GET success width. Functional impact: guest INFO_GET preserves the secure pending indication until secure notifications are retrieved, and successful secure GET clears the guest-visible pending latch. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v2: - add Jens R-b Changes since v1: - drop the defensive fw_notif_enabled guard in notif_sri_action() --- xen/arch/arm/tee/ffa_notif.c | 51 ++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 1260f98a77e9..e1cd852d1c53 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -18,6 +18,7 @@ =20 static bool __ro_after_init fw_notif_enabled; static unsigned int __ro_after_init notif_sri_irq; +static DEFINE_SPINLOCK(notif_info_lock); =20 static bool inject_notif_pending(struct domain *d) { @@ -111,6 +112,7 @@ void ffa_handle_notification_info_get(struct cpu_user_r= egs *regs) { struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; + uint32_t fid =3D get_user_reg(regs, 0); bool notif_pending; =20 if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !fw_notif_enabled ) @@ -119,7 +121,10 @@ void ffa_handle_notification_info_get(struct cpu_user_= regs *regs) return; } =20 - notif_pending =3D test_and_clear_bool(ctx->notif.secure_pending); + spin_lock(&ctx->notif.notif_lock); + notif_pending =3D ctx->notif.secure_pending; + spin_unlock(&ctx->notif.notif_lock); + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) { notif_pending |=3D test_and_clear_bool(ctx->notif.vm_pending); @@ -133,7 +138,9 @@ void ffa_handle_notification_info_get(struct cpu_user_r= egs *regs) if ( notif_pending ) { /* A pending global notification for the guest */ - ffa_set_regs(regs, FFA_SUCCESS_64, 0, + ffa_set_regs(regs, + smccc_is_conv_64(fid) ? FFA_SUCCESS_64 : FFA_SUCCESS_= 32, + 0, 1U << FFA_NOTIF_INFO_GET_ID_COUNT_SHIFT, ffa_get_vm_i= d(d), 0, 0, 0, 0); } @@ -156,6 +163,8 @@ void ffa_handle_notification_get(struct cpu_user_regs *= regs) uint32_t w5 =3D 0; uint32_t w6 =3D 0; uint32_t w7 =3D 0; + uint32_t secure_flags =3D flags & ( FFA_NOTIF_FLAG_BITMAP_SP | + FFA_NOTIF_FLAG_BITMAP_SPM ); =20 if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !fw_notif_enabled ) { @@ -175,27 +184,16 @@ void ffa_handle_notification_get(struct cpu_user_regs= *regs) return; } =20 - if ( fw_notif_enabled && (flags & ( FFA_NOTIF_FLAG_BITMAP_SP | - FFA_NOTIF_FLAG_BITMAP_SPM )) ) + if ( fw_notif_enabled && secure_flags ) { struct arm_smccc_1_2_regs arg =3D { .a0 =3D FFA_NOTIFICATION_GET, .a1 =3D recv, - .a2 =3D flags & ( FFA_NOTIF_FLAG_BITMAP_SP | - FFA_NOTIF_FLAG_BITMAP_SPM ), + .a2 =3D secure_flags, }; struct arm_smccc_1_2_regs resp; int32_t e; =20 - /* - * Clear secure pending if both FFA_NOTIF_FLAG_BITMAP_SP and - * FFA_NOTIF_FLAG_BITMAP_SPM are set since secure world can't have - * any more pending notifications. - */ - if ( ( flags & FFA_NOTIF_FLAG_BITMAP_SP ) && - ( flags & FFA_NOTIF_FLAG_BITMAP_SPM ) ) - ACCESS_ONCE(ctx->notif.secure_pending) =3D false; - arm_smccc_1_2_smc(&arg, &resp); e =3D ffa_get_ret_code(&resp); if ( e ) @@ -212,6 +210,10 @@ void ffa_handle_notification_get(struct cpu_user_regs = *regs) =20 if ( flags & FFA_NOTIF_FLAG_BITMAP_SPM ) w6 =3D resp.a6; + + spin_lock(&ctx->notif.notif_lock); + ctx->notif.secure_pending =3D false; + spin_unlock(&ctx->notif.notif_lock); } =20 if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) @@ -356,7 +358,10 @@ static void notif_vm_pend_intr(uint16_t vm_id) * guarantees that the data structure isn't freed while we're accessing * it. */ - ACCESS_ONCE(ctx->notif.secure_pending) =3D true; + spin_lock(&ctx->notif.notif_lock); + ctx->notif.secure_pending =3D true; + spin_unlock(&ctx->notif.notif_lock); + inject_notif_pending(d); =20 out_unlock: @@ -375,11 +380,15 @@ static void notif_sri_action(void *unused) unsigned int n; int32_t res; =20 - do { + spin_lock(¬if_info_lock); + + do + { arm_smccc_1_2_smc(&arg, &resp); res =3D ffa_get_ret_code(&resp); if ( res ) { + spin_unlock(¬if_info_lock); if ( res !=3D FFA_RET_NO_DATA && printk_ratelimit() ) printk(XENLOG_WARNING "ffa: notification info get failed: error %d\n", re= s); @@ -393,7 +402,7 @@ static void notif_sri_action(void *unused) id_pos =3D 0; for ( n =3D 0; n < list_count; n++ ) { - unsigned int count =3D ((ids_count >> 2 * n) & 0x3) + 1; + unsigned int count =3D ((ids_count >> (2 * n)) & 0x3) + 1; uint16_t vm_id =3D get_id_from_resp(&resp, id_pos); =20 notif_vm_pend_intr(vm_id); @@ -401,7 +410,9 @@ static void notif_sri_action(void *unused) id_pos +=3D count; } =20 - } while (resp.a2 & FFA_NOTIF_INFO_GET_MORE_FLAG); + } while ( resp.a2 & FFA_NOTIF_INFO_GET_MORE_FLAG ); + + spin_unlock(¬if_info_lock); } =20 static DECLARE_TASKLET(notif_sri_tasklet, notif_sri_action, NULL); @@ -489,6 +500,7 @@ int ffa_notif_domain_init(struct domain *d) =20 spin_lock_init(&ctx->notif.notif_lock); ctx->notif.notif_irq_raised =3D false; + ctx->notif.secure_pending =3D false; ctx->notif.hyp_pending =3D 0; =20 if ( fw_notif_enabled ) @@ -507,6 +519,7 @@ void ffa_notif_domain_destroy(struct domain *d) =20 spin_lock(&ctx->notif.notif_lock); ctx->notif.notif_irq_raised =3D false; + ctx->notif.secure_pending =3D false; ctx->notif.hyp_pending =3D 0; spin_unlock(&ctx->notif.notif_lock); =20 --=20 2.53.0 From nobody Mon Sep 21 19:53:42 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; dkim=pass; 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=pass(p=none dis=none) header.from=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1788446656; cv=none; d=zohomail.com; s=zohoarc; b=AdyuBVUAmDah/+hti+yObjS6/TSGFFKXaldiLrj1ir5g0WCgLC4Xo5IuImirKKw//22zaTaaE+u+tJSXzGfsQqY9KrFCqzHE+mE7tsyVMHpDyRNq/pKfYe+Sv5YG0+qZ7NThq3BOFv2Sisk43SdwBKzQFrxG7zI3ZM8aOwJ5H8M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788446656; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=S+Yky0aRO/D1GCIUIKjNMKBf+XmEM10xIGnhiISf0ME=; b=mSVtKdH5aE7nuBfI6FDJB/qEmtxmZdJG/Z0WYhbQx70zaqR7W7Zd+SjixTNOReXD4oF9pH/nf8PjyY0tJq9LVzWgE7u6Bkgb2zNcKA3hmDDqz4dfF0vaH9zabLMIhJpiHSVmf0ng4xFb/Iga0623LLHZxoItGBzjzl1zEd4Nbe0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1788446656900931.1822735961966; Thu, 3 Sep 2026 07:44:16 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1407376.1640507 (Exim 4.92) (envelope-from ) id 1x28fS-0001TD-AP; Thu, 03 Sep 2026 14:43:54 +0000 Received: by outflank-mailman (output) from mailman id 1407376.1640507; Thu, 03 Sep 2026 14:43:54 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fS-0001SI-6S; Thu, 03 Sep 2026 14:43:54 +0000 Received: by outflank-mailman (input) for mailman id 1407376; Thu, 03 Sep 2026 14:43:53 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fR-0001De-4Y for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 14:43:53 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1x28fQ-00Ap6r-HT for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 16:43:52 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a998797-e002-0a2a0a5209dd-0a2a4504af4a-32 for ; Thu, 03 Sep 2026 16:43:52 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-ebf023.mxtls.expurgate.net with ESMTP (eXpurgate 4.57.1) (envelope-from ) id 6a9987a7-b57f-0a2a45040019-d98c6eac884c-1 for ; Thu, 03 Sep 2026 16:43:52 +0200 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 A1BE01650; Thu, 3 Sep 2026 07:43:47 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.7.135]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 123683F673; Thu, 3 Sep 2026 07:43:49 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=foss header.d=arm.com header.i="@arm.com" header.h="From:To:Cc:Subject:Date:In-Reply-To:References" DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1788446631; bh=pa6oZ8m/24AdXnyLzD3DBAmh8KUG2PzE4sIQhu9ry14=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OGyb6v0ZeL6+rEj4lNyQK7K8LIkgDb74qkB/mDgcShYXm7n1ZdWBM1aTRxbC7hraq nDrvbQFoLIb07t6/c9MzbfaJ+m6aO7iO+tBOusMSh26oLb+1mUp7rMjDL4iKL6OHKR BrvH3LLDdMWYVmSvdGI2O9locGZAG4PAIsrplCjY= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel , Jens Wiklander Subject: [PATCH v3 5/6] xen/arm: ffa: Track VM notification bindings locally Date: Thu, 3 Sep 2026 16:43:30 +0200 Message-ID: <3b679d45c4a3fda4763112bc8570fa53129f3883.1788268510.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-ebf023/1788446632-C26CAB50-5F136E49/0/0 X-purgate-type: clean X-purgate-size: 7651 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1788446657458158500 Content-Type: text/plain; charset="utf-8" VM-to-VM notifications need receiver-side bind state so Xen can validate which sender owns each notification bit. Non-secure BIND and UNBIND requests currently have no local state and cannot enforce that contract. Add per-bit VM notification binding state to struct ffa_ctx_notif and use it to handle non-secure BIND and UNBIND requests when CONFIG_FFA_VM_TO_VM is enabled. The update helper validates the whole request under notif_lock before mutating anything, denies bind or unbind when a bit is pending, rejects rebinding to a different sender, and keeps rebinding to the same sender idempotent. Promote vm_pending to a bitmap so the bind logic can reason per notification ID, use that bitmap directly when reporting pending state, and initialize and clear the new VM notification state during domain init and teardown. Functional impact: when CONFIG_FFA_VM_TO_VM is enabled, Xen tracks VM notification bindings locally and validates non-secure bind and unbind requests against that state. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes since v2: - add Jens R-b Changes since v1: - use memset() to clear vm_bind[] in init/destroy - replace the file-scope #error check with BUILD_BUG_ON() --- xen/arch/arm/tee/ffa_notif.c | 96 ++++++++++++++++++++++++++++++---- xen/arch/arm/tee/ffa_private.h | 11 ++-- 2 files changed, 94 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index e1cd852d1c53..a841c8f8d747 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include =20 @@ -58,6 +59,54 @@ static int32_t ffa_notif_validate_params(uint16_t dom_id= , uint16_t caller_id, return FFA_RET_OK; } =20 +static int32_t ffa_notif_update_vm_binding(struct ffa_ctx *ctx, + uint16_t dest_id, uint64_t bitm= ap, + bool bind) +{ + unsigned int id; + int32_t ret =3D FFA_RET_OK; + + spin_lock(&ctx->notif.notif_lock); + + for ( id =3D 0; id < FFA_NUM_VM_NOTIF; id++ ) + { + if ( !(bitmap & BIT(id, ULL)) ) + continue; + + if ( ctx->notif.vm_pending & BIT(id, ULL) ) + { + ret =3D FFA_RET_DENIED; + goto out_unlock; + } + + if ( bind ) + { + if ( ctx->notif.vm_bind[id] !=3D 0 && + ctx->notif.vm_bind[id] !=3D dest_id ) + { + ret =3D FFA_RET_DENIED; + goto out_unlock; + } + } + else if ( ctx->notif.vm_bind[id] !=3D dest_id ) + { + ret =3D FFA_RET_DENIED; + goto out_unlock; + } + } + + for ( id =3D 0; id < FFA_NUM_VM_NOTIF; id++ ) + { + if ( bitmap & BIT(id, ULL) ) + ctx->notif.vm_bind[id] =3D bind ? dest_id : 0; + } + +out_unlock: + spin_unlock(&ctx->notif.notif_lock); + + return ret; +} + int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; @@ -78,11 +127,21 @@ int32_t ffa_handle_notification_bind(struct cpu_user_r= egs *regs) if ( ret ) return ret; =20 - if ( FFA_ID_IS_SECURE(dest_id) && fw_notif_enabled ) - return ffa_simple_call(FFA_NOTIFICATION_BIND, src_dst, flags, - bitmap_lo, bitmap_hi); + if ( FFA_ID_IS_SECURE(dest_id) ) + { + if ( fw_notif_enabled ) + return ffa_simple_call(FFA_NOTIFICATION_BIND, src_dst, flags, + bitmap_lo, bitmap_hi); =20 - return FFA_RET_NOT_SUPPORTED; + return FFA_RET_NOT_SUPPORTED; + } + + if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + return FFA_RET_NOT_SUPPORTED; + + return ffa_notif_update_vm_binding(ctx, dest_id, + ((uint64_t)bitmap_hi << 32) | bitma= p_lo, + true); } =20 int32_t ffa_handle_notification_unbind(struct cpu_user_regs *regs) @@ -101,11 +160,21 @@ int32_t ffa_handle_notification_unbind(struct cpu_use= r_regs *regs) if ( ret ) return ret; =20 - if ( FFA_ID_IS_SECURE(dest_id) && fw_notif_enabled ) - return ffa_simple_call(FFA_NOTIFICATION_UNBIND, src_dst, 0, bitmap= _lo, - bitmap_hi); + if ( FFA_ID_IS_SECURE(dest_id) ) + { + if ( fw_notif_enabled ) + return ffa_simple_call(FFA_NOTIFICATION_UNBIND, src_dst, 0, + bitmap_lo, bitmap_hi); =20 - return FFA_RET_NOT_SUPPORTED; + return FFA_RET_NOT_SUPPORTED; + } + + if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + return FFA_RET_NOT_SUPPORTED; + + return ffa_notif_update_vm_binding(ctx, dest_id, + ((uint64_t)bitmap_hi << 32) | bitma= p_lo, + false); } =20 void ffa_handle_notification_info_get(struct cpu_user_regs *regs) @@ -127,9 +196,10 @@ void ffa_handle_notification_info_get(struct cpu_user_= regs *regs) =20 if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) { - notif_pending |=3D test_and_clear_bool(ctx->notif.vm_pending); - spin_lock(&ctx->notif.notif_lock); + if ( ctx->notif.vm_pending ) + notif_pending =3D true; + if ( ctx->notif.hyp_pending ) notif_pending =3D true; spin_unlock(&ctx->notif.notif_lock); @@ -498,9 +568,13 @@ int ffa_notif_domain_init(struct domain *d) struct ffa_ctx *ctx =3D d->arch.tee; int32_t res; =20 + BUILD_BUG_ON(FFA_NUM_VM_NOTIF > 64); + spin_lock_init(&ctx->notif.notif_lock); ctx->notif.notif_irq_raised =3D false; ctx->notif.secure_pending =3D false; + ctx->notif.vm_pending =3D 0; + memset(ctx->notif.vm_bind, 0, sizeof(ctx->notif.vm_bind)); ctx->notif.hyp_pending =3D 0; =20 if ( fw_notif_enabled ) @@ -520,6 +594,8 @@ void ffa_notif_domain_destroy(struct domain *d) spin_lock(&ctx->notif.notif_lock); ctx->notif.notif_irq_raised =3D false; ctx->notif.secure_pending =3D false; + ctx->notif.vm_pending =3D 0; + memset(ctx->notif.vm_bind, 0, sizeof(ctx->notif.vm_bind)); ctx->notif.hyp_pending =3D 0; spin_unlock(&ctx->notif.notif_lock); =20 diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 025dfe6fed7b..30c064e2dc30 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -236,6 +236,7 @@ #define FFA_NOTIF_INFO_GET_ID_COUNT_MASK 0x1F =20 #define FFA_NOTIF_RX_BUFFER_FULL BIT(0, U) +#define FFA_NUM_VM_NOTIF 64U =20 /* Feature IDs used with FFA_FEATURES */ #define FFA_FEATURE_NOTIF_PEND_INTR 0x1U @@ -334,10 +335,14 @@ struct ffa_ctx_notif { bool secure_pending; =20 /* - * True if domain is reported by FFA_NOTIFICATION_INFO_GET to have - * pending notifications from VMs (including framework ones). + * Bitmap of pending notifications from VMs (including framework ones). + */ + uint64_t vm_pending; + + /* + * Source endpoint bound to each VM notification ID (0 means unbound). */ - bool vm_pending; + uint16_t vm_bind[FFA_NUM_VM_NOTIF]; =20 /* * Lock protecting the hypervisor-managed notification state. --=20 2.53.0 From nobody Mon Sep 21 19:53:42 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; dkim=pass; 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=pass(p=none dis=none) header.from=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1788446651; cv=none; d=zohomail.com; s=zohoarc; b=g3VokuitOAF0Bwr3CLnsx/m8iAJ9Ex0Rc6Ygj+Js7quauRXLr84hAx6MMBnIL3snmmQGR0d7yAEvUcobRqkxH88CoUxMx4Q4hzs8KPF8sLBD1vTgCWOHFFIJMAoUzLr5adDIUJlbcjGNxhNi/4I6WDac4/9R5Akbq9WJIeoSzd0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788446651; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=modWJhQcOJrL0dHkobBnfF1syPf2yZ63WFkJgwbl2cc=; b=Qhq3BlQn+2xowZEfujYQ4gCvUms2eMC8DSWYVsDcGYmTXu28QcyJIwAo268n6oqaWXcgiuKV0TQw+8804SB38SahcdSdmZuMm1LFCt9ytWVhSs1SL/4C3rbFZ6uoiSZ7llA8166Ia6a3SMwQw3kwVqUZ9/Fj2O9zzO7lxpXb45Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1788446651938467.0514226131784; Thu, 3 Sep 2026 07:44:11 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1407378.1640516 (Exim 4.92) (envelope-from ) id 1x28fU-0001kc-LY; Thu, 03 Sep 2026 14:43:56 +0000 Received: by outflank-mailman (output) from mailman id 1407378.1640516; Thu, 03 Sep 2026 14:43:56 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fU-0001kV-GP; Thu, 03 Sep 2026 14:43:56 +0000 Received: by outflank-mailman (input) for mailman id 1407378; Thu, 03 Sep 2026 14:43:54 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1x28fS-0001Wj-Op for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 14:43:54 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1x28fS-00Ap6r-5U for xen-devel@lists.xenproject.org; Thu, 03 Sep 2026 16:43:54 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a9987a6-e002-0a2a0a5209dd-0a2a4503a126-8 for ; Thu, 03 Sep 2026 16:43:54 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-33051d.mxtls.expurgate.net with ESMTP (eXpurgate 4.57.1) (envelope-from ) id 6a9987a9-fae8-0a2a45030019-d98c6eacc06c-1 for ; Thu, 03 Sep 2026 16:43:53 +0200 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 3CE5E1596; Thu, 3 Sep 2026 07:43:49 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.7.135]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DA9213F673; Thu, 3 Sep 2026 07:43:51 -0700 (PDT) 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=foss header.d=arm.com header.i="@arm.com" header.h="From:To:Cc:Subject:Date:In-Reply-To:References" DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1788446633; bh=2RiwZlyuUPZr3BL6OvfCnly9DXHp8ba50e2fDBTUIes=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qUyqMKitmr54/ha23EVQ7gzVumVCjg9/UqtgVxkMlMyEFBP+egP62l2+taWCE/6fO dQlOaK+vGHPJJXq4JD23x4YuEZ4hE5ERmGlG7grsWFE6zyaOVuC7xmL5aig7AS1nKX vb3jNSdbTbj+MCnNduVxF6UryG0hN+7lsKLR/Njo= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v3 6/6] xen/arm: ffa: Deliver VM-to-VM notifications locally Date: Thu, 3 Sep 2026 16:43:31 +0200 Message-ID: <24033eeb87446cda8c91f27a453317417328fd5f.1788268510.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-33051d/1788446634-74E874E9-6A154D21/0/0 X-purgate-type: clean X-purgate-size: 9857 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1788446653462158500 Content-Type: text/plain; charset="utf-8" VM notification binding and pending tracking exist for non-secure endpoints, but FFA_NOTIFICATION_SET still only forwards secure destinations to the SPMC. Non-secure VMs therefore cannot receive notifications from other VMs. Local NPI delivery also needs explicit re-arm tracking so repeated raises are not lost while the interrupt is already pending. Add a local VM notification delivery path for non-secure destinations. notification_set_vm() resolves the destination endpoint, verifies that every requested bit is bound to the sender, sets the receiver's vm_pending bitmap under notif_lock, and raises an NPI only when local pending state is not already armed. Track whether a local NPI is already armed with notif_irq_raised, clear that state once both VM and hypervisor pending bitmaps are drained, and keep notif_lock held across the VM notification injection attempt. If no destination vCPU is online, leave the pending bits set and keep notif_irq_raised clear so delivery can be retried later. Also expose firmware notification availability so FFA_FEATURES only advertises notification support when it is actually provided by the firmware or by CONFIG_FFA_VM_TO_VM. Functional impact: when CONFIG_FFA_VM_TO_VM is enabled, non-secure FFA_NOTIFICATION_SET delivers VM-to-VM notifications locally and keeps NPI delivery reliable across repeated raises. Signed-off-by: Bertrand Marquis --- Changes since v2: - remove redundant irq raised cleanup (Jens) Changes since v1: - serialize notification_set_vm() state updates with the NPI attempt - keep pending VM notifications set when local injection fails --- xen/arch/arm/tee/ffa.c | 24 ++++++++-- xen/arch/arm/tee/ffa_notif.c | 84 ++++++++++++++++++++++++++++++++-- xen/arch/arm/tee/ffa_private.h | 17 ++++--- 3 files changed, 107 insertions(+), 18 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 1fe33f26454a..7fe021049cba 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -39,8 +39,13 @@ * o FFA_MSG_SEND_DIRECT_REQ: * - only supported from a VM to an SP * o FFA_NOTIFICATION_*: + * - only supported when firmware notifications are enabled or VM-to-VM + * support is built in * - only supports global notifications, that is, per vCPU notifications - * are not supported + * are not supported and secure per-vCPU notification information is + * not forwarded + * - the source endpoint ID reported for a notification may no longer + * exist by the time the receiver consumes it * - doesn't support signalling the secondary scheduler of pending * notification for secure partitions * - doesn't support notifications for Xen itself @@ -245,6 +250,8 @@ static void handle_features(struct cpu_user_regs *regs) uint32_t a1 =3D get_user_reg(regs, 1); struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; + bool notif_supported =3D IS_ENABLED(CONFIG_FFA_VM_TO_VM) || + ffa_notif_fw_enabled(); =20 /* * FFA_FEATURES defines w2 as input properties only for specific @@ -343,10 +350,16 @@ static void handle_features(struct cpu_user_regs *reg= s) =20 break; case FFA_FEATURE_NOTIF_PEND_INTR: - ffa_set_regs_success(regs, GUEST_FFA_NOTIF_PEND_INTR_ID, 0); + if ( notif_supported ) + ffa_set_regs_success(regs, GUEST_FFA_NOTIF_PEND_INTR_ID, 0); + else + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); break; case FFA_FEATURE_SCHEDULE_RECV_INTR: - ffa_set_regs_success(regs, GUEST_FFA_SCHEDULE_RECV_INTR_ID, 0); + if ( notif_supported ) + ffa_set_regs_success(regs, GUEST_FFA_SCHEDULE_RECV_INTR_ID, 0); + else + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); break; case FFA_PARTITION_INFO_GET_REGS: if ( ACCESS_ONCE(ctx->guest_vers) >=3D FFA_VERSION_1_2 ) @@ -361,7 +374,10 @@ static void handle_features(struct cpu_user_regs *regs) case FFA_NOTIFICATION_SET: case FFA_NOTIFICATION_INFO_GET_32: case FFA_NOTIFICATION_INFO_GET_64: - ffa_set_regs_success(regs, 0, 0); + if ( notif_supported ) + ffa_set_regs_success(regs, 0, 0); + else + ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); break; default: ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index a841c8f8d747..4ca2f75605bb 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -21,6 +21,11 @@ static bool __ro_after_init fw_notif_enabled; static unsigned int __ro_after_init notif_sri_irq; static DEFINE_SPINLOCK(notif_info_lock); =20 +bool ffa_notif_fw_enabled(void) +{ + return fw_notif_enabled; +} + static bool inject_notif_pending(struct domain *d) { struct vcpu *v; @@ -107,6 +112,55 @@ out_unlock: return ret; } =20 +/* + * Deliver a VM-to-VM notification. ctx->notif.notif_lock protects + * vm_bind/vm_pending so callers must not hold it already. + */ +static int32_t notification_set_vm(uint16_t dst_id, uint16_t src_id, + uint32_t flags, uint64_t bitmap) +{ + struct domain *dst_d; + struct ffa_ctx *dst_ctx; + unsigned int id; + int32_t ret; + + if ( flags ) + return FFA_RET_INVALID_PARAMETERS; + + ret =3D ffa_endpoint_domain_lookup(dst_id, &dst_d, &dst_ctx); + if ( ret ) + return ret; + + ret =3D FFA_RET_OK; + + spin_lock(&dst_ctx->notif.notif_lock); + + for ( id =3D 0; id < FFA_NUM_VM_NOTIF; id++ ) + { + if ( !(bitmap & BIT(id, ULL)) ) + continue; + + if ( dst_ctx->notif.vm_bind[id] !=3D src_id ) + { + ret =3D FFA_RET_DENIED; + goto out_unlock; + } + } + + dst_ctx->notif.vm_pending |=3D bitmap; + if ( !dst_ctx->notif.notif_irq_raised && + (dst_ctx->notif.vm_pending || dst_ctx->notif.hyp_pending) && + inject_notif_pending(dst_d) ) + dst_ctx->notif.notif_irq_raised =3D true; + +out_unlock: + spin_unlock(&dst_ctx->notif.notif_lock); + + rcu_unlock_domain(dst_d); + + return ret; +} + int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; @@ -288,16 +342,28 @@ void ffa_handle_notification_get(struct cpu_user_regs= *regs) =20 if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) { + bool pending; + spin_lock(&ctx->notif.notif_lock); =20 if ( (flags & FFA_NOTIF_FLAG_BITMAP_HYP) && ctx->notif.hyp_pending= ) { w7 =3D ctx->notif.hyp_pending; ctx->notif.hyp_pending =3D 0; - if ( !ctx->notif.vm_pending ) - ctx->notif.notif_irq_raised =3D false; } =20 + if ( (flags & FFA_NOTIF_FLAG_BITMAP_VM) && ctx->notif.vm_pending ) + { + w4 =3D (uint32_t)(ctx->notif.vm_pending & GENMASK(31, 0)); + w5 =3D (uint32_t)((ctx->notif.vm_pending >> 32) & GENMASK(31, = 0)); + ctx->notif.vm_pending =3D 0; + } + + pending =3D (ctx->notif.hyp_pending !=3D 0) || + (ctx->notif.vm_pending !=3D 0); + if ( !pending ) + ctx->notif.notif_irq_raised =3D false; + spin_unlock(&ctx->notif.notif_lock); } =20 @@ -323,9 +389,17 @@ int32_t ffa_handle_notification_set(struct cpu_user_re= gs *regs) if ( flags ) return FFA_RET_INVALID_PARAMETERS; =20 - if ( FFA_ID_IS_SECURE(dest_id) && fw_notif_enabled ) - return ffa_simple_call(FFA_NOTIFICATION_SET, src_dst, flags, bitma= p_lo, - bitmap_hi); + if ( FFA_ID_IS_SECURE(dest_id) ) + { + if ( fw_notif_enabled ) + return ffa_simple_call(FFA_NOTIFICATION_SET, src_dst, flags, + bitmap_lo, bitmap_hi); + } + else if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + { + return notification_set_vm(dest_id, caller_id, flags, + ((uint64_t)bitmap_hi << 32) | bitmap_lo= ); + } =20 return FFA_RET_NOT_SUPPORTED; } diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 30c064e2dc30..7096207b0528 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -340,20 +340,18 @@ struct ffa_ctx_notif { uint64_t vm_pending; =20 /* - * Source endpoint bound to each VM notification ID (0 means unbound). + * Tracks whether an NPI has been raised for local pending notificatio= ns. + * Protected by notif_lock. */ - uint16_t vm_bind[FFA_NUM_VM_NOTIF]; + bool notif_irq_raised; =20 /* - * Lock protecting the hypervisor-managed notification state. + * Source endpoint bound to each VM notification ID (0 means unbound). */ - spinlock_t notif_lock; + uint16_t vm_bind[FFA_NUM_VM_NOTIF]; =20 - /* - * Tracks whether a local notification pending interrupt was raised. - * Protected by notif_lock. - */ - bool notif_irq_raised; + /* Lock protecting local notification state. */ + spinlock_t notif_lock; =20 /* * Bitmap of pending hypervisor notifications (for HYP bitmap queries). @@ -495,6 +493,7 @@ void ffa_notif_init(void); void ffa_notif_init_interrupt(void); int ffa_notif_domain_init(struct domain *d); void ffa_notif_domain_destroy(struct domain *d); +bool ffa_notif_fw_enabled(void); =20 int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs); int32_t ffa_handle_notification_unbind(struct cpu_user_regs *regs); --=20 2.53.0