[PATCH 10/10] xen/arm: ffa: advertise FF-A v1.2

Bertrand Marquis posted 10 patches 2 weeks, 2 days ago
There is a newer version of this series
[PATCH 10/10] xen/arm: ffa: advertise FF-A v1.2
Posted by Bertrand Marquis 2 weeks, 2 days ago
Advertise RUN/YIELD/INTERRUPT via FFA_FEATURES now that the runtime
helpers are in place, and expose the RX/TX MAP capacity field only once
a guest has negotiated FF-A v1.2.

While there, drop the stale <asm/tee/ffa.h> include.

To comply with the wider v1.2 register ABI, zero registers x8–x17 when
responding to a v1.2 VM. The dispatcher also rejects SMCCC64 calls from
AArch32 guests.

Finally, bump Xen's FF-A version to 1.2.

Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
 xen/arch/arm/tee/ffa.c         | 25 ++++++++++++++++++++-----
 xen/arch/arm/tee/ffa_private.h | 28 +++++++++++++++++++---------
 2 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c
index 8b2f042287fc..c8fe97856d06 100644
--- a/xen/arch/arm/tee/ffa.c
+++ b/xen/arch/arm/tee/ffa.c
@@ -24,9 +24,6 @@
  * o FFA_MEM_DONATE_* and FFA_MEM_LEND_* - Used when tranferring ownership
  *   or access of a memory region
  * o FFA_MSG_SEND2 and FFA_MSG_WAIT - Used for indirect messaging
- * o FFA_MSG_YIELD
- * o FFA_INTERRUPT - Used to report preemption
- * o FFA_RUN
  *
  * Limitations in the implemented FF-A interfaces:
  * o FFA_RXTX_MAP_*:
@@ -68,7 +65,6 @@
 #include <asm/event.h>
 #include <asm/regs.h>
 #include <asm/smccc.h>
-#include <asm/tee/ffa.h>
 #include <asm/tee/tee.h>
 
 #include "ffa_private.h"
@@ -262,6 +258,9 @@ static void handle_features(struct cpu_user_regs *regs)
     case FFA_MSG_SEND_DIRECT_REQ_32:
     case FFA_MSG_SEND_DIRECT_REQ_64:
     case FFA_MSG_SEND2:
+    case FFA_RUN:
+    case FFA_INTERRUPT:
+    case FFA_MSG_YIELD:
         ffa_set_regs_success(regs, 0, 0);
         break;
     case FFA_MSG_SEND_DIRECT_REQ2:
@@ -290,7 +289,16 @@ static void handle_features(struct cpu_user_regs *regs)
          * differs from FFA_PAGE_SIZE (SZ_4K).
          */
         BUILD_BUG_ON(PAGE_SIZE != FFA_PAGE_SIZE);
-        ffa_set_regs_success(regs, 0, 0);
+
+        /*
+         * From FFA v1.2, we can give the maximum number of pages we support
+         * for the RX/TX buffers.
+         */
+        if ( ctx->guest_vers < FFA_VERSION_1_2 )
+            ffa_set_regs_success(regs, 0, 0);
+        else
+            ffa_set_regs_success(regs, FFA_MAX_RXTX_PAGE_COUNT << 16, 0);
+
         break;
     case FFA_FEATURE_NOTIF_PEND_INTR:
         ffa_set_regs_success(regs, GUEST_FFA_NOTIF_PEND_INTR_ID, 0);
@@ -323,6 +331,13 @@ static bool ffa_handle_call(struct cpu_user_regs *regs)
     if ( !ctx )
         return false;
 
+    if ( !is_64bit_domain(d) && smccc_is_conv_64(fid) )
+    {
+        /* 32bit guests should only use 32bit convention calls */
+        ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED);
+        return true;
+    }
+
     /* A version must be negotiated first */
     if ( !ctx->guest_vers_negotiated )
     {
diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h
index a9a03c7c5d71..6afca2ea07ef 100644
--- a/xen/arch/arm/tee/ffa_private.h
+++ b/xen/arch/arm/tee/ffa_private.h
@@ -53,7 +53,7 @@
  * that particular guest or SP.
  */
 #define FFA_MY_VERSION_MAJOR    1U
-#define FFA_MY_VERSION_MINOR    1U
+#define FFA_MY_VERSION_MINOR    2U
 #define FFA_MY_VERSION          MAKE_FFA_VERSION(FFA_MY_VERSION_MAJOR, \
                                                  FFA_MY_VERSION_MINOR)
 
@@ -505,14 +505,24 @@ static inline void ffa_set_regs(struct cpu_user_regs *regs, register_t v0,
                                 register_t v4, register_t v5, register_t v6,
                                 register_t v7)
 {
-        set_user_reg(regs, 0, v0);
-        set_user_reg(regs, 1, v1);
-        set_user_reg(regs, 2, v2);
-        set_user_reg(regs, 3, v3);
-        set_user_reg(regs, 4, v4);
-        set_user_reg(regs, 5, v5);
-        set_user_reg(regs, 6, v6);
-        set_user_reg(regs, 7, v7);
+    struct domain *d = current->domain;
+    struct ffa_ctx *ctx = d->arch.tee;
+    int i;
+
+    set_user_reg(regs, 0, v0);
+    set_user_reg(regs, 1, v1);
+    set_user_reg(regs, 2, v2);
+    set_user_reg(regs, 3, v3);
+    set_user_reg(regs, 4, v4);
+    set_user_reg(regs, 5, v5);
+    set_user_reg(regs, 6, v6);
+    set_user_reg(regs, 7, v7);
+
+    if ( ctx && ctx->guest_vers >= FFA_VERSION_1_2 && ctx->is_64bit )
+    {
+        for (i = 8; i <= 17; i++)
+            set_user_reg(regs, i, 0);
+    }
 }
 
 static inline void ffa_set_regs_error(struct cpu_user_regs *regs,
-- 
2.51.2


Re: [PATCH 10/10] xen/arm: ffa: advertise FF-A v1.2
Posted by Jens Wiklander 1 week, 2 days ago
Hi Bertrand,

On Thu, Nov 27, 2025 at 4:53 PM Bertrand Marquis
<bertrand.marquis@arm.com> wrote:
>
> Advertise RUN/YIELD/INTERRUPT via FFA_FEATURES now that the runtime
> helpers are in place, and expose the RX/TX MAP capacity field only once
> a guest has negotiated FF-A v1.2.
>
> While there, drop the stale <asm/tee/ffa.h> include.
>
> To comply with the wider v1.2 register ABI, zero registers x8–x17 when
> responding to a v1.2 VM. The dispatcher also rejects SMCCC64 calls from
> AArch32 guests.
>
> Finally, bump Xen's FF-A version to 1.2.
>
> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
> ---
>  xen/arch/arm/tee/ffa.c         | 25 ++++++++++++++++++++-----
>  xen/arch/arm/tee/ffa_private.h | 28 +++++++++++++++++++---------
>  2 files changed, 39 insertions(+), 14 deletions(-)
>
> diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c
> index 8b2f042287fc..c8fe97856d06 100644
> --- a/xen/arch/arm/tee/ffa.c
> +++ b/xen/arch/arm/tee/ffa.c
> @@ -24,9 +24,6 @@
>   * o FFA_MEM_DONATE_* and FFA_MEM_LEND_* - Used when tranferring ownership
>   *   or access of a memory region
>   * o FFA_MSG_SEND2 and FFA_MSG_WAIT - Used for indirect messaging
> - * o FFA_MSG_YIELD
> - * o FFA_INTERRUPT - Used to report preemption
> - * o FFA_RUN
>   *
>   * Limitations in the implemented FF-A interfaces:
>   * o FFA_RXTX_MAP_*:
> @@ -68,7 +65,6 @@
>  #include <asm/event.h>
>  #include <asm/regs.h>
>  #include <asm/smccc.h>
> -#include <asm/tee/ffa.h>
>  #include <asm/tee/tee.h>
>
>  #include "ffa_private.h"
> @@ -262,6 +258,9 @@ static void handle_features(struct cpu_user_regs *regs)
>      case FFA_MSG_SEND_DIRECT_REQ_32:
>      case FFA_MSG_SEND_DIRECT_REQ_64:
>      case FFA_MSG_SEND2:
> +    case FFA_RUN:
> +    case FFA_INTERRUPT:
> +    case FFA_MSG_YIELD:
>          ffa_set_regs_success(regs, 0, 0);
>          break;
>      case FFA_MSG_SEND_DIRECT_REQ2:
> @@ -290,7 +289,16 @@ static void handle_features(struct cpu_user_regs *regs)
>           * differs from FFA_PAGE_SIZE (SZ_4K).
>           */
>          BUILD_BUG_ON(PAGE_SIZE != FFA_PAGE_SIZE);
> -        ffa_set_regs_success(regs, 0, 0);
> +
> +        /*
> +         * From FFA v1.2, we can give the maximum number of pages we support
> +         * for the RX/TX buffers.
> +         */
> +        if ( ctx->guest_vers < FFA_VERSION_1_2 )
> +            ffa_set_regs_success(regs, 0, 0);
> +        else
> +            ffa_set_regs_success(regs, FFA_MAX_RXTX_PAGE_COUNT << 16, 0);
> +
>          break;
>      case FFA_FEATURE_NOTIF_PEND_INTR:
>          ffa_set_regs_success(regs, GUEST_FFA_NOTIF_PEND_INTR_ID, 0);
> @@ -323,6 +331,13 @@ static bool ffa_handle_call(struct cpu_user_regs *regs)
>      if ( !ctx )
>          return false;
>
> +    if ( !is_64bit_domain(d) && smccc_is_conv_64(fid) )

You use ctx->is_64bit in ffa_set_regs() below, but here
is_64bit_domain(d). Which one do we prefer?

Cheers,
Jens

> +    {
> +        /* 32bit guests should only use 32bit convention calls */
> +        ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED);
> +        return true;
> +    }
> +
>      /* A version must be negotiated first */
>      if ( !ctx->guest_vers_negotiated )
>      {
> diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h
> index a9a03c7c5d71..6afca2ea07ef 100644
> --- a/xen/arch/arm/tee/ffa_private.h
> +++ b/xen/arch/arm/tee/ffa_private.h
> @@ -53,7 +53,7 @@
>   * that particular guest or SP.
>   */
>  #define FFA_MY_VERSION_MAJOR    1U
> -#define FFA_MY_VERSION_MINOR    1U
> +#define FFA_MY_VERSION_MINOR    2U
>  #define FFA_MY_VERSION          MAKE_FFA_VERSION(FFA_MY_VERSION_MAJOR, \
>                                                   FFA_MY_VERSION_MINOR)
>
> @@ -505,14 +505,24 @@ static inline void ffa_set_regs(struct cpu_user_regs *regs, register_t v0,
>                                  register_t v4, register_t v5, register_t v6,
>                                  register_t v7)
>  {
> -        set_user_reg(regs, 0, v0);
> -        set_user_reg(regs, 1, v1);
> -        set_user_reg(regs, 2, v2);
> -        set_user_reg(regs, 3, v3);
> -        set_user_reg(regs, 4, v4);
> -        set_user_reg(regs, 5, v5);
> -        set_user_reg(regs, 6, v6);
> -        set_user_reg(regs, 7, v7);
> +    struct domain *d = current->domain;
> +    struct ffa_ctx *ctx = d->arch.tee;
> +    int i;
> +
> +    set_user_reg(regs, 0, v0);
> +    set_user_reg(regs, 1, v1);
> +    set_user_reg(regs, 2, v2);
> +    set_user_reg(regs, 3, v3);
> +    set_user_reg(regs, 4, v4);
> +    set_user_reg(regs, 5, v5);
> +    set_user_reg(regs, 6, v6);
> +    set_user_reg(regs, 7, v7);
> +
> +    if ( ctx && ctx->guest_vers >= FFA_VERSION_1_2 && ctx->is_64bit )
> +    {
> +        for (i = 8; i <= 17; i++)
> +            set_user_reg(regs, i, 0);
> +    }
>  }
>
>  static inline void ffa_set_regs_error(struct cpu_user_regs *regs,
> --
> 2.51.2
>
Re: [PATCH 10/10] xen/arm: ffa: advertise FF-A v1.2
Posted by Bertrand Marquis 1 week, 2 days ago
Hi Jens,

> On 4 Dec 2025, at 08:59, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> 
> Hi Bertrand,
> 
> On Thu, Nov 27, 2025 at 4:53 PM Bertrand Marquis
> <bertrand.marquis@arm.com> wrote:
>> 
>> Advertise RUN/YIELD/INTERRUPT via FFA_FEATURES now that the runtime
>> helpers are in place, and expose the RX/TX MAP capacity field only once
>> a guest has negotiated FF-A v1.2.
>> 
>> While there, drop the stale <asm/tee/ffa.h> include.
>> 
>> To comply with the wider v1.2 register ABI, zero registers x8–x17 when
>> responding to a v1.2 VM. The dispatcher also rejects SMCCC64 calls from
>> AArch32 guests.
>> 
>> Finally, bump Xen's FF-A version to 1.2.
>> 
>> Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
>> ---
>> xen/arch/arm/tee/ffa.c         | 25 ++++++++++++++++++++-----
>> xen/arch/arm/tee/ffa_private.h | 28 +++++++++++++++++++---------
>> 2 files changed, 39 insertions(+), 14 deletions(-)
>> 
>> diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c
>> index 8b2f042287fc..c8fe97856d06 100644
>> --- a/xen/arch/arm/tee/ffa.c
>> +++ b/xen/arch/arm/tee/ffa.c
>> @@ -24,9 +24,6 @@
>>  * o FFA_MEM_DONATE_* and FFA_MEM_LEND_* - Used when tranferring ownership
>>  *   or access of a memory region
>>  * o FFA_MSG_SEND2 and FFA_MSG_WAIT - Used for indirect messaging
>> - * o FFA_MSG_YIELD
>> - * o FFA_INTERRUPT - Used to report preemption
>> - * o FFA_RUN
>>  *
>>  * Limitations in the implemented FF-A interfaces:
>>  * o FFA_RXTX_MAP_*:
>> @@ -68,7 +65,6 @@
>> #include <asm/event.h>
>> #include <asm/regs.h>
>> #include <asm/smccc.h>
>> -#include <asm/tee/ffa.h>
>> #include <asm/tee/tee.h>
>> 
>> #include "ffa_private.h"
>> @@ -262,6 +258,9 @@ static void handle_features(struct cpu_user_regs *regs)
>>     case FFA_MSG_SEND_DIRECT_REQ_32:
>>     case FFA_MSG_SEND_DIRECT_REQ_64:
>>     case FFA_MSG_SEND2:
>> +    case FFA_RUN:
>> +    case FFA_INTERRUPT:
>> +    case FFA_MSG_YIELD:
>>         ffa_set_regs_success(regs, 0, 0);
>>         break;
>>     case FFA_MSG_SEND_DIRECT_REQ2:
>> @@ -290,7 +289,16 @@ static void handle_features(struct cpu_user_regs *regs)
>>          * differs from FFA_PAGE_SIZE (SZ_4K).
>>          */
>>         BUILD_BUG_ON(PAGE_SIZE != FFA_PAGE_SIZE);
>> -        ffa_set_regs_success(regs, 0, 0);
>> +
>> +        /*
>> +         * From FFA v1.2, we can give the maximum number of pages we support
>> +         * for the RX/TX buffers.
>> +         */
>> +        if ( ctx->guest_vers < FFA_VERSION_1_2 )
>> +            ffa_set_regs_success(regs, 0, 0);
>> +        else
>> +            ffa_set_regs_success(regs, FFA_MAX_RXTX_PAGE_COUNT << 16, 0);
>> +
>>         break;
>>     case FFA_FEATURE_NOTIF_PEND_INTR:
>>         ffa_set_regs_success(regs, GUEST_FFA_NOTIF_PEND_INTR_ID, 0);
>> @@ -323,6 +331,13 @@ static bool ffa_handle_call(struct cpu_user_regs *regs)
>>     if ( !ctx )
>>         return false;
>> 
>> +    if ( !is_64bit_domain(d) && smccc_is_conv_64(fid) )
> 
> You use ctx->is_64bit in ffa_set_regs() below, but here
> is_64bit_domain(d). Which one do we prefer?

It would definitely be more coherent to use ctx->is_64bit.

I will fix that in next version.

Cheers
Bertrand