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/inc/hf/arch/plat/ffa.h b/inc/hf/arch/plat/ffa.h
index 6142440..07f274f 100644
--- a/inc/hf/arch/plat/ffa.h
+++ b/inc/hf/arch/plat/ffa.h
@@ -311,3 +311,6 @@
void plat_ffa_unwind_call_chain_ffa_direct_resp(struct vcpu *current,
struct vcpu *next);
+
+void plat_ffa_enable_virtual_maintenance_interrupts(
+ struct vcpu_locked current_locked);
diff --git a/inc/hf/manifest.h b/inc/hf/manifest.h
index 0985217..60c6f76 100644
--- a/inc/hf/manifest.h
+++ b/inc/hf/manifest.h
@@ -151,6 +151,8 @@
uint8_t messaging_method;
/** mandatory - action in response to non secure interrupt */
uint8_t ns_interrupts_action;
+ /** optional - managed exit signaled through vIRQ */
+ bool me_signal_virq;
/** optional - receipt of notifications. */
bool notification_support;
/** optional */
diff --git a/inc/hf/vm.h b/inc/hf/vm.h
index e87e2b8..350d3b4 100644
--- a/inc/hf/vm.h
+++ b/inc/hf/vm.h
@@ -222,6 +222,7 @@
* non secure interrupt.
*/
uint8_t ns_interrupts_action;
+ bool me_signal_virq;
struct vm *next_boot;
/**
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",
diff --git a/test/vmapi/ffa_secure_partitions/services/partition_services.c b/test/vmapi/ffa_secure_partitions/services/partition_services.c
index 3fa669a..b4ae2cd 100644
--- a/test/vmapi/ffa_secure_partitions/services/partition_services.c
+++ b/test/vmapi/ffa_secure_partitions/services/partition_services.c
@@ -146,8 +146,6 @@
if (sel1_secure_service) {
/* S-EL1 partition, register interrupt handler for NPI. */
exception_setup(irq, NULL);
- hf_interrupt_enable(HF_NOTIFICATION_PENDING_INTID, true,
- INTERRUPT_TYPE_IRQ);
arch_irq_enable();
} else {
/*