summaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2016-04-21 06:31:54 -0400
committerThomas Gleixner <tglx@linutronix.de>2016-04-21 15:04:29 -0400
commit91951f980e521d8f7e92283735b99fb9f4b05d93 (patch)
treedd870503ba69eec8a7eef85189e4f235d52222d4 /drivers/irqchip
parent4589f450fb285ab85f7513b6649e51ec2a820653 (diff)
irqchip/mips-gic: Don't overrun pcpu_masks array
Commit 2a0787051182 ("irqchip/mips-gic: Use gic_vpes instead of NR_CPUS") & commit 78930f09b940 ("irqchip/mips-gic: Clear percpu_masks correctly when mapping") both introduce code which accesses gic_vpes entries in the pcpu_masks array. However, this array has length NR_CPUS. If NR_CPUS is less than gic_vpes (ie. the kernel supports use of less CPUs than are present in the system) then we overrun the array, clobber some other data & generally die pretty promptly. Most notably this affects uniprocessor kernels running on any multicore or multithreaded Malta with a GIC (ie. the vast majority of real Malta boards). Fix this by only accessing up to min(gic_vpes, NR_CPUS) entries in the pcpu_masks array, preventing the array overrun. Fixes: 2a0787051182 ("irqchip/mips-gic: Use gic_vpes instead of NR_CPUS") Fixes: 78930f09b940 ("irqchip/mips-gic: Clear percpu_masks correctly when mapping") Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Cc: Jason Cooper <jason@lakedaemon.net> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Ralf Baechle <ralf@linux-mips.org> Link: http://lkml.kernel.org/r/1461234714-9975-1-git-send-email-paul.burton@imgtec.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-mips-gic.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 94a30da0cfac..4dffccf532a2 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -467,7 +467,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
467 gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first(&tmp))); 467 gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first(&tmp)));
468 468
469 /* Update the pcpu_masks */ 469 /* Update the pcpu_masks */
470 for (i = 0; i < gic_vpes; i++) 470 for (i = 0; i < min(gic_vpes, NR_CPUS); i++)
471 clear_bit(irq, pcpu_masks[i].pcpu_mask); 471 clear_bit(irq, pcpu_masks[i].pcpu_mask);
472 set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask); 472 set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
473 473
@@ -707,7 +707,7 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
707 spin_lock_irqsave(&gic_lock, flags); 707 spin_lock_irqsave(&gic_lock, flags);
708 gic_map_to_pin(intr, gic_cpu_pin); 708 gic_map_to_pin(intr, gic_cpu_pin);
709 gic_map_to_vpe(intr, vpe); 709 gic_map_to_vpe(intr, vpe);
710 for (i = 0; i < gic_vpes; i++) 710 for (i = 0; i < min(gic_vpes, NR_CPUS); i++)
711 clear_bit(intr, pcpu_masks[i].pcpu_mask); 711 clear_bit(intr, pcpu_masks[i].pcpu_mask);
712 set_bit(intr, pcpu_masks[vpe].pcpu_mask); 712 set_bit(intr, pcpu_masks[vpe].pcpu_mask);
713 spin_unlock_irqrestore(&gic_lock, flags); 713 spin_unlock_irqrestore(&gic_lock, flags);