From nobody Thu May 7 07:48:57 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=1777441488; cv=none; d=zohomail.com; s=zohoarc; b=liKMaZVB+lb/k+1EvhJq/3+zCzY6OvzputGSung12DpXCGUzbB473UgPvwnCzH+pGw20yjGFdGMuX6bOtukdJrrR7DVnyl1+bUgOEENDOA2NJ3QdhT/vxRY2tJhkh2fh8pXHBdwIvP66U+7AsTEQe7nrSdd6YZZyLycyUJrQEEY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777441488; 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=WKKSczJlZI72MKqmSxli1VuWsQHX4BCNVKQfFoYPfwY=; b=LN2vm6bxuacDHFta3ZHfNgN5ry+U62PfWGQbNHEpJRwbEOe/2h7qFWkpjG6JG9LbkAwMtjh+sW+bD27OLEDotaBj5M9uRx/Upn4Hna4MhOOp9QWVS+bmK8pwzhiwAcVXxFSyAKXtoEF83rx3hmSEwIKAU7HKW4TQSIYMrX2f004= 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 1777441487750179.86066317670281; Tue, 28 Apr 2026 22:44:47 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1296939.1573072 (Exim 4.92) (envelope-from ) id 1wHxiR-00084z-LT; Wed, 29 Apr 2026 05:44:07 +0000 Received: by outflank-mailman (output) from mailman id 1296939.1573072; Wed, 29 Apr 2026 05:44:07 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiR-00084s-Ia; Wed, 29 Apr 2026 05:44:07 +0000 Received: by outflank-mailman (input) for mailman id 1296939; Wed, 29 Apr 2026 05:44:06 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiQ-00084I-MM for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 05:44:06 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wHxiQ-003p6b-21 for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 07:44:06 +0200 Received: from [10.42.69.10] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69f19aa3-e002-0a2a0a5209dd-0a2a450ae8ea-2 for ; Wed, 29 Apr 2026 07:44:06 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-4011c0.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69f19aa5-56b3-0a2a450a0019-d98c6eac86d2-1 for ; Wed, 29 Apr 2026 07:44:05 +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 209DA2BCE; Tue, 28 Apr 2026 22:43:59 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.90.163]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3EAE33F62B; Tue, 28 Apr 2026 22:44:03 -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=1777441444; bh=D0cWhXb5cOQnh67SWhy+Xw1f5uxdZNslX4hyB6LTlbM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mP5yOT8W5xF9s2AHoIo0HBtQluRfUBB5R3yG9h/hpcntrzT1TI4lVdaFvPbZ22Ua2 mIvQ9MiuE5m5zwRgaUmg3JSK4ROlrF2xVxlIYmLWlag0x2D6lASoV+qnRQZWc/5ccr bsi8k3W4LWPaLtKHmF2ZECs1o56euNT4DIGSZ11A= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 1/6] xen/arm: ffa: Fix NPI injection when vcpu0 is offline Date: Wed, 29 Apr 2026 07:43:22 +0200 Message-ID: <2a36253fca9c23681fea0d5493faeb3044de558d.1776955622.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-4011c0/1777441446-4415A8B7-5EAC21DC/0/0 X-purgate-type: clean X-purgate-size: 3404 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1777441490106158500 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 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 Thu May 7 07:48:57 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=1777441490; cv=none; d=zohomail.com; s=zohoarc; b=KmOKv89wsTkB/gmlEIEjjZNngQaRGdo1FYqQQFiDMSyYUuQWA2wIxd3A+jhhXBTQ+dGnl0f0DSaTiyTRtgKAkQ43GjNnAqqs8Cjd2bffR8xUvqyEa3b4KTTHyIe+dKRzGkIpjVeszCxdG0EwbyIrciLgVMJPZVS4WlDAJPbE+Hc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777441490; 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=HZrwRA5VNHqj01+MxnvaenWghzavARtkdTgaFx5fOZc=; b=oBzto7ghC97g+u/spstlUHKFyLLyK9d1fHTN09MB3RF1OUVR02hlHfTfGRmFg2UOCNJOYcuVMTiE+IT4yVnFB8fEZf8xXXErR/guNfKSfU6sxpBD+yUWCc4rKiGnRaZeENEaMA87fFgTCEimlDRgb62UmYD5BuU/mEjcnlUldoU= 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 177744149015254.35443528404005; Tue, 28 Apr 2026 22:44:50 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1296942.1573082 (Exim 4.92) (envelope-from ) id 1wHxiT-0008J8-Rw; Wed, 29 Apr 2026 05:44:09 +0000 Received: by outflank-mailman (output) from mailman id 1296942.1573082; Wed, 29 Apr 2026 05:44:09 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiT-0008Iz-P6; Wed, 29 Apr 2026 05:44:09 +0000 Received: by outflank-mailman (input) for mailman id 1296942; Wed, 29 Apr 2026 05:44:08 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiS-0008En-GJ for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 05:44:08 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wHxiR-0078Bd-S1 for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 07:44:07 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69f19a9f-5cb7-0a2a0a5109dd-0a2a4507ede2-12 for ; Wed, 29 Apr 2026 07:44:07 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69f19aa6-229c-0a2a45070019-d98c6eacb28e-1 for ; Wed, 29 Apr 2026 07:44:07 +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 C745D328D; Tue, 28 Apr 2026 22:44:00 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.90.163]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id EB45A3F62B; Tue, 28 Apr 2026 22:44:04 -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=1777441446; bh=IvYNqDbera/Ke8I0F2UPOw6J8/rPOohK8qd0lYFvQZM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=inm5aBwxI6owTAxlvk6jPjRmOK55M16BCQgB5DNdQ/iBYs8C7yhJXqo06rL/wuu0w 43oOdT64yp7kACF+j41i1kQHlbRVvv4EqgZQTvdy37cPjUdw+/LfgDdi9feTyf7McC hYscRSAFQ+daJBvOFLXT3j5e/qQiKt/G4s4UbyaM= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 2/6] xen/arm: ffa: Track hypervisor notifications in a bitmap Date: Wed, 29 Apr 2026 07:43:23 +0200 Message-ID: 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/1777441447-AD364C48-2A5E094F/0/0 X-purgate-type: clean X-purgate-size: 6808 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1777441491954158500 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 --- 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 c291f32b56ff..9ddda3f88986 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 Thu May 7 07:48:57 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=1777441483; cv=none; d=zohomail.com; s=zohoarc; b=S/Zh/iXag63LJiocnUOFiVfzXUzJO/lZwwAP7Dfyb6QKs838qRYqOlBD9Fm4kRs5PfkC/XttpEeq12ErYt5W5a+rQtUGYW7FQRD9RFcXxuUvxt6IQE/z15TFlBetThyDW4LRQ1wxhwx3vfTk5oEyj2Gij0M5wa6YbiU9QVfEU9E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777441483; 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=tYAYoDi5hgAm4tridDmbrWH8iC+cvseYwOBogS+t33M=; b=WHoL+f0JOsKrAZoR+9A/Ak2BWNTVzIpJcRfHrcL61TgndilEkciDCriPFYa1LPlCXRK1WOv/VKV2LrpevrjCgMxmbV/9E77RvjKfaR0X6fr0PKWwNvNVtt/ANWRQclr09Dvv+GEeNqKHwD4hZ8YJBa/qX/mfg61J1SRUHykxNzc= 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 1777441483713735.9638118830663; Tue, 28 Apr 2026 22:44:43 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1296943.1573091 (Exim 4.92) (envelope-from ) id 1wHxiW-00006i-2k; Wed, 29 Apr 2026 05:44:12 +0000 Received: by outflank-mailman (output) from mailman id 1296943.1573091; Wed, 29 Apr 2026 05:44:12 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiV-00006Y-W4; Wed, 29 Apr 2026 05:44:11 +0000 Received: by outflank-mailman (input) for mailman id 1296943; Wed, 29 Apr 2026 05:44:10 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiU-0008JC-1u for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 05:44:10 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wHxiT-002HZP-Dd for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 07:44:09 +0200 Received: from [10.42.69.11] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69f19aa3-2eae-0a2a0a5409dd-0a2a450b8fc0-16 for ; Wed, 29 Apr 2026 07:44:09 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-42698a.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69f19aa8-212f-0a2a450b0019-d98c6eacb3b4-1 for ; Wed, 29 Apr 2026 07:44:09 +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 8D80032E2; Tue, 28 Apr 2026 22:44:02 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.90.163]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A3CF93F62B; Tue, 28 Apr 2026 22:44:06 -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=1777441448; bh=xwgrVrb7mJ/jIKX+IuIaposJPSmY8HXotyRYbP0OwgU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=R4gqe1tXR6ZmJbt735SB+/fEeuSChDwFV3wr4m9hqQ7XjqAE34+5l34M9aPpoFGvA 0UIyKw07aTfycMyWLMoS4reXep3eaX9oJ+VWxXhPA2CND7fijyielN8S2Yq+0wRbLQ l3y+wmL1lufVjK4ujVWuFjd6LgsFsWJQpmQ4a3OE= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 3/6] xen/arm: ffa: Tighten notification parameter validation Date: Wed, 29 Apr 2026 07:43:24 +0200 Message-ID: <9ad2fe8d75a13494536787fc6aa98eb6eb3e67c6.1776955622.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-42698a/1777441449-06772F3B-A0C9D0BA/0/0 X-purgate-type: clean X-purgate-size: 6031 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1777441486340154100 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 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 Thu May 7 07:48:57 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=1777441489; cv=none; d=zohomail.com; s=zohoarc; b=J2QcQRFzVJxIcp3f4D6ibEwmGujcu+fptzoJHS2Aw8FZlZ7OCqj2mU6g7I/tIVnW86rw1A96aLsBWnBitPjZJF6WvEg4Ax+Jw13S6Ba7/kdMIDQhCICpsA8onEStw0Dg3joZN43SaTzPLgHs6Tnb48vTJfOhFdpUZ5ixAURvzWk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777441489; 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=PyMGwFeT7o2ZhZqy5GaZVQ5SnbcYwwJ7IXmis1FNPF0=; b=Hq/FES5X1M5De7y/v5ehOZEdxLEq+EJqgyJmmPwgqdmmLhfomk9F8hRq/dFMKhc4k1qsaqKa+OHcFMOIzdhloq8gJZD/RtjT0B9dJm+ipbgButChoYKtSoYvmwyk4eVzXphEqMEGWhr/AlCOEfN5pGR3B8kKXxJ0lRzlsJfRYTQ= 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 1777441489473152.7853939807518; Tue, 28 Apr 2026 22:44:49 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1296944.1573097 (Exim 4.92) (envelope-from ) id 1wHxiW-0000Ds-Hu; Wed, 29 Apr 2026 05:44:12 +0000 Received: by outflank-mailman (output) from mailman id 1296944.1573097; Wed, 29 Apr 2026 05:44:12 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiW-0000DJ-DZ; Wed, 29 Apr 2026 05:44:12 +0000 Received: by outflank-mailman (input) for mailman id 1296944; Wed, 29 Apr 2026 05:44:11 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiV-00005z-L6 for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 05:44:11 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wHxiV-002Hh3-0w for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 07:44:11 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69f19a93-2eae-0a2a0a5409dd-0a2a45099eba-44 for ; Wed, 29 Apr 2026 07:44:11 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69f19aaa-2497-0a2a45090019-d98c6eaccf84-1 for ; Wed, 29 Apr 2026 07:44:10 +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 493EA2BCE; Tue, 28 Apr 2026 22:44:04 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.90.163]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 690FD3F62B; Tue, 28 Apr 2026 22:44:08 -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=1777441449; bh=BJ9kpVORXjEmJR3F6tp4iMiyL0HijTQJTCH2Qdp2K1U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dj6lhwGKazFYUmEf7LGtDyFsmG0A361JkJGAE9N5HVdzJvD+KQzg3+ZBzE7DmoUYq JO1RFx81+xWGobW+Dc3V3X5dJIhufRaAijA9bbV2xns+fylDh+2sFygNibL5acWcqr 8CSNKBYnGab6q8daj0JizFr7UeppPqRxPohsDMh0= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 4/6] xen/arm: ffa: Preserve secure notification state when polling SPMC Date: Wed, 29 Apr 2026 07:43:25 +0200 Message-ID: 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/1777441450-4377AA53-000CACC7/0/0 X-purgate-type: clean X-purgate-size: 7201 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1777441490164158500 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 --- 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 Thu May 7 07:48:57 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=1777441485; cv=none; d=zohomail.com; s=zohoarc; b=BE+7pWzHEjBF8PrxYJe4H61RYWpkSySk9lN6PduQoT7il9lnWHFKr19wdefdaLoARr5qf+tkuRR0OTUGBlw7UFZlR1xzz+raNxcEmBL8UIVxHlYN9rsElvXVBxp0PFhZ9l16dbGTH17H6oBSzSgotV0JZFP59C2btAlZcjTpslA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777441485; 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=qzm/BB/CLQ38h4zyaRshtYhQYS20piuuUprvI+SMVWQ=; b=n1CEV6lckNHYUOAbR5PgWpxu+V9x+33k49qCj5y4ZW8jEe+Sl8d1IcBUftCT/1JPEZgXVeBw2d+giSIXmfqr3YNPQYQjnaq8uDoZ8brEhxd9JnZ80wurs7i+D15VJOC/gj4fURlITKJXMNon2QvduUCdRUW69oKVHYWhPCmwdFU= 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 1777441485821136.3441167534935; Tue, 28 Apr 2026 22:44:45 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1296946.1573109 (Exim 4.92) (envelope-from ) id 1wHxiY-0000bp-OE; Wed, 29 Apr 2026 05:44:14 +0000 Received: by outflank-mailman (output) from mailman id 1296946.1573109; Wed, 29 Apr 2026 05:44:14 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiY-0000bc-LF; Wed, 29 Apr 2026 05:44:14 +0000 Received: by outflank-mailman (input) for mailman id 1296946; Wed, 29 Apr 2026 05:44:13 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiX-0000UH-Ev for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 05:44:13 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wHxiW-003p6b-Qr for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 07:44:12 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69f19a94-e002-0a2a0a5209dd-0a2a450cba4e-24 for ; Wed, 29 Apr 2026 07:44:12 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-d25034.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69f19aab-62f1-0a2a450c0019-d98c6eacb3d2-1 for ; Wed, 29 Apr 2026 07:44:12 +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 0856D2BCE; Tue, 28 Apr 2026 22:44:06 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.90.163]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 29A5B3F62B; Tue, 28 Apr 2026 22:44:10 -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=1777441451; bh=HhDBJf0IfXGwpTjfY2ecC/WNtpLQx+0BHlKhp3zkvP0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IyJIf0pObIJcvGsVV9rDtmrwWDUL7jn1OseYOkchfyR6ODE67oB/EJgwZ9Ktpy4AA KJsL3tzy0R1TvDrx8ZkjYsKpVD2BNVCDyQYY4zBvHUhbeEBO+CDCDUpKQQj8Rd1TqZ fGK6iiLEeIkfWb7lU9BUUmWksA0S19uJDoKnx5E8= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 5/6] xen/arm: ffa: Track VM notification bindings locally Date: Wed, 29 Apr 2026 07:43:26 +0200 Message-ID: <13a7b810346a31acb5b1407b51c17141aebb33f8.1776955622.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-d25034/1777441452-6E169CF5-22CD8A8E/0/0 X-purgate-type: clean X-purgate-size: 7559 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1777441487588154100 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 --- 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 9ddda3f88986..78a0a9815d56 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 Thu May 7 07:48:57 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=1777441492; cv=none; d=zohomail.com; s=zohoarc; b=IM8shEuWGE/SFDQ+g6kEqWQBq7/meJWlbM0LIXty0ThV10MCSoar/h5Y+3kWGge6FMmHh5Y4cYh5ssvJMnJNQO19jvJRzV/x946ivMXbBGZIitcIFOj8gJRgfkn7Lh8Ul28yCXO9xkPEWBYoAwkZiolK5NNkOuuWxEPAgx3YJrE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777441492; 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=D9m0jPlkSP61PBxVSkTv+flqMVIRluFfKlDQWruJzxc=; b=AL29v7ABlZROi8T+HrCovBpG3zfrXhM6TUFax83S4FlW+532hgQ3WrD4suU6TVsABqf2+RPLvopy+jhZAaL61LNZNZmhMVqu/5LdrghtgZ7prKW/72zIPpVuqAdkxYf5zFcMQrMDq8cYZ7r25aln2w2x0jze351HfPn0HGHEIG8= 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 1777441492671443.6825808286003; Tue, 28 Apr 2026 22:44:52 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1296949.1573118 (Exim 4.92) (envelope-from ) id 1wHxia-0000tZ-2t; Wed, 29 Apr 2026 05:44:16 +0000 Received: by outflank-mailman (output) from mailman id 1296949.1573118; Wed, 29 Apr 2026 05:44:16 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiZ-0000tM-UR; Wed, 29 Apr 2026 05:44:15 +0000 Received: by outflank-mailman (input) for mailman id 1296949; Wed, 29 Apr 2026 05:44:15 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wHxiZ-0000ee-3A for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 05:44:15 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wHxiY-002Hh3-FU for xen-devel@lists.xenproject.org; Wed, 29 Apr 2026 07:44:14 +0200 Received: from [10.42.69.1] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69f19aab-2eae-0a2a0a5409dd-0a2a4501be9e-6 for ; Wed, 29 Apr 2026 07:44:14 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-d62444.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69f19aad-c1f2-0a2a45010019-d98c6eac870c-1 for ; Wed, 29 Apr 2026 07:44:14 +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 C6533328D; Tue, 28 Apr 2026 22:44:07 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.90.163]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DFC2A3F62B; Tue, 28 Apr 2026 22:44:11 -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=1777441453; bh=bzcppw7eOfYm4UiVzmHypcylvW+Izet9K8ImNObcrec=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EcTW028WW95ZvmPZrEP3MQi38GiBXqEkA3YIIlkrpv8KntLoZC1veLBlB0VXu4Kbe YT+yJM9PfMnmtQOemAu3Zhn+PfCP/pyL+qjsE++Dckr70vKM1is21h6w5v4ncqXRKR Q2tLb0cg+i3tayPZilp/KryTowOReQLSLo4exmAk= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 6/6] xen/arm: ffa: Deliver VM-to-VM notifications locally Date: Wed, 29 Apr 2026 07:43:27 +0200 Message-ID: <1ead2af7182a0501f16e7b4e9ad3e58ccd8f538c.1776955622.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-d62444/1777441454-BDC64FF4-3CDC08FC/0/0 X-purgate-type: clean X-purgate-size: 9730 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1777441495724154100 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 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 | 82 ++++++++++++++++++++++++++++++++-- xen/arch/arm/tee/ffa_private.h | 17 ++++--- 3 files changed, 107 insertions(+), 16 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..b29d948a7110 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,6 +342,8 @@ 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= ) @@ -298,6 +354,18 @@ void ffa_handle_notification_get(struct cpu_user_regs = *regs) 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 +391,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 78a0a9815d56..923a071a9d7c 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