FF-A: Respond to PSCI_CPU_OFF from SPMD.
At run-time when a PSCI call is made from NWd, the corresponding SPMD PM
hooks gets called and is eventually routed to the SPMC. This change
implements a generic "SPMD handler" processing PM events that may be
conveyed from SPMD to SPMC such as core suspend, core off.
Change-Id: Id288e26d9fbb8328acc71f5cf68c39e095a0e3da
Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index f7851d9..d923a68 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -260,6 +260,7 @@
}
#if SECURE_WORLD == 1
+
static bool sp_boot_next(struct vcpu *current, struct vcpu **next,
struct ffa_value *ffa_ret)
{
@@ -302,6 +303,54 @@
vm_unlock(¤t_vm_locked);
return ret;
}
+
+/**
+ * Handle special direct messages from SPMD to SPMC. For now related to power
+ * management only.
+ */
+static bool spmd_handler(struct ffa_value *args, struct vcpu *current)
+{
+ ffa_vm_id_t sender = ffa_msg_send_sender(*args);
+ ffa_vm_id_t receiver = ffa_msg_send_receiver(*args);
+ ffa_vm_id_t current_vm_id = current->vm->id;
+
+ /*
+ * Check if direct message request is originating from the SPMD and
+ * directed to the SPMC.
+ */
+ if (!(sender == HF_SPMD_VM_ID && receiver == HF_SPMC_VM_ID &&
+ current_vm_id == HF_OTHER_WORLD_ID)) {
+ 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));
+
+ /*
+ * 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 message not handled %#x\n", __func__,
+ args->arg3);
+ return false;
+ }
+
+ return true;
+}
+
#endif
/**
@@ -460,11 +509,17 @@
(args->arg4 >> 16) & 0xffff,
current);
return true;
- case FFA_MSG_SEND_DIRECT_REQ_32:
+ case FFA_MSG_SEND_DIRECT_REQ_32: {
+#if SECURE_WORLD == 1
+ if (spmd_handler(args, current)) {
+ return true;
+ }
+#endif
*args = api_ffa_msg_send_direct_req(
ffa_msg_send_sender(*args),
ffa_msg_send_receiver(*args), *args, current, next);
return true;
+ }
case FFA_MSG_SEND_DIRECT_RESP_32:
*args = api_ffa_msg_send_direct_resp(
ffa_msg_send_sender(*args),