refactor: handling of FFA_INTERRUPT ABI
This is the first patch attempting to simplify further
the handling of secure interrupts.
The ABI FFA_INTERRUPT should be invoked at the non-secure
FF-A instance, when the NWd is preempted by a secure interrupt.
In case the target SP is not ready to handle the interrupt
the function plat_ffa_handle_secure_interrupt could
return FFA_NORMAL_WORLD_RESUME.
The referred function is also used in the handler of irqs,
and in such case the ffa_value is not relevant.
So in attempt to simplify things further, the return ABI
FFA_NORMAL_WORLD_RESUME is moved explicitly to the handling
of FFA_INTERRUPT:
- If an SP is dispatched at the handling of FFA_INTERRUPT,
the NWd will eventually receive the ABI resultant from the
call used by the SP to go back to waiting state. In other words
the FFA_NORMAL_WORLD_RESUME ABI will be overwritten.
- If the SP is not dispatched then the FFA_NORMAL_WORLD_RESUME
ABI used for the SPMD to dispatch the NWd.
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: I1efc003bd2c7baeffcae0a59dc2429d2ffb151fa
diff --git a/inc/hf/arch/plat/ffa.h b/inc/hf/arch/plat/ffa.h
index 97f0c05..cc1319f 100644
--- a/inc/hf/arch/plat/ffa.h
+++ b/inc/hf/arch/plat/ffa.h
@@ -259,8 +259,7 @@
int64_t plat_ffa_interrupt_deactivate(uint32_t pint_id, uint32_t vint_id,
struct vcpu *current);
-struct ffa_value plat_ffa_handle_secure_interrupt(struct vcpu *current,
- struct vcpu **next);
+void plat_ffa_handle_secure_interrupt(struct vcpu *current, struct vcpu **next);
bool plat_ffa_inject_notification_pending_interrupt(
struct vcpu_locked next_locked, struct vcpu_locked current_locked,
struct vm_locked receiver_locked);
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 231d374..390b555 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -715,7 +715,20 @@
*args = ffa_error(FFA_DENIED);
return true;
}
- *args = plat_ffa_handle_secure_interrupt(current, next);
+
+ plat_ffa_handle_secure_interrupt(current, next);
+
+ /*
+ * If the next vCPU belongs to an SP, the next time the NWd
+ * gets resumed these values will be overwritten by the ABI
+ * that used to handover execution back to the NWd.
+ * If the NWd is to be resumed from here, then it will
+ * receive the FFA_NORMAL_WORLD_RESUME ABI which is to signal
+ * that an interrupt has occured, thought it wasn't handled.
+ * This happens when the target vCPU was in preempted state,
+ * and the SP couldn't not be resumed to handle the interrupt.
+ */
+ *args = (struct ffa_value){.func = FFA_NORMAL_WORLD_RESUME};
return true;
case FFA_CONSOLE_LOG_32:
case FFA_CONSOLE_LOG_64:
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index ac3dc5e..becd42e 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -811,8 +811,7 @@
return true;
}
-struct ffa_value plat_ffa_handle_secure_interrupt(struct vcpu *current,
- struct vcpu **next)
+void plat_ffa_handle_secure_interrupt(struct vcpu *current, struct vcpu **next)
{
(void)current;
(void)next;
@@ -822,8 +821,6 @@
* SPMC. Execution should not reach hypervisor with this ABI.
*/
CHECK(false);
-
- return ffa_error(FFA_NOT_SUPPORTED);
}
void plat_ffa_sri_state_set(enum plat_ffa_sri_state state)
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 3eed88e..722607a 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -1654,15 +1654,13 @@
* CPU in order for it to service the virtual interrupt. This design limitation
* simplifies the interrupt management implementation in SPMC.
*/
-struct ffa_value plat_ffa_handle_secure_interrupt(struct vcpu *current,
- struct vcpu **next)
+void plat_ffa_handle_secure_interrupt(struct vcpu *current, struct vcpu **next)
{
struct vcpu *target_vcpu;
struct vcpu_locked target_vcpu_locked =
(struct vcpu_locked){.vcpu = NULL};
struct vcpu_locked current_locked;
struct two_vcpu_locked vcpus_locked;
- struct ffa_value ffa_ret = ffa_error(FFA_NOT_SUPPORTED);
uint32_t id;
/* Find pending interrupt id. This also activates the interrupt. */
@@ -1718,16 +1716,6 @@
* processing interrupt, resume the current vCPU.
*/
if (*next == NULL) {
- /*
- * If next is NULL, it means the SPMC can't resume
- * the SP. If the normal world has been preempted,
- * use FFA_NORMAL_WORLD_RESUME for SPMD to give
- * execution back to the Normal World.
- */
- if (current->vm->id == HF_OTHER_WORLD_ID) {
- ffa_ret = (struct ffa_value){
- .func = FFA_NORMAL_WORLD_RESUME};
- }
target_vcpu_locked.vcpu->preempted_vcpu = NULL;
} else {
target_vcpu_locked.vcpu->preempted_vcpu = current;
@@ -1742,8 +1730,6 @@
}
vcpu_unlock(¤t_locked);
-
- return ffa_ret;
}
/**