Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit e306a89

Browse files
SiFiveHollandKAGA-KOKO
authored andcommitted
irqchip/sifive-plic: Chain to parent IRQ after handlers are ready
Now that the PLIC uses a platform driver, the driver is probed later in the boot process, where interrupts from peripherals might already be pending. As a result, plic_handle_irq() may be called as early as the call to irq_set_chained_handler() completes. But this call happens before the per-context handler is completely set up, so there is a window where plic_handle_irq() can see incomplete per-context state and crash. Avoid this by delaying the call to irq_set_chained_handler() until all handlers from all PLICs are initialized. Fixes: 8ec99b0 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver") Reported-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Samuel Holland <samuel.holland@sifive.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Anup Patel <anup@brainfault.org> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240529215458.937817-1-samuel.holland@sifive.com Closes: https://lore.kernel.org/r/CAMuHMdVYFFR7K5SbHBLY-JHhb7YpgGMS_hnRWm8H0KD-wBo+4A@mail.gmail.com/
1 parent 0110c4b commit e306a89

File tree

1 file changed

+17
-17
lines changed

1 file changed

+17
-17
lines changed

drivers/irqchip/irq-sifive-plic.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ struct plic_handler {
8585
struct plic_priv *priv;
8686
};
8787
static int plic_parent_irq __ro_after_init;
88-
static bool plic_cpuhp_setup_done __ro_after_init;
88+
static bool plic_global_setup_done __ro_after_init;
8989
static DEFINE_PER_CPU(struct plic_handler, plic_handlers);
9090

9191
static int plic_irq_set_type(struct irq_data *d, unsigned int type);
@@ -487,10 +487,8 @@ static int plic_probe(struct platform_device *pdev)
487487
unsigned long plic_quirks = 0;
488488
struct plic_handler *handler;
489489
u32 nr_irqs, parent_hwirq;
490-
struct irq_domain *domain;
491490
struct plic_priv *priv;
492491
irq_hw_number_t hwirq;
493-
bool cpuhp_setup;
494492

495493
if (is_of_node(dev->fwnode)) {
496494
const struct of_device_id *id;
@@ -549,14 +547,6 @@ static int plic_probe(struct platform_device *pdev)
549547
continue;
550548
}
551549

552-
/* Find parent domain and register chained handler */
553-
domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), DOMAIN_BUS_ANY);
554-
if (!plic_parent_irq && domain) {
555-
plic_parent_irq = irq_create_mapping(domain, RV_IRQ_EXT);
556-
if (plic_parent_irq)
557-
irq_set_chained_handler(plic_parent_irq, plic_handle_irq);
558-
}
559-
560550
/*
561551
* When running in M-mode we need to ignore the S-mode handler.
562552
* Here we assume it always comes later, but that might be a
@@ -597,25 +587,35 @@ static int plic_probe(struct platform_device *pdev)
597587
goto fail_cleanup_contexts;
598588

599589
/*
600-
* We can have multiple PLIC instances so setup cpuhp state
590+
* We can have multiple PLIC instances so setup global state
601591
* and register syscore operations only once after context
602592
* handlers of all online CPUs are initialized.
603593
*/
604-
if (!plic_cpuhp_setup_done) {
605-
cpuhp_setup = true;
594+
if (!plic_global_setup_done) {
595+
struct irq_domain *domain;
596+
bool global_setup = true;
597+
606598
for_each_online_cpu(cpu) {
607599
handler = per_cpu_ptr(&plic_handlers, cpu);
608600
if (!handler->present) {
609-
cpuhp_setup = false;
601+
global_setup = false;
610602
break;
611603
}
612604
}
613-
if (cpuhp_setup) {
605+
606+
if (global_setup) {
607+
/* Find parent domain and register chained handler */
608+
domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), DOMAIN_BUS_ANY);
609+
if (domain)
610+
plic_parent_irq = irq_create_mapping(domain, RV_IRQ_EXT);
611+
if (plic_parent_irq)
612+
irq_set_chained_handler(plic_parent_irq, plic_handle_irq);
613+
614614
cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
615615
"irqchip/sifive/plic:starting",
616616
plic_starting_cpu, plic_dying_cpu);
617617
register_syscore_ops(&plic_irq_syscore_ops);
618-
plic_cpuhp_setup_done = true;
618+
plic_global_setup_done = true;
619619
}
620620
}
621621

0 commit comments

Comments
 (0)