From: Mykola Kvach <[email protected]> The FF-A notification SRI interrupt handler was not correctly tied to CPU hotplug and suspend/resume. As a result, CPUs going offline and back online could end up with stale or missing handlers, breaking delivery of FF-A notifications.
Signed-off-by: Mykola Kvach <[email protected]> --- xen/arch/arm/tee/ffa_notif.c | 63 ++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c index 86bef6b3b2..84f5c6b43b 100644 --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -359,10 +359,28 @@ static int32_t ffa_notification_bitmap_destroy(uint16_t vm_id) return ffa_simple_call(FFA_NOTIFICATION_BITMAP_DESTROY, vm_id, 0, 0, 0); } -void ffa_notif_init_interrupt(void) +static DEFINE_PER_CPU_READ_MOSTLY(struct irqaction, sri_irq); + +static int request_sri_irq(void) { int ret; + struct irqaction *sri_action = &this_cpu(sri_irq); + + sri_action->name = "FF-A notif"; + sri_action->handler = notif_irq_handler; + sri_action->dev_id = NULL; + sri_action->free_on_release = 0; + + ret = setup_irq(notif_sri_irq, 0, sri_action); + if ( ret ) + printk(XENLOG_ERR "ffa: setup_irq irq %u failed: error %d\n", + notif_sri_irq, ret); + return ret; +} + +void ffa_notif_init_interrupt(void) +{ if ( fw_notif_enabled && notif_sri_irq < NR_GIC_SGI ) { /* @@ -375,14 +393,36 @@ void ffa_notif_init_interrupt(void) * pending, while the SPMC in the secure world will not notice that * the interrupt was lost. */ - ret = request_irq(notif_sri_irq, 0, notif_irq_handler, "FF-A notif", - NULL); - if ( ret ) - printk(XENLOG_ERR "ffa: request_irq irq %u failed: error %d\n", - notif_sri_irq, ret); + request_sri_irq(); } } +static void deinit_ffa_notif_interrupt(void) +{ + if ( fw_notif_enabled && notif_sri_irq < NR_GIC_SGI ) + release_irq(notif_sri_irq, NULL); +} + +static int cpu_ffa_notif_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch ( action ) + { + case CPU_DYING: + deinit_ffa_notif_interrupt(); + break; + default: + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block cpu_ffa_notif_nfb = { + .notifier_call = cpu_ffa_notif_callback, +}; + void ffa_notif_init(void) { const struct arm_smccc_1_2_regs arg = { @@ -391,7 +431,6 @@ void ffa_notif_init(void) }; struct arm_smccc_1_2_regs resp; unsigned int irq; - int ret; /* Only enable fw notification if all ABIs we need are supported */ if ( ffa_fw_supports_fid(FFA_NOTIFICATION_BITMAP_CREATE) && @@ -407,13 +446,11 @@ void ffa_notif_init(void) notif_sri_irq = irq; if ( irq >= NR_GIC_SGI ) irq_set_type(irq, IRQ_TYPE_EDGE_RISING); - ret = request_irq(irq, 0, notif_irq_handler, "FF-A notif", NULL); - if ( ret ) - { - printk(XENLOG_ERR "ffa: request_irq irq %u failed: error %d\n", - irq, ret); + + if ( request_sri_irq() ) return; - } + + register_cpu_notifier(&cpu_ffa_notif_nfb); fw_notif_enabled = true; } } -- 2.43.0
