linux/drivers/irqchip
Will Deacon e30364e00b irqchip/gic: Ensure ordering between read of INTACK and shared data
commit f86c4fbd93 upstream.

When an IPI is generated by a CPU, the pattern looks roughly like:

  <write shared data>
  smp_wmb();
  <write to GIC to signal SGI>

On the receiving CPU we rely on the fact that, once we've taken the
interrupt, then the freshly written shared data must be visible to us.
Put another way, the CPU isn't going to speculate taking an interrupt.

Unfortunately, this assumption turns out to be broken.

Consider that CPUx wants to send an IPI to CPUy, which will cause CPUy
to read some shared_data. Before CPUx has done anything, a random
peripheral raises an IRQ to the GIC and the IRQ line on CPUy is raised.
CPUy then takes the IRQ and starts executing the entry code, heading
towards gic_handle_irq. Furthermore, let's assume that a bunch of the
previous interrupts handled by CPUy were SGIs, so the branch predictor
kicks in and speculates that irqnr will be <16 and we're likely to
head into handle_IPI. The prefetcher then grabs a speculative copy of
shared_data which contains a stale value.

Meanwhile, CPUx gets round to updating shared_data and asking the GIC
to send an SGI to CPUy. Internally, the GIC decides that the SGI is
more important than the peripheral interrupt (which hasn't yet been
ACKed) but doesn't need to do anything to CPUy, because the IRQ line
is already raised.

CPUy then reads the ACK register on the GIC, sees the SGI value which
confirms the branch prediction and we end up with a stale shared_data
value.

This patch fixes the problem by adding an smp_rmb() to the IPI entry
code in gic_handle_irq. As it turns out, the combination of a control
dependency and an ISB instruction from the EOI in the GICv3 driver is
enough to provide the ordering we need, so we add a comment there
justifying the absence of an explicit smp_rmb().

Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
[bwh: Backported to 3.16: drop changes to irq-gic-v3]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
History 2016-08-22 22:37:57 +01:00
..
exynos-combiner.c irqchip: exynos-combiner: call handle_bad_irq directly 2014-02-14 07:27:40 +09:00
irq-armada-370-xp.c irqchip: armada-370-xp: Fix chained per-cpu interrupts 2015-03-23 15:16:41 +00:00
irq-bcm2835.c irqchip: Remove asmlinkage from static functions 2014-03-12 13:00:41 +01:00
irq-brcmstb-l2.c irqchip: brcmstb-l2: Level-2 interrupts are edge sensitive 2014-06-21 02:08:34 +00:00
irq-clps711x.c ARM: clps711x: Add CLPS711X irqchip driver 2014-02-28 17:27:30 +01:00
irq-crossbar.c irqchip: irq-crossbar: Not allocating enough memory 2014-04-28 21:43:24 +02:00
irq-dw-apb-ictl.c irqchip: add DesignWare APB ICTL interrupt controller 2013-12-13 16:29:40 +01:00
irq-gic.c irqchip/gic: Ensure ordering between read of INTACK and shared data 2016-08-22 22:37:57 +01:00
irq-imgpdc.c irq-imgpdc: add ImgTec PDC irqchip driver 2013-08-21 14:17:56 +01:00
irq-metag-ext.c irq-metag*: stop set_affinity vectoring to offline cpus 2014-02-25 22:35:06 +00:00
irq-metag.c irq-metag*: stop set_affinity vectoring to offline cpus 2014-02-25 22:35:06 +00:00
irq-mmp.c ARM: SoC: cleanups for 3.15 2014-04-05 13:51:19 -07:00
irq-moxart.c irqchip: Remove asmlinkage from static functions 2014-03-12 13:00:41 +01:00
irq-mxs.c irqchip: mxs: Fix function type for IRQCHIP_OF_DECLARE 2014-05-20 14:25:23 -05:00
irq-nvic.c irqchip: nvic: Fix wrong num_ct argument for irq_alloc_domain_generic_chips() 2013-07-05 11:39:24 +02:00
irq-orion.c irqchip: orion: Reverse irq handling priority 2014-05-08 14:42:09 +00:00
irq-renesas-intc-irqpin.c irqchip: renesas-intc-irqpin: Fix register bitfield shift calculation 2013-11-24 15:55:17 +09:00
irq-renesas-irqc.c irqchip: renesas-irqc: Enable mask on suspend 2014-01-22 21:48:55 +01:00
irq-s3c24xx.c irqchip: s3c24xx: Fix function type for IRQCHIP_OF_DECLARE 2014-05-20 14:25:23 -05:00
irq-sirfsoc.c irqchip: sirf: fix one minor checkpatch issue 2014-05-12 21:43:49 +08:00
irq-sun4i.c irqchip: sun4i: Simplify sun4i_irq_ack 2014-03-19 12:34:29 +01:00
irq-sunxi-nmi.c irqchip: sunxi-nmi: Fix off-by-one error in irq iterator 2015-06-30 17:15:21 +01:00
irq-tb10x.c irqchip: Add TB10x interrupt controller driver 2013-06-25 18:54:21 +02:00
irq-versatile-fpga.c irqchip/versatile-fpga: Fix PCI IRQ mapping on Versatile PB 2016-01-11 10:50:17 +00:00
irq-vic.c irqchip: vic: Properly chain the cascaded IRQs 2014-04-15 18:24:24 +02:00
irq-vt8500.c irqchip: Remove asmlinkage from static functions 2014-03-12 13:00:41 +01:00
irq-xtensa-mx.c irqchip: xtensa: Select only an online cpu 2014-03-04 17:37:55 +01:00
irq-xtensa-pic.c xtensa: move built-in PIC to drivers/irqchip 2014-01-14 10:19:56 -08:00
irq-zevio.c irqchip: Remove asmlinkage from static functions 2014-03-12 13:00:41 +01:00
irqchip.c irqchip: align irqchip OF match table section naming 2014-05-20 14:24:40 -05:00
irqchip.h of: consolidate linker section OF match table declarations 2014-05-20 14:25:24 -05:00
Kconfig irqchip: brcmstb-l2: Add Broadcom Set Top Box Level-2 interrupt controller 2014-05-27 14:43:06 +00:00
Makefile irqchip: brcmstb-l2: Add Broadcom Set Top Box Level-2 interrupt controller 2014-05-27 14:43:06 +00:00
spear-shirq.c irqchip: spear_shirq: Fix interrupt offset 2014-06-21 23:26:39 +00:00