genirq: Robustify handle_percpu_devid_irq()
The percpu_devid handler is not robust against spurious interrupts. If a spurious interrupt happens and no action is installed then the handler crashes with a NULL pointer dereference. Add a sanity check for this and log the wreckage once in dmesg. Reported-by: Majun <majun258@huawei.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: guohanjun@huawei.com Cc: dingtianhong@huawei.com Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1609021436160.5647@nanos
This commit is contained in:
parent
eb0dc47ab6
commit
fc590c22f9
|
@ -756,7 +756,6 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
|
|||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct irqaction *action = desc->action;
|
||||
void *dev_id = raw_cpu_ptr(action->percpu_dev_id);
|
||||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
irqreturn_t res;
|
||||
|
||||
|
@ -765,9 +764,20 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
|
|||
if (chip->irq_ack)
|
||||
chip->irq_ack(&desc->irq_data);
|
||||
|
||||
trace_irq_handler_entry(irq, action);
|
||||
res = action->handler(irq, dev_id);
|
||||
trace_irq_handler_exit(irq, action, res);
|
||||
if (likely(action)) {
|
||||
trace_irq_handler_entry(irq, action);
|
||||
res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));
|
||||
trace_irq_handler_exit(irq, action, res);
|
||||
} else {
|
||||
unsigned int cpu = smp_processor_id();
|
||||
bool enabled = cpumask_test_cpu(cpu, desc->percpu_enabled);
|
||||
|
||||
if (enabled)
|
||||
irq_percpu_disable(desc, cpu);
|
||||
|
||||
pr_err_once("Spurious%s percpu IRQ%u on CPU%u\n",
|
||||
enabled ? " and unmasked" : "", irq, cpu);
|
||||
}
|
||||
|
||||
if (chip->irq_eoi)
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
|
|
Loading…
Reference in New Issue