From nobody Tue May 5 08:57:31 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=1776433311; cv=none; d=zohomail.com; s=zohoarc; b=WGDwUy8XBnlwgdyvNGSYxrjnb7B48T1KUrwrEMa8zgpZh63rBo+2RNhNkMARo40x6gCH/miMeKu/mVFYN6bmLRHsTZlVFqNvIL75t34eYNWbrGzI8ikEqHa1cyXQkVucnV7fnhTvUIqCuzNVX/pCD8febVFbdBpsCculO6oICNw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776433311; 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=s8TiP1VE/kX/ko3XO+ANZI/AhKbokBHo65rxmjG3vCk=; b=FV8v0/EwLD/j4XGnYn9dOmg/rNN43oFei5dZEpF660AkW5rW+ChRfNlFQSknWhO5O1Y1fPIqZGrDAvG2iB5udc7kySAi+RQ6gHHxJ+CyTD/Djts69UUFdrcDRX7iZ/7ubVxSP51amNLAQrQieyFL8c8eEwA+uhET4rgrKlwOmco= 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 1776433310950745.5822573104992; Fri, 17 Apr 2026 06:41:50 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1284300.1566123 (Exim 4.92) (envelope-from ) id 1wDjRr-0005Xi-G5; Fri, 17 Apr 2026 13:41:31 +0000 Received: by outflank-mailman (output) from mailman id 1284300.1566123; Fri, 17 Apr 2026 13:41:31 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRr-0005Xb-C4; Fri, 17 Apr 2026 13:41:31 +0000 Received: by outflank-mailman (input) for mailman id 1284300; Fri, 17 Apr 2026 13:41:30 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRq-0005XG-DB for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 13:41:30 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wDjRp-000Ejb-QG for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 15:41:29 +0200 Received: from [10.42.69.6] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69e23869-5cb7-0a2a0a5109dd-0a2a450688f0-46 for ; Fri, 17 Apr 2026 15:41:29 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-16d1c6.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69e23888-7371-0a2a45060019-d98c6eacc488-1 for ; Fri, 17 Apr 2026 15:41:29 +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 BFB2E1E5E; Fri, 17 Apr 2026 06:41:22 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.89.170]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 164583F7D8; Fri, 17 Apr 2026 06:41:26 -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=1776433288; bh=2EBHRYe3a9Iu2Tcg1hgwEsSiL6lkKJcFnxNSP9Ue5No=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VdYJxFcLI4jsdEtYZSOcScludKGT5YwwMuMO0TwaaXWi1Hgkxt892Fotc+CN25Arq uRpUQYMjXbKpDSE5fOBcWIAD9XE8w9J02CloxF0T26Qh7gFylIzux2q+Ro2n5PIvfA P811XWtiGYC16BhHODf+4AbWTwWhWzSMWGbofGO0= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 1/6] xen/arm: ffa: Fix NPI injection when vcpu0 is offline Date: Fri, 17 Apr 2026 15:40:49 +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-16d1c6/1776433289-52369D75-B7400893/0/0 X-purgate-type: clean X-purgate-size: 3302 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1776433311513158500 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 --- 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 Tue May 5 08:57:31 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=1776433311; cv=none; d=zohomail.com; s=zohoarc; b=ircj++SwWCOX8qqgKbBVDaDctSRKXjJs14cZu8q94tWuELV5BT/qeKo7VTefq3HlJqZF2ZciRp68pzsDR5Lld9FRD8xFt2izim7A6jM/cxhjxjFi1noHoqoFZcRDQxvyUeMpdrED9/5WbYWcmtCiyVKvPlzy6HPPAuElofJCOOE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776433311; 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=7liEaokosXL/ZPIJG1cA5cVEhgpdkRunIZjEVs3ryvE=; b=FKZxF18Q4fTsCrpp7PQzz9XMWzjB9x4zCEnDxUXkquc4pakDeGpFDjrSv9KbSISYM2idhHEz2u614Y3/bF1tsa/cIZPLLggIEydy1GhFslKRl+/w5FYxa2lIl2qTtEYZM8CdhWJKNnc78NtoCwUVN1LfR6kk8pYZO34F2adVeJE= 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 1776433311721938.0190992430837; Fri, 17 Apr 2026 06:41:51 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1284302.1566131 (Exim 4.92) (envelope-from ) id 1wDjRs-0005lk-Lj; Fri, 17 Apr 2026 13:41:32 +0000 Received: by outflank-mailman (output) from mailman id 1284302.1566131; Fri, 17 Apr 2026 13:41:32 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRs-0005ld-J0; Fri, 17 Apr 2026 13:41:32 +0000 Received: by outflank-mailman (input) for mailman id 1284302; Fri, 17 Apr 2026 13:41:31 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRr-0005cp-T0 for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 13:41:31 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wDjRr-000Ejb-9z for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 15:41:31 +0200 Received: from [10.42.69.10] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69e23878-5cb7-0a2a0a5109dd-0a2a450a8746-26 for ; Fri, 17 Apr 2026 15:41:31 +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 69e2388a-56b3-0a2a450a0019-d98c6eacc2a8-1 for ; Fri, 17 Apr 2026 15:41:31 +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 845031516; Fri, 17 Apr 2026 06:41:24 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.89.170]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D5E8A3F7D8; Fri, 17 Apr 2026 06:41:28 -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=1776433290; bh=caqGVxvnjz0bVK6Ez9rNrj5k4WIzyoABx5lWZ62MqVc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F/9rK41YnPUbCvUBHCt5U0B3AIRzfayyu4D5MvWYWuc5xGXma+MxvpDDLffQHSAt1 B7Bg4iM3FAywj4XwhUbq14JxtRUZZPfPf8yYJSbdp5KP+U5YjXRuj29S8szj7wmgER JoceslpxERiNOPD+UNgMD4dmFI7ngoNnufOaX6AY= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 2/6] xen/arm: ffa: Track hypervisor notifications in a bitmap Date: Fri, 17 Apr 2026 15:40:50 +0200 Message-ID: <7053b8c14bbe50cc855dad0a82cde2bb10153d2b.1776266307.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/1776433291-CEB778B7-F8329588/0/0 X-purgate-type: clean X-purgate-size: 4902 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1776433313286154100 Content-Type: text/plain; charset="utf-8" Hypervisor notifications are currently tracked with a dedicated buff_full_pending boolean. That state only represents a single HYP notification bit and keeps HYP bitmap handling tied to single-purpose bookkeeping. Replace the boolean with a hypervisor notification bitmap protected by notif_lock. INFO_GET reports pending when the bitmap is non-zero, GET returns and clears the HYP bitmap under the lock, and RX-buffer-full sets FFA_NOTIF_RX_BUFFER_FULL in the bitmap instead of updating separate state. 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. No functional changes. Signed-off-by: Bertrand Marquis --- xen/arch/arm/tee/ffa_notif.c | 46 ++++++++++++++++++++++++++-------- xen/arch/arm/tee/ffa_private.h | 9 +++++-- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 07bc5cb3a430..d15119409a25 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -94,8 +94,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 +181,17 @@ 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; + } + + spin_unlock(&ctx->notif.notif_lock); } =20 ffa_set_regs(regs, FFA_SUCCESS_32, 0, w2, w3, w4, w5, w6, w7); @@ -207,12 +219,17 @@ int32_t ffa_handle_notification_set(struct cpu_user_r= egs *regs) void ffa_raise_rx_buffer_full(struct domain *d) { struct ffa_ctx *ctx =3D d->arch.tee; + uint32_t prev_bitmap; =20 if ( !ctx ) return; =20 - ACCESS_ONCE(ctx->notif.buff_full_pending) =3D true; - if ( !test_and_set_bool(ctx->notif.vm_pending) ) + spin_lock(&ctx->notif.notif_lock); + prev_bitmap =3D ctx->notif.hyp_pending; + ctx->notif.hyp_pending |=3D FFA_NOTIF_RX_BUFFER_FULL; + spin_unlock(&ctx->notif.notif_lock); + + if ( !(prev_bitmap & FFA_NOTIF_RX_BUFFER_FULL) ) inject_notif_pending(d); } #endif @@ -426,12 +443,15 @@ 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.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 +461,16 @@ 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.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..5693772481ed 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -340,9 +340,14 @@ 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; + + /* + * Bitmap of pending hypervisor notifications (for HYP bitmap queries). + */ + uint32_t hyp_pending; }; =20 struct ffa_ctx { --=20 2.53.0 From nobody Tue May 5 08:57:31 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=1776433320; cv=none; d=zohomail.com; s=zohoarc; b=g3tVwPvgmDiSYAE/Kfql5cmk8xUeokHdNYeN5FRMlI9txfn3ZhCbrqbJZjPd9hzF/UVtw2WwhL2+MeZPhQ1ummoI0cOTW/kA2m+zUv6arxkGMmtL511U6XrUGIAwCBqYpMIAuoREc7hiBaxTwVb7hEQehtnrw6y/XVY0GVmt7SA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776433320; 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=/HBk+LRzPvdF5lx5gpvyGRH9UVAWjcGz9bb5g/p/B/0=; b=j7ORJY/tEPf/PCXeAYvwv1retN8/3YEPdVXDLYghmzlHFLbwtfjBKspe+eMele3bIe9T3QhAyz/K7Swo2POynT8R9+w6lg+hg8+BRkgbNdKw9EMd8wAGGGK1q/4VLuZcn873TCXqvxMfJODzQLApTpgy5DEXPJQJIKcVkhcbBHk= 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 1776433320955401.7997643644138; Fri, 17 Apr 2026 06:42:00 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1284305.1566140 (Exim 4.92) (envelope-from ) id 1wDjRv-00062z-Uu; Fri, 17 Apr 2026 13:41:35 +0000 Received: by outflank-mailman (output) from mailman id 1284305.1566140; Fri, 17 Apr 2026 13:41:35 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRv-00062s-R5; Fri, 17 Apr 2026 13:41:35 +0000 Received: by outflank-mailman (input) for mailman id 1284305; Fri, 17 Apr 2026 13:41:34 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRu-0005zq-6m for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 13:41:34 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wDjRt-009kb3-Jo for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 15:41:33 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69e23874-e002-0a2a0a5209dd-0a2a4504d544-46 for ; Fri, 17 Apr 2026 15:41:33 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-ebf023.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69e2388c-1dec-0a2a45040019-d98c6eacd9ca-1 for ; Fri, 17 Apr 2026 15:41:32 +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 47521152B; Fri, 17 Apr 2026 06:41:26 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.89.170]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9D90C3F7D8; Fri, 17 Apr 2026 06:41:30 -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=1776433292; bh=GpMN53OmsGMUNWxbJRMSEFaE53+mcg2MmZqtr/Lo+zY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ucGQGoVsedG3vqsRL/HuomCA0Jz5/3TnwHbqBxEWVCowvK4bG1Xo/y+ovBDsdFWfW rBTnupjUo8k5NpYtaJM/9xf8eDMCYTsLR9ajQX7S2poaQAWt+gaNSbPsLuTeYulTVW SRcArxibT/wa8kwDgYF7hKelE08jkMfcUyucIY9o= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 3/6] xen/arm: ffa: Tighten notification parameter validation Date: Fri, 17 Apr 2026 15:40:51 +0200 Message-ID: <1036add9199c6304eb649854024c74dd0f0192cc.1776266307.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/1776433293-300413FF-D93CA36A/0/0 X-purgate-type: clean X-purgate-size: 5853 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1776433323265154100 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_parse_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 parser for notification caller/destination validation - wire BIND and UNBIND through the shared parser 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 --- 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 d15119409a25..491db3b04df5 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -42,21 +42,40 @@ static void inject_notif_pending(struct domain *d) d); } =20 +static int32_t ffa_notif_parse_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_parse_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 @@ -66,16 +85,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_parse_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; } @@ -142,6 +167,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 )) ) { @@ -204,11 +235,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_parse_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 Tue May 5 08:57:31 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=1776433319; cv=none; d=zohomail.com; s=zohoarc; b=ad5ZdhbYtTJK1zySLGumzz20zvO0H34IpXTJmAc7m79YzwU4EgHF6S26CpOCmG9ujfRP2nTCdztBp/tOvIHuSym2NeN2dtLEraKK68KgT4XNvAJXeKbDBimzaEsQyYHuShGigORuPhgILKnuLYXG2HOLM4FK1n7vMeOy+s+fB18= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776433319; 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=ul4jGbGeuGV4A0IBk74ypHX37nRWLhWBCY6qIg9sFJo=; b=f/It8WI4XGpgXsrImJnOKpAn5NsYV3+xjHRRLFDoqkGRuTCR7jM67n9BzA7flxQvh4EioS4GNrrH4AWXM6MvW6HVdha05ZVPyEpWLrXVNQT6kD6QRasu9gnPdytTNpXe5lDs9wCweBz71tBzfP3AtsslZgy7piuiQ0KsN5KWI1M= 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 1776433319026503.9027673401132; Fri, 17 Apr 2026 06:41:59 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1284306.1566149 (Exim 4.92) (envelope-from ) id 1wDjRx-0006I3-9Y; Fri, 17 Apr 2026 13:41:37 +0000 Received: by outflank-mailman (output) from mailman id 1284306.1566149; Fri, 17 Apr 2026 13:41:37 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRx-0006Hw-5i; Fri, 17 Apr 2026 13:41:37 +0000 Received: by outflank-mailman (input) for mailman id 1284306; Fri, 17 Apr 2026 13:41:35 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRv-000617-Dt for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 13:41:35 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wDjRu-009kb3-Qj for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 15:41:34 +0200 Received: from [10.42.69.1] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69e2387d-e002-0a2a0a5209dd-0a2a4501dbf6-44 for ; Fri, 17 Apr 2026 15:41:34 +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 69e2388e-c1f2-0a2a45010019-d98c6eacc4ba-1 for ; Fri, 17 Apr 2026 15:41:34 +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 0B3C01516; Fri, 17 Apr 2026 06:41:28 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.89.170]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5D90F3F7D8; Fri, 17 Apr 2026 06:41:32 -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=1776433293; bh=muz5M8Iqgy9eYpjCmc9pZ8VEHmiBcMu4FfUho63d0M0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iZTB9GDnC8dlk4AuK5JEPg+WSaTmt+qDuvHT6F6NOx2Z/7Af49FmybLRpf2vLCeJ+ ZfyhuzZXZe5xRicWkcQ64iNe5zjxp0Y/XgX38wJJYkQm1RyTIJpE5/nSVgBcMVQzfH 99YaNfJX4D5swFgq217QsO69bfIdG3TBCLtW+vmU= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 4/6] xen/arm: ffa: Preserve secure notification state when polling SPMC Date: Fri, 17 Apr 2026 15:40:52 +0200 Message-ID: <5b9ce4a4a3927ce2287ec4db7f864174f53b8f17.1776266307.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/1776433294-B5468FF4-67EDDF68/0/0 X-purgate-type: clean X-purgate-size: 7136 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1776433319609158500 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 --- xen/arch/arm/tee/ffa_notif.c | 54 +++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 491db3b04df5..fff00ca2baec 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 void inject_notif_pending(struct domain *d) { @@ -109,6 +110,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 ) @@ -117,7 +119,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); @@ -131,7 +136,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); } @@ -154,6 +161,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 ) { @@ -173,27 +182,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 ) @@ -210,6 +208,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) ) @@ -354,7 +356,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: @@ -373,11 +378,18 @@ static void notif_sri_action(void *unused) unsigned int n; int32_t res; =20 - do { + if ( !fw_notif_enabled ) + return; + + 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); @@ -391,7 +403,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); @@ -399,7 +411,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); @@ -486,6 +500,7 @@ int ffa_notif_domain_init(struct domain *d) int32_t res; =20 spin_lock_init(&ctx->notif.notif_lock); + ctx->notif.secure_pending =3D false; ctx->notif.hyp_pending =3D 0; =20 if ( fw_notif_enabled ) @@ -503,6 +518,7 @@ void ffa_notif_domain_destroy(struct domain *d) struct ffa_ctx *ctx =3D d->arch.tee; =20 spin_lock(&ctx->notif.notif_lock); + 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 Tue May 5 08:57:31 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=1776433323; cv=none; d=zohomail.com; s=zohoarc; b=N7BpZ5n83xLdcRhe6zhZNddEGgBreg7ANnj0fKutGHCTAlx/hAXuT8J+IQl42AS3YMaU9GVgtdX8YL6s0l68105jd3kyJkvrPc9rG4Z7DoGfKWM7ixIeIN4i7qnTe/uOf3AQM8IB5jF2QnppsPwVckfgfZMdgATdxS7/zhuhTok= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776433323; 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=7PmRYQ+jHBnQrx3V+V74CZkqeePfDdjRcaxt92t68DQ=; b=ZQyd+q4X7zJkjY0/0eoby40C3hnPub7BCOo4uGg+4RQS2k7JlXaAp74wYVYwj1PMQU6qYn+/Yq6dolCKKBCTUUOq45WMx/qmLl0bXBBayW2Ph2z1hDTHTMtMDUXF8AvU5R0Z29RISrb+9Bg3jFZCTaASF8youo4zCu6i5gN0JF8= 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 1776433323661536.3407906823688; Fri, 17 Apr 2026 06:42:03 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1284307.1566158 (Exim 4.92) (envelope-from ) id 1wDjRz-0006ZC-I0; Fri, 17 Apr 2026 13:41:39 +0000 Received: by outflank-mailman (output) from mailman id 1284307.1566158; Fri, 17 Apr 2026 13:41:39 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRz-0006Yt-DK; Fri, 17 Apr 2026 13:41:39 +0000 Received: by outflank-mailman (input) for mailman id 1284307; Fri, 17 Apr 2026 13:41:37 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRx-0006Hl-97 for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 13:41:37 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wDjRw-009kb3-MC for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 15:41:36 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69e23890-e002-0a2a0a5209dd-0a2a450ce252-2 for ; Fri, 17 Apr 2026 15:41:36 +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 69e2388f-62f1-0a2a450c0019-d98c6eacc2d0-1 for ; Fri, 17 Apr 2026 15:41:36 +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 BE7E3152B; Fri, 17 Apr 2026 06:41:29 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.89.170]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 23F323F7D8; Fri, 17 Apr 2026 06:41:33 -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=1776433295; bh=K0L3j6rOuFbocNT0G1KNMjoLTTA4P4wveYKXWHNkbsg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=B/bQ7sOWm1dxec2RmlYkfebzmi/bx9ZcepiAYslRbJWBW4zioVi1baQfMBdZdGO9e iOsX8RZScJAHJVd/WiJyZMZhoIsRS3//jupKt4dEtgK+DTvoPK9HMnh1zAV9Ezl8AA M3k7OdCTx034h/uFsaB+kER/aYVcEChWw2C1lEcU= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 5/6] xen/arm: ffa: Track VM notification bindings locally Date: Fri, 17 Apr 2026 15:40:53 +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-d25034/1776433296-F620CCF5-86443AD2/0/0 X-purgate-type: clean X-purgate-size: 7406 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1776433325533158500 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 --- xen/arch/arm/tee/ffa_notif.c | 97 ++++++++++++++++++++++++++++++---- xen/arch/arm/tee/ffa_private.h | 15 ++++-- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index fff00ca2baec..4def701f0130 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -56,6 +56,54 @@ static int32_t ffa_notif_parse_params(uint16_t dom_id, u= int16_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; @@ -76,11 +124,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) @@ -99,11 +157,21 @@ int32_t ffa_handle_notification_unbind(struct cpu_user= _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) @@ -125,9 +193,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); @@ -497,10 +566,14 @@ void ffa_notif_init(void) int ffa_notif_domain_init(struct domain *d) { struct ffa_ctx *ctx =3D d->arch.tee; + unsigned int i; int32_t res; =20 spin_lock_init(&ctx->notif.notif_lock); ctx->notif.secure_pending =3D false; + ctx->notif.vm_pending =3D 0; + for ( i =3D 0; i < FFA_NUM_VM_NOTIF; i++ ) + ctx->notif.vm_bind[i] =3D 0; ctx->notif.hyp_pending =3D 0; =20 if ( fw_notif_enabled ) @@ -516,9 +589,13 @@ int ffa_notif_domain_init(struct domain *d) void ffa_notif_domain_destroy(struct domain *d) { struct ffa_ctx *ctx =3D d->arch.tee; + unsigned int i; =20 spin_lock(&ctx->notif.notif_lock); ctx->notif.secure_pending =3D false; + ctx->notif.vm_pending =3D 0; + for ( i =3D 0; i < FFA_NUM_VM_NOTIF; i++ ) + ctx->notif.vm_bind[i] =3D 0; 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 5693772481ed..6d83afb3d00a 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -236,6 +236,11 @@ #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 + +#if FFA_NUM_VM_NOTIF > 64 +#error "FFA_NUM_VM_NOTIF must be <=3D 64" +#endif =20 /* Feature IDs used with FFA_FEATURES */ #define FFA_FEATURE_NOTIF_PEND_INTR 0x1U @@ -334,10 +339,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 Tue May 5 08:57:31 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=1776433320; cv=none; d=zohomail.com; s=zohoarc; b=c7G/TYqPD8A57OtOBga1vbzl2/j6tazgiiTAywh5/tAeeTCuTKEEyvhgUT9+/KZH0cq5sBygsqwSY5sG6V5XfHMzW4dnNljXIAJfrRpLwInojiV9mAzxneSumaBL+NbLUFfh9x+PUE/wdYpr5KPfmldU1DefAPNObdO9AQ9XzfI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776433320; 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=6DmxDjavy012+r4PHPlnGQhDkz68JtI2TOFLrty0LVs=; b=ePJ492tcgtM/fyaw5L46+v48gNturc6vVuUNdb+Op+7pJrZQ1KZ1M15iVKvPnziXfxY00oBy71qQqGRuCLTwYo8L57yvPsIu0gjf2N2RyNGowncJ1QkxqZxAabLWatooHYAgBWqG4I4nVVVTNCVPCLeFxiwXXeFV4wYq9Ymp3wI= 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 1776433320062191.11831504740712; Fri, 17 Apr 2026 06:42:00 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1284310.1566162 (Exim 4.92) (envelope-from ) id 1wDjRz-0006cF-Rn; Fri, 17 Apr 2026 13:41:39 +0000 Received: by outflank-mailman (output) from mailman id 1284310.1566162; Fri, 17 Apr 2026 13:41:39 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRz-0006b5-Lc; Fri, 17 Apr 2026 13:41:39 +0000 Received: by outflank-mailman (input) for mailman id 1284310; Fri, 17 Apr 2026 13:41:39 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wDjRy-0006Xe-SW for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 13:41:38 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wDjRw-000EHD-Ne for xen-devel@lists.xenproject.org; Fri, 17 Apr 2026 15:41:38 +0200 Received: from [10.42.69.3] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69e2388e-bab6-0a2a0a5309dd-0a2a4503ed30-10 for ; Fri, 17 Apr 2026 15:41:38 +0200 Received: from [217.140.110.172] (helo=foss.arm.com) by tlsNG-33051d.mxtls.expurgate.net with ESMTP (eXpurgate 4.56.1) (envelope-from ) id 69e23891-672d-0a2a45030019-d98c6eacd12a-1 for ; Fri, 17 Apr 2026 15:41:37 +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 529231516; Fri, 17 Apr 2026 06:41:31 -0700 (PDT) Received: from C3HXLD123V.arm.com (unknown [10.57.89.170]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D6D373F7D8; Fri, 17 Apr 2026 06:41:35 -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=1776433297; bh=cZZGPI6vYtUzakFAvu0YBSmNdIu2H7Rzaign3ej2VlA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y1XalVlal1hWmaJVNRfQYNZEX63Jd6p5Jf9DVO7ivurdKHvPxODE93GmrQBpPyrXJ OjFOR1PtxYL6A0kjZi4T+J7W8qdXR8ejrNDRuD3yPJcJiPxo/NdQw8yIZ1tM/sLTsI bzCi6GUXv+iF0ls9DWhFLcmdMLQFkRYjyYCyo+jY= From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: Volodymyr Babchuk , Jens Wiklander , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH 6/6] xen/arm: ffa: Deliver VM-to-VM notifications locally Date: Fri, 17 Apr 2026 15:40:54 +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-33051d/1776433298-2BB6C938-83D67431/0/0 X-purgate-type: clean X-purgate-size: 12215 X-ZohoMail-DKIM: pass (identity @arm.com) X-ZM-MESSAGEID: 1776433321559158500 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 the receiver transitions from no local pending notifications to some. 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 roll back newly-added VM pending bits if no destination vCPU is online. 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 --- xen/arch/arm/tee/ffa.c | 24 +++++-- xen/arch/arm/tee/ffa_notif.c | 126 +++++++++++++++++++++++++++++++-- xen/arch/arm/tee/ffa_private.h | 11 ++- 3 files changed, 147 insertions(+), 14 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 4def701f0130..e77321244926 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -20,7 +20,12 @@ 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 void inject_notif_pending(struct domain *d) +bool ffa_notif_fw_enabled(void) +{ + return fw_notif_enabled; +} + +static bool inject_notif_pending(struct domain *d) { struct vcpu *v; =20 @@ -34,13 +39,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 static int32_t ffa_notif_parse_params(uint16_t dom_id, uint16_t caller_id, @@ -104,6 +111,73 @@ 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; + uint64_t prev_bitmap =3D 0; + uint64_t new_bitmap; + bool inject =3D false; + + 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; + } + } + + prev_bitmap =3D dst_ctx->notif.vm_pending; + dst_ctx->notif.vm_pending |=3D bitmap; + if ( !dst_ctx->notif.notif_irq_raised && + (dst_ctx->notif.vm_pending || dst_ctx->notif.hyp_pending) ) + { + dst_ctx->notif.notif_irq_raised =3D true; + inject =3D true; + } + +out_unlock: + spin_unlock(&dst_ctx->notif.notif_lock); + + new_bitmap =3D bitmap & ~prev_bitmap; + if ( ret =3D=3D FFA_RET_OK && inject && new_bitmap && + !inject_notif_pending(dst_d) ) + { + spin_lock(&dst_ctx->notif.notif_lock); + dst_ctx->notif.vm_pending &=3D ~new_bitmap; + if ( !(dst_ctx->notif.vm_pending || dst_ctx->notif.hyp_pending) ) + dst_ctx->notif.notif_irq_raised =3D false; + spin_unlock(&dst_ctx->notif.notif_lock); + ret =3D FFA_RET_DENIED; + } + + rcu_unlock_domain(dst_d); + + return ret; +} + int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs) { struct domain *d =3D current->domain; @@ -285,6 +359,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= ) @@ -293,6 +369,18 @@ void ffa_handle_notification_get(struct cpu_user_regs = *regs) ctx->notif.hyp_pending =3D 0; } =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 @@ -318,9 +406,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; } @@ -330,6 +426,7 @@ void ffa_raise_rx_buffer_full(struct domain *d) { struct ffa_ctx *ctx =3D d->arch.tee; uint32_t prev_bitmap; + bool inject =3D false; =20 if ( !ctx ) return; @@ -337,10 +434,23 @@ void ffa_raise_rx_buffer_full(struct domain *d) spin_lock(&ctx->notif.notif_lock); prev_bitmap =3D ctx->notif.hyp_pending; ctx->notif.hyp_pending |=3D FFA_NOTIF_RX_BUFFER_FULL; + if ( !ctx->notif.notif_irq_raised && + (ctx->notif.vm_pending || ctx->notif.hyp_pending) ) + { + ctx->notif.notif_irq_raised =3D true; + inject =3D true; + } spin_unlock(&ctx->notif.notif_lock); =20 - if ( !(prev_bitmap & FFA_NOTIF_RX_BUFFER_FULL) ) - inject_notif_pending(d); + if ( inject && !(prev_bitmap & FFA_NOTIF_RX_BUFFER_FULL) && + !inject_notif_pending(d) ) + { + spin_lock(&ctx->notif.notif_lock); + ctx->notif.hyp_pending &=3D ~FFA_NOTIF_RX_BUFFER_FULL; + if ( !(ctx->notif.vm_pending || ctx->notif.hyp_pending) ) + ctx->notif.notif_irq_raised =3D false; + spin_unlock(&ctx->notif.notif_lock); + } } #endif =20 @@ -572,6 +682,7 @@ int ffa_notif_domain_init(struct domain *d) spin_lock_init(&ctx->notif.notif_lock); ctx->notif.secure_pending =3D false; ctx->notif.vm_pending =3D 0; + ctx->notif.notif_irq_raised =3D false; for ( i =3D 0; i < FFA_NUM_VM_NOTIF; i++ ) ctx->notif.vm_bind[i] =3D 0; ctx->notif.hyp_pending =3D 0; @@ -594,6 +705,7 @@ void ffa_notif_domain_destroy(struct domain *d) spin_lock(&ctx->notif.notif_lock); ctx->notif.secure_pending =3D false; ctx->notif.vm_pending =3D 0; + ctx->notif.notif_irq_raised =3D false; for ( i =3D 0; i < FFA_NUM_VM_NOTIF; i++ ) ctx->notif.vm_bind[i] =3D 0; ctx->notif.hyp_pending =3D 0; diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 6d83afb3d00a..5bb19bd11dd0 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -344,13 +344,17 @@ 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). */ + uint16_t vm_bind[FFA_NUM_VM_NOTIF]; + + /* Lock protecting local notification state. */ spinlock_t notif_lock; =20 /* @@ -493,6 +497,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