Hi Alexandru, On 11/25/20 4:51 PM, Alexandru Elisei wrote: > GICv2 generates IPIs with a MMIO write to the GICD_SGIR register. A common > pattern for IPI usage is for the IPI receiver to read data written to > memory by the sender. The armv7 and armv8 architectures implement a > weakly-ordered memory model, which means that barriers are required to make > sure that the expected values are observed. > > It turns out that because the receiver CPU must observe the write to memory > that generated the IPI when reading the GICC_IAR MMIO register, we only > need to ensure ordering of memory accesses, and not completion. Use a > smp_wmb (DMB ISHST) barrier before sending the IPI. > > This also matches what the Linux GICv2 irqchip driver does (more details > in commit 8adbf57fc429 ("irqchip: gic: use dmb ishst instead of dsb when > raising a softirq")). > > Signed-off-by: Alexandru Elisei <alexandru.elisei@xxxxxxx> Reviewed-by: Eric Auger <eric.auger@xxxxxxxxxx> Eric > --- > lib/arm/gic-v2.c | 4 ++++ > arm/gic.c | 2 ++ > 2 files changed, 6 insertions(+) > > diff --git a/lib/arm/gic-v2.c b/lib/arm/gic-v2.c > index dc6a97c600ec..da244c82de34 100644 > --- a/lib/arm/gic-v2.c > +++ b/lib/arm/gic-v2.c > @@ -45,6 +45,8 @@ void gicv2_ipi_send_single(int irq, int cpu) > { > assert(cpu < 8); > assert(irq < 16); > + > + smp_wmb(); > writel(1 << (cpu + 16) | irq, gicv2_dist_base() + GICD_SGIR); > } > > @@ -53,5 +55,7 @@ void gicv2_ipi_send_mask(int irq, const cpumask_t *dest) > u8 tlist = (u8)cpumask_bits(dest)[0]; > > assert(irq < 16); > + > + smp_wmb(); > writel(tlist << 16 | irq, gicv2_dist_base() + GICD_SGIR); > } > diff --git a/arm/gic.c b/arm/gic.c > index 512c83636a2e..401ffafe4299 100644 > --- a/arm/gic.c > +++ b/arm/gic.c > @@ -260,11 +260,13 @@ static void check_lpi_hits(int *expected, const char *msg) > > static void gicv2_ipi_send_self(void) > { > + smp_wmb(); > writel(2 << 24 | IPI_IRQ, gicv2_dist_base() + GICD_SGIR); > } > > static void gicv2_ipi_send_broadcast(void) > { > + smp_wmb(); > writel(1 << 24 | IPI_IRQ, gicv2_dist_base() + GICD_SGIR); > } > >