diff mbox series

[v3,3/5] xen/arm: ffa: Add buffer full notification support

Message ID 3aceccbc7d006b87bfe20a9a4f660eb831185dbb.1742570590.git.bertrand.marquis@arm.com (mailing list archive)
State Superseded
Headers show
Series FF-A VM to VM support | expand

Commit Message

Bertrand Marquis March 24, 2025, 9:14 a.m. UTC
Add support to raise a Rx buffer full notification to a VM.
This function will be used for indirect message support between VM and
is only activated if CONFIG_FFA_VM_TO_VM is selected.

Even if there are 32 framework notifications possible, right now only
one is defined so the implementation is simplified to only handle the
buffer full notification using a boolean. If other framework
notifications have to be supported one day, the design will have to be
modified to handle it properly.

Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
Changes in v3:
- introduce a vm_pending boolean to track if VM notifications are
  pending and allow to decorelate pending secure notifications from
  pending vm ones
- remove ifdef around boolean entries for notifications and make use of
  IS_ENABLED instead of ifdefs when possible
- Fix notification number signaled to VMs for buffer full to use the
  proper GUEST_FFA_NOTIF_PEND_INTR_ID instead of the identifier received
  from the SPMC.
- Move back into this patch ffa_private.h part which was wrongly in the
  patch for indirect messages between VM
Changes in v2:
- Switch ifdef to IS_ENABLED when possible
---
 xen/arch/arm/tee/ffa_notif.c   | 36 ++++++++++++++++++++++++++++------
 xen/arch/arm/tee/ffa_private.h | 23 +++++++++++++++++++++-
 2 files changed, 52 insertions(+), 7 deletions(-)

Comments

Jens Wiklander March 24, 2025, 10:30 a.m. UTC | #1
Hi Bertrand,

On Mon, Mar 24, 2025 at 10:15 AM Bertrand Marquis
<bertrand.marquis@arm.com> wrote:
>
> Add support to raise a Rx buffer full notification to a VM.
> This function will be used for indirect message support between VM and
> is only activated if CONFIG_FFA_VM_TO_VM is selected.
>
> Even if there are 32 framework notifications possible, right now only
> one is defined so the implementation is simplified to only handle the
> buffer full notification using a boolean. If other framework
> notifications have to be supported one day, the design will have to be
> modified to handle it properly.
>
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
> ---
> Changes in v3:
> - introduce a vm_pending boolean to track if VM notifications are
>   pending and allow to decorelate pending secure notifications from
>   pending vm ones
> - remove ifdef around boolean entries for notifications and make use of
>   IS_ENABLED instead of ifdefs when possible
> - Fix notification number signaled to VMs for buffer full to use the
>   proper GUEST_FFA_NOTIF_PEND_INTR_ID instead of the identifier received
>   from the SPMC.
> - Move back into this patch ffa_private.h part which was wrongly in the
>   patch for indirect messages between VM
> Changes in v2:
> - Switch ifdef to IS_ENABLED when possible
> ---
>  xen/arch/arm/tee/ffa_notif.c   | 36 ++++++++++++++++++++++++++++------
>  xen/arch/arm/tee/ffa_private.h | 23 +++++++++++++++++++++-
>  2 files changed, 52 insertions(+), 7 deletions(-)

Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>

Cheers,
Jens

>
> diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c
> index 00efaf8f7353..f6df2f15bb00 100644
> --- a/xen/arch/arm/tee/ffa_notif.c
> +++ b/xen/arch/arm/tee/ffa_notif.c
> @@ -69,6 +69,7 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs)
>  {
>      struct domain *d = current->domain;
>      struct ffa_ctx *ctx = d->arch.tee;
> +    bool notif_pending;
>
>      if ( !notif_enabled )
>      {
> @@ -76,7 +77,11 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs)
>          return;
>      }
>
> -    if ( test_and_clear_bool(ctx->notif.secure_pending) )
> +    notif_pending = test_and_clear_bool(ctx->notif.secure_pending);
> +    if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) )
> +        notif_pending |= test_and_clear_bool(ctx->notif.vm_pending);
> +
> +    if ( notif_pending )
>      {
>          /* A pending global notification for the guest */
>          ffa_set_regs(regs, FFA_SUCCESS_64, 0,
> @@ -93,6 +98,7 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs)
>  void ffa_handle_notification_get(struct cpu_user_regs *regs)
>  {
>      struct domain *d = current->domain;
> +    struct ffa_ctx *ctx = d->arch.tee;
>      uint32_t recv = get_user_reg(regs, 1);
>      uint32_t flags = get_user_reg(regs, 2);
>      uint32_t w2 = 0;
> @@ -132,11 +138,7 @@ void ffa_handle_notification_get(struct cpu_user_regs *regs)
>           */
>          if ( ( flags  & FFA_NOTIF_FLAG_BITMAP_SP ) &&
>               ( flags & FFA_NOTIF_FLAG_BITMAP_SPM ) )
> -        {
> -                struct ffa_ctx *ctx = d->arch.tee;
> -
> -                ACCESS_ONCE(ctx->notif.secure_pending) = false;
> -        }
> +            ACCESS_ONCE(ctx->notif.secure_pending) = false;
>
>          arm_smccc_1_2_smc(&arg, &resp);
>          e = ffa_get_ret_code(&resp);
> @@ -156,6 +158,14 @@ void ffa_handle_notification_get(struct cpu_user_regs *regs)
>              w6 = resp.a6;
>      }
>
> +    if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) &&
> +          flags & FFA_NOTIF_FLAG_BITMAP_HYP &&
> +          test_and_clear_bool(ctx->notif.buff_full_pending) )
> +    {
> +        ACCESS_ONCE(ctx->notif.vm_pending) = false;
> +        w7 = FFA_NOTIF_RX_BUFFER_FULL;
> +    }
> +
>      ffa_set_regs(regs, FFA_SUCCESS_32, 0, w2, w3, w4, w5, w6, w7);
>  }
>
> @@ -178,6 +188,20 @@ int ffa_handle_notification_set(struct cpu_user_regs *regs)
>                             bitmap_hi);
>  }
>
> +#ifdef CONFIG_FFA_VM_TO_VM
> +void ffa_raise_rx_buffer_full(struct domain *d)
> +{
> +    struct ffa_ctx *ctx = d->arch.tee;
> +
> +    if ( !ctx )
> +        return;
> +
> +    ACCESS_ONCE(ctx->notif.buff_full_pending) = true;
> +    if ( !test_and_set_bool(ctx->notif.vm_pending) )
> +        vgic_inject_irq(d, d->vcpu[0], GUEST_FFA_NOTIF_PEND_INTR_ID, true);
> +}
> +#endif
> +
>  /*
>   * Extract a 16-bit ID (index n) from the successful return value from
>   * FFA_NOTIFICATION_INFO_GET_64 or FFA_NOTIFICATION_INFO_GET_32. IDs are
> diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h
> index bd6877d8c632..878af2d76e0e 100644
> --- a/xen/arch/arm/tee/ffa_private.h
> +++ b/xen/arch/arm/tee/ffa_private.h
> @@ -210,6 +210,8 @@
>  #define FFA_NOTIF_INFO_GET_ID_COUNT_SHIFT   7
>  #define FFA_NOTIF_INFO_GET_ID_COUNT_MASK    0x1F
>
> +#define FFA_NOTIF_RX_BUFFER_FULL        BIT(0, U)
> +
>  /* Feature IDs used with FFA_FEATURES */
>  #define FFA_FEATURE_NOTIF_PEND_INTR     0x1U
>  #define FFA_FEATURE_SCHEDULE_RECV_INTR  0x2U
> @@ -295,9 +297,20 @@ struct ffa_mem_region {
>  struct ffa_ctx_notif {
>      /*
>       * True if domain is reported by FFA_NOTIFICATION_INFO_GET to have
> -     * pending global notifications.
> +     * pending notifications from the secure world.
>       */
>      bool secure_pending;
> +
> +    /*
> +     * True if domain is reported by FFA_NOTIFICATION_INFO_GET to have
> +     * pending notifications from VMs (including framework ones).
> +     */
> +    bool vm_pending;
> +
> +    /*
> +     * True if domain has buffer full notification pending
> +     */
> +    bool buff_full_pending;
>  };
>
>  struct ffa_ctx {
> @@ -369,6 +382,14 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs);
>  void ffa_handle_notification_get(struct cpu_user_regs *regs);
>  int ffa_handle_notification_set(struct cpu_user_regs *regs);
>
> +#ifdef CONFIG_FFA_VM_TO_VM
> +void ffa_raise_rx_buffer_full(struct domain *d);
> +#else
> +static inline void ffa_raise_rx_buffer_full(struct domain *d)
> +{
> +}
> +#endif
> +
>  void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid);
>  int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs);
>
> --
> 2.47.1
>
diff mbox series

Patch

diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c
index 00efaf8f7353..f6df2f15bb00 100644
--- a/xen/arch/arm/tee/ffa_notif.c
+++ b/xen/arch/arm/tee/ffa_notif.c
@@ -69,6 +69,7 @@  void ffa_handle_notification_info_get(struct cpu_user_regs *regs)
 {
     struct domain *d = current->domain;
     struct ffa_ctx *ctx = d->arch.tee;
+    bool notif_pending;
 
     if ( !notif_enabled )
     {
@@ -76,7 +77,11 @@  void ffa_handle_notification_info_get(struct cpu_user_regs *regs)
         return;
     }
 
-    if ( test_and_clear_bool(ctx->notif.secure_pending) )
+    notif_pending = test_and_clear_bool(ctx->notif.secure_pending);
+    if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) )
+        notif_pending |= test_and_clear_bool(ctx->notif.vm_pending);
+
+    if ( notif_pending )
     {
         /* A pending global notification for the guest */
         ffa_set_regs(regs, FFA_SUCCESS_64, 0,
@@ -93,6 +98,7 @@  void ffa_handle_notification_info_get(struct cpu_user_regs *regs)
 void ffa_handle_notification_get(struct cpu_user_regs *regs)
 {
     struct domain *d = current->domain;
+    struct ffa_ctx *ctx = d->arch.tee;
     uint32_t recv = get_user_reg(regs, 1);
     uint32_t flags = get_user_reg(regs, 2);
     uint32_t w2 = 0;
@@ -132,11 +138,7 @@  void ffa_handle_notification_get(struct cpu_user_regs *regs)
          */
         if ( ( flags  & FFA_NOTIF_FLAG_BITMAP_SP ) &&
              ( flags & FFA_NOTIF_FLAG_BITMAP_SPM ) )
-        {
-                struct ffa_ctx *ctx = d->arch.tee;
-
-                ACCESS_ONCE(ctx->notif.secure_pending) = false;
-        }
+            ACCESS_ONCE(ctx->notif.secure_pending) = false;
 
         arm_smccc_1_2_smc(&arg, &resp);
         e = ffa_get_ret_code(&resp);
@@ -156,6 +158,14 @@  void ffa_handle_notification_get(struct cpu_user_regs *regs)
             w6 = resp.a6;
     }
 
+    if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) &&
+          flags & FFA_NOTIF_FLAG_BITMAP_HYP &&
+          test_and_clear_bool(ctx->notif.buff_full_pending) )
+    {
+        ACCESS_ONCE(ctx->notif.vm_pending) = false;
+        w7 = FFA_NOTIF_RX_BUFFER_FULL;
+    }
+
     ffa_set_regs(regs, FFA_SUCCESS_32, 0, w2, w3, w4, w5, w6, w7);
 }
 
@@ -178,6 +188,20 @@  int ffa_handle_notification_set(struct cpu_user_regs *regs)
                            bitmap_hi);
 }
 
+#ifdef CONFIG_FFA_VM_TO_VM
+void ffa_raise_rx_buffer_full(struct domain *d)
+{
+    struct ffa_ctx *ctx = d->arch.tee;
+
+    if ( !ctx )
+        return;
+
+    ACCESS_ONCE(ctx->notif.buff_full_pending) = true;
+    if ( !test_and_set_bool(ctx->notif.vm_pending) )
+        vgic_inject_irq(d, d->vcpu[0], GUEST_FFA_NOTIF_PEND_INTR_ID, true);
+}
+#endif
+
 /*
  * Extract a 16-bit ID (index n) from the successful return value from
  * FFA_NOTIFICATION_INFO_GET_64 or FFA_NOTIFICATION_INFO_GET_32. IDs are
diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h
index bd6877d8c632..878af2d76e0e 100644
--- a/xen/arch/arm/tee/ffa_private.h
+++ b/xen/arch/arm/tee/ffa_private.h
@@ -210,6 +210,8 @@ 
 #define FFA_NOTIF_INFO_GET_ID_COUNT_SHIFT   7
 #define FFA_NOTIF_INFO_GET_ID_COUNT_MASK    0x1F
 
+#define FFA_NOTIF_RX_BUFFER_FULL        BIT(0, U)
+
 /* Feature IDs used with FFA_FEATURES */
 #define FFA_FEATURE_NOTIF_PEND_INTR     0x1U
 #define FFA_FEATURE_SCHEDULE_RECV_INTR  0x2U
@@ -295,9 +297,20 @@  struct ffa_mem_region {
 struct ffa_ctx_notif {
     /*
      * True if domain is reported by FFA_NOTIFICATION_INFO_GET to have
-     * pending global notifications.
+     * pending notifications from the secure world.
      */
     bool secure_pending;
+
+    /*
+     * True if domain is reported by FFA_NOTIFICATION_INFO_GET to have
+     * pending notifications from VMs (including framework ones).
+     */
+    bool vm_pending;
+
+    /*
+     * True if domain has buffer full notification pending
+     */
+    bool buff_full_pending;
 };
 
 struct ffa_ctx {
@@ -369,6 +382,14 @@  void ffa_handle_notification_info_get(struct cpu_user_regs *regs);
 void ffa_handle_notification_get(struct cpu_user_regs *regs);
 int ffa_handle_notification_set(struct cpu_user_regs *regs);
 
+#ifdef CONFIG_FFA_VM_TO_VM
+void ffa_raise_rx_buffer_full(struct domain *d);
+#else
+static inline void ffa_raise_rx_buffer_full(struct domain *d)
+{
+}
+#endif
+
 void ffa_handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid);
 int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs);