feat(ff-a): save partitions version during ffa_version

This will be useful later when we may need to consider the version
of a partition when structuring a response to certain FF-A functions.

Also add a call to FFA_VERSION during initialization of the hypervisor
so the SPMC knows the hypervisors implemented version.

Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
Change-Id: Ia8f5f8a9589300311a1e129536acce0948d5a6bc
diff --git a/src/api.c b/src/api.c
index 56b8bc2..de2bf5b 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1794,8 +1794,11 @@
 }
 
 /** Returns the version of the implemented FF-A specification. */
-struct ffa_value api_ffa_version(uint32_t requested_version)
+struct ffa_value api_ffa_version(struct vcpu *current,
+				 uint32_t requested_version)
 {
+	struct vm_locked current_vm_locked;
+
 	/*
 	 * Ensure that both major and minor revision representation occupies at
 	 * most 15 bits.
@@ -1809,6 +1812,10 @@
 		return (struct ffa_value){.func = (uint32_t)FFA_NOT_SUPPORTED};
 	}
 
+	current_vm_locked = vm_lock(current->vm);
+	current_vm_locked.vm->ffa_version = requested_version;
+	vm_unlock(&current_vm_locked);
+
 	return ((struct ffa_value){.func = FFA_VERSION_COMPILED});
 }
 
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index c0d8c28..9bedee8 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -485,7 +485,7 @@
 	 */
 	switch (func) {
 	case FFA_VERSION_32:
-		*args = api_ffa_version(args->arg1);
+		*args = api_ffa_version(current, args->arg1);
 		return true;
 	case FFA_PARTITION_INFO_GET_32: {
 		struct ffa_uuid uuid;
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 4d0e349..b8489e3 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -76,6 +76,17 @@
 
 	arch_ffa_init();
 
+	/*
+	 * Call FFA_VERSION so the SPMC can store the hypervisor's
+	 * version. This may be useful if there is a mismatch of
+	 * versions.
+	 */
+	ret = arch_other_world_call((struct ffa_value){
+		.func = FFA_VERSION_32, .arg1 = FFA_VERSION_COMPILED});
+	if (ret.func == (uint32_t)FFA_NOT_SUPPORTED) {
+		panic("Hypervisor and SPMC versions are not compatible.\n");
+	}
+
 	/* Setup TEE VM RX/TX buffers */
 	other_world_vm->mailbox.send = &other_world_send_buffer;
 	other_world_vm->mailbox.recv = &other_world_recv_buffer;
diff --git a/src/init.c b/src/init.c
index db05ad9..ab8d8a4 100644
--- a/src/init.c
+++ b/src/init.c
@@ -174,7 +174,7 @@
 	/* Enable TLB invalidation for VM page table updates. */
 	mm_vm_enable_invalidation();
 
-	/* Set up message buffers for TEE dispatcher. */
+	/* Perform platform specfic FF-A initialization. */
 	plat_ffa_init(manifest.ffa_tee_enabled);
 
 	dlog_info("Hafnium initialisation completed\n");
diff --git a/src/load.c b/src/load.c
index 501d00e..0aebb54 100644
--- a/src/load.c
+++ b/src/load.c
@@ -187,6 +187,7 @@
 	dlog_verbose("VM has %d physical interrupts defined in manifest.\n", k);
 
 	if (manifest_vm->is_ffa_partition) {
+		vm_locked.vm->ffa_version = manifest_vm->partition.ffa_version;
 		/* Link rxtx buffers to mailbox */
 		if (manifest_vm->partition.rxtx.available) {
 			if (!link_rxtx_to_mailbox(stage1_locked, vm_locked,