@@ -141,13 +141,24 @@ static void handle_version(struct cpu_user_regs *regs)
struct ffa_ctx *ctx = d->arch.tee;
uint32_t vers = get_user_reg(regs, 1);
- if ( vers < FFA_VERSION_1_1 )
- vers = FFA_VERSION_1_0;
- else
- vers = FFA_VERSION_1_1;
+ /**
+ * As of now we only support 1.0 or 1.1.
+ * For any 1.x >= 1.1 return OK with 1.1
+ * For 1.0 return OK with 1.0
+ * For anything else return an error.
+ */
+ if ( (vers >> FFA_VERSION_MAJOR_SHIFT) == FFA_MY_VERSION_MAJOR )
+ {
+ if ( vers < FFA_VERSION_1_1 )
+ vers = FFA_VERSION_1_0;
+ else
+ vers = FFA_VERSION_1_1;
- ctx->guest_vers = vers;
- ffa_set_regs(regs, vers, 0, 0, 0, 0, 0, 0, 0);
+ ctx->guest_vers = vers;
+ ffa_set_regs(regs, vers, 0, 0, 0, 0, 0, 0, 0);
+ }
+ else
+ ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED);
}
static void handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid)
@@ -530,7 +541,8 @@ static bool ffa_probe(void)
goto err_no_fw;
}
- if ( vers < FFA_MIN_SPMC_VERSION || vers > FFA_MY_VERSION )
+ if ( vers < FFA_MIN_SPMC_VERSION ||
+ (vers >> FFA_VERSION_MAJOR_SHIFT) != FFA_MY_VERSION_MAJOR )
{
printk(XENLOG_ERR "ffa: Incompatible version %#x found\n", vers);
goto err_no_fw;
@@ -542,7 +554,17 @@ static bool ffa_probe(void)
printk(XENLOG_INFO "ARM FF-A Firmware version %u.%u\n",
major_vers, minor_vers);
- ffa_fw_version = vers;
+ /**
+ * If the call succeed and the version returned is higher or equal to
+ * the one Xen requested, the version requested by Xen will be the one
+ * used. If the version returned is lower but compatible with Xen, Xen
+ * will use that version instead.
+ * A version with a different major is rejected before.
+ */
+ if ( vers > FFA_MY_VERSION )
+ ffa_fw_version = FFA_MY_VERSION;
+ else
+ ffa_fw_version = vers;
for ( int i = 0; i < ARRAY_SIZE(ffa_fw_feat_needed); i++ )
{
Fix FFA version negotiation with the firmware to follow the specification guidance more closely. When the firmware returns OK we can have several cases: - the version requested is accepted but the firmware supports a greater one in the same major. - the firmware supports a greater major version. It could still return OK even if the version requested is not accepted. Reject it. - the firmware supports a lower version. It will return OK and give that version. Check if we support it and use it or reject it if we do not. Adapt the code to: - reject any version lower than the one we support or not with the same major version - use the version returned if in our supported range (currently 1.1 only) - use 1.1 if the version returned is greater. Also adapt the handling of version requests from VM: - return an error for a different major - return 1.1 for a version >= 1.1 - return 1.0 if 1.0 was requested Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com> --- xen/arch/arm/tee/ffa.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-)