feat(interrupts): preferred managed exit signal
A SP optionally specifies if vIRQ is the preferred choice for
signaling Managed Exit in response to a non secure interrupt.
Moreover, SPMC enables the following virtual maintenenace interrupts
by default for each Secure Partition:
> Managed Exit Interrupt
> Notification Pending Interrupt
Change-Id: I17131b42ee6fae2896804e4f952d9a371f237cd5
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 4bab99c..abab7a4 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -492,3 +492,9 @@
(void)current;
(void)next;
}
+
+void plat_ffa_enable_virtual_maintenance_interrupts(
+ struct vcpu_locked current_locked)
+{
+ (void)current_locked;
+}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index fc1548a..9629a61 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -998,3 +998,9 @@
(void)current;
(void)next;
}
+
+void plat_ffa_enable_virtual_maintenance_interrupts(
+ struct vcpu_locked current_locked)
+{
+ (void)current_locked;
+}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index ef39ce4..c3de2d5 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -2040,3 +2040,38 @@
sl_unlock(&next->lock);
sl_unlock(¤t->lock);
}
+
+void plat_ffa_enable_virtual_maintenance_interrupts(
+ struct vcpu_locked current_locked)
+{
+ struct vcpu *current;
+ struct interrupts *interrupts;
+ struct vm *vm;
+
+ current = current_locked.vcpu;
+ interrupts = ¤t->interrupts;
+ vm = current->vm;
+
+ if (plat_ffa_vm_managed_exit_supported(vm)) {
+ vcpu_virt_interrupt_set_enabled(interrupts,
+ HF_MANAGED_EXIT_INTID);
+ /*
+ * SPMC decides the interrupt type for Managed exit signal based
+ * on the partition manifest.
+ */
+ if (vm->me_signal_virq) {
+ vcpu_virt_interrupt_set_type(interrupts,
+ HF_MANAGED_EXIT_INTID,
+ INTERRUPT_TYPE_IRQ);
+ } else {
+ vcpu_virt_interrupt_set_type(interrupts,
+ HF_MANAGED_EXIT_INTID,
+ INTERRUPT_TYPE_FIQ);
+ }
+ }
+
+ if (vm->notifications.enabled) {
+ vcpu_virt_interrupt_set_enabled(interrupts,
+ HF_NOTIFICATION_PENDING_INTID);
+ }
+}
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index c41169b..0f45e3b 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -465,3 +465,9 @@
(void)current;
(void)next;
}
+
+void plat_ffa_enable_virtual_maintenance_interrupts(
+ struct vcpu_locked current_locked)
+{
+ (void)current_locked;
+}
diff --git a/src/load.c b/src/load.c
index db4de88..d105f72 100644
--- a/src/load.c
+++ b/src/load.c
@@ -207,6 +207,9 @@
vm_locked.vm->ns_interrupts_action =
manifest_vm->partition.ns_interrupts_action;
+ vm_locked.vm->me_signal_virq =
+ manifest_vm->partition.me_signal_virq;
+
vm_locked.vm->notifications.enabled =
manifest_vm->partition.notification_support;
@@ -837,6 +840,10 @@
vcpu = vm_get_vcpu(vm, 0);
vcpu_locked = vcpu_lock(vcpu);
+
+ /* Enable virtual maintenance interrupts for Secure Partitions. */
+ plat_ffa_enable_virtual_maintenance_interrupts(vcpu_locked);
+
if (has_fdt) {
vcpu_secondary_reset_and_start(vcpu_locked, secondary_entry,
pa_addr(fdt_addr));
diff --git a/src/manifest.c b/src/manifest.c
index b6c6e9a..90aefd7 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -910,6 +910,12 @@
"partition\n");
return MANIFEST_ILLEGAL_NS_ACTION;
}
+
+ TRY(read_bool(&root, "managed-exit-virq",
+ &vm->partition.me_signal_virq));
+ if (vm->partition.me_signal_virq) {
+ dlog_verbose(" Managed Exit signaled through vIRQ\n");
+ }
}
TRY(read_bool(&root, "notification-support",