feat(ff-a): handle forwarded FFA_VERSION from SPMD
The SPMD must forward calls to FFA_VERSION to the SPMC so that the
ff-a version of the callee can be saved for later use. Since the
return value of FFA_VERSION is not wrapped in a FF-A call we must
forward the call using a direct message request from the SPMD to
the SPMC. W2 of this request is used to identify the function
that should handle the message. Update the spmd_handler function
to choose the appropriate function to handle the message based on
W2 for both PSCI and FFA_VERSION.
Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
Change-Id: Ibf55f33130242303dd19f500f55abed5f06dbbef
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index bf5d530..94a0c5b 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -56,6 +56,15 @@
*/
#define CLIENT_ID_MASK UINT64_C(0xffff)
+/*
+ * Target function IDs for framework messages from the SPMD.
+ */
+#define SPMD_FWK_MSG_BIT UINT64_C(1 << 31)
+#define SPMD_FWK_MSG_FUNC_MASK UINT64_C(0xFF)
+#define SPMD_FWK_MSG_PSCI UINT8_C(0)
+#define SPMD_FWK_MSG_FFA_VERSION_REQ UINT8_C(0x8)
+#define SPMD_FWK_MSG_FFA_VERSION_RESP UINT8_C(0x9)
+
/**
* Returns a reference to the currently executing vCPU.
*/
@@ -367,39 +376,67 @@
ffa_vm_id_t sender = ffa_sender(*args);
ffa_vm_id_t receiver = ffa_receiver(*args);
ffa_vm_id_t current_vm_id = current->vm->id;
+ uint32_t fwk_msg = ffa_fwk_msg(*args);
+ uint8_t fwk_msg_func_id = fwk_msg & SPMD_FWK_MSG_FUNC_MASK;
/*
- * Check if direct message request is originating from the SPMD and
- * directed to the SPMC.
+ * Check if direct message request is originating from the SPMD,
+ * directed to the SPMC and the message is a framework message.
*/
if (!(sender == HF_SPMD_VM_ID && receiver == HF_SPMC_VM_ID &&
- current_vm_id == HF_OTHER_WORLD_ID)) {
+ current_vm_id == HF_OTHER_WORLD_ID) ||
+ (fwk_msg & SPMD_FWK_MSG_BIT) == 0) {
return false;
}
- switch (args->arg3) {
- case PSCI_CPU_OFF: {
- struct vm *vm = vm_get_first_boot();
- struct vcpu *vcpu = vm_get_vcpu(vm, vcpu_index(current));
+ switch (fwk_msg_func_id) {
+ case SPMD_FWK_MSG_PSCI: {
+ switch (args->arg3) {
+ case PSCI_CPU_OFF: {
+ struct vm *vm = vm_get_first_boot();
+ struct vcpu *vcpu =
+ vm_get_vcpu(vm, vcpu_index(current));
- /*
- * TODO: the PM event reached the SPMC. In a later iteration,
- * the PM event can be passed to the SP by resuming it.
- */
+ /*
+ * TODO: the PM event reached the SPMC. In a later
+ * iteration, the PM event can be passed to the SP by
+ * resuming it.
+ */
+ *args = (struct ffa_value){
+ .func = FFA_MSG_SEND_DIRECT_RESP_32,
+ .arg1 = ((uint64_t)HF_SPMC_VM_ID << 16) |
+ HF_SPMD_VM_ID,
+ .arg2 = 0U};
+
+ dlog_verbose("%s cpu off notification cpuid %#x\n",
+ __func__, vcpu->cpu->id);
+ cpu_off(vcpu->cpu);
+ break;
+ }
+ default:
+ dlog_verbose("%s PSCI message not handled %#x\n",
+ __func__, args->arg3);
+ return false;
+ }
+ }
+ case SPMD_FWK_MSG_FFA_VERSION_REQ: {
+ struct ffa_value ret = api_ffa_version(current, args->arg3);
*args = (struct ffa_value){
.func = FFA_MSG_SEND_DIRECT_RESP_32,
.arg1 = ((uint64_t)HF_SPMC_VM_ID << 16) | HF_SPMD_VM_ID,
- .arg2 = 0U};
-
- dlog_verbose("%s cpu off notification cpuid %#x\n", __func__,
- vcpu->cpu->id);
- cpu_off(vcpu->cpu);
+ /* Set bit 31 since this is a framework message. */
+ .arg2 = SPMD_FWK_MSG_BIT |
+ SPMD_FWK_MSG_FFA_VERSION_RESP,
+ .arg3 = ret.func};
break;
}
default:
- dlog_verbose("%s message not handled %#x\n", __func__,
- args->arg3);
- return false;
+ dlog_verbose("%s message not handled %#x\n", __func__, fwk_msg);
+ *args = (struct ffa_value){
+ .func = FFA_MSG_SEND_DIRECT_RESP_32,
+ .arg1 = ((uint64_t)HF_SPMC_VM_ID << 16) | HF_SPMD_VM_ID,
+ /* Set bit 31 since this is a framework message. */
+ .arg2 = SPMD_FWK_MSG_BIT | fwk_msg_func_id};
}
return true;