[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/6] xen/arm: ffa: Fix NPI injection when vcpu0 is offline



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 <bertrand.marquis@xxxxxxx>
---
 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;
 
+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 
offline\n",
+               d);
+}
+
 int32_t ffa_handle_notification_bind(struct cpu_user_regs *regs)
 {
     struct domain *d = current->domain;
@@ -190,7 +213,7 @@ void ffa_raise_rx_buffer_full(struct domain *d)
 
     ACCESS_ONCE(ctx->notif.buff_full_pending) = true;
     if ( !test_and_set_bool(ctx->notif.vm_pending) )
-        vgic_inject_irq(d, d->vcpu[0], GUEST_FFA_NOTIF_PEND_INTR_ID, true);
+        inject_notif_pending(d);
 }
 #endif
 
@@ -238,7 +261,6 @@ static void notif_vm_pend_intr(uint16_t vm_id)
 {
     struct ffa_ctx *ctx;
     struct domain *d;
-    struct vcpu *v;
 
     /*
      * vm_id == 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) = 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 
offline\n",
-               d);
+    inject_notif_pending(d);
 
 out_unlock:
     rcu_unlock_domain(d);
-- 
2.53.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.