lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Tue, 19 Aug 2014 17:46:00 +0100 From: Daniel Thompson <daniel.thompson@...aro.org> To: Russell King <linux@....linux.org.uk> Cc: Daniel Thompson <daniel.thompson@...aro.org>, linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org, kgdb-bugreport@...ts.sourceforge.net, patches@...aro.org, linaro-kernel@...ts.linaro.org, John Stultz <john.stultz@...aro.org>, Anton Vorontsov <anton.vorontsov@...aro.org>, Colin Cross <ccross@...roid.com>, kernel-team@...roid.com, Rob Herring <robherring2@...il.com>, Linus Walleij <linus.walleij@...aro.org>, Ben Dooks <ben.dooks@...ethink.co.uk>, Catalin Marinas <catalin.marinas@....com>, Dave Martin <Dave.Martin@....com>, Fabio Estevam <festevam@...il.com>, Frederic Weisbecker <fweisbec@...il.com>, Nicolas Pitre <nico@...aro.org>, Thomas Gleixner <tglx@...utronix.de>, Jason Cooper <jason@...edaemon.net> Subject: [PATCH v10 10/19] irqchip: gic: Group 0 workaround. An ARM system based on GICv1 that runs by default in secure mode and uses both group 0 and group 1 interrupts (in order to exploit FIQ) will suffer a problem where the IRQ handler occasionally spuriously acknowledges a group 0 (FIQ) interrupt. This can be prevented by ensuring the IRQ handler makes non-secure memory access to the GIC registers but this is complex because the non-secure bits cannot be apply to 4k pages (the bit is one level up in the page table and applies to 1MB at a time). This workaround uses an alternative approach that spots the spurious acknowledgment and regenerates the FIQ. This keeps the workaround exclusively within the GIC driver (although there is a runtime perforamnce penalty resulting from this approach). Reported-by: Harro Haan <hrhaan@...il.com> Signed-off-by: Daniel Thompson <daniel.thompson@...aro.org> Tested-by: Harro Haan <hrhaan@...il.com> Cc: Thomas Gleixner <tglx@...utronix.de> Cc: Jason Cooper <jason@...edaemon.net> --- drivers/irqchip/irq-gic.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 8834749..bda5a91 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -279,14 +279,59 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) #define gic_set_wake NULL #endif +#ifdef CONFIG_FIQ +/* This is a software emulation of the Aliased Interrupt Acknowledge Register + * (GIC_AIAR) found in GICv2+. + */ +static u32 gic_handle_spurious_group_0(struct gic_chip_data *gic, u32 irqstat) +{ + u32 irqnr = irqstat & GICC_IAR_INT_ID_MASK; + void __iomem *dist_base = gic_data_dist_base(gic); + u32 offset, mask; + + if (!gic_data_fiq_enable(gic) || irqnr >= 1021) + return irqstat; + + offset = irqnr / 32 * 4; + mask = 1 << (irqnr % 32); + if (readl_relaxed(dist_base + GIC_DIST_IGROUP + offset) & mask) + return irqstat; + + /* this interrupt must be taken as a FIQ so put it back into the + * pending state and end our own servicing of it. + */ + writel_relaxed(mask, dist_base + GIC_DIST_PENDING_SET + offset); + readl_relaxed(dist_base + GIC_DIST_PENDING_SET + offset); + writel_relaxed(irqstat, gic_data_cpu_base(gic) + GIC_CPU_EOI); + + return 1023; +} + +static u32 gic_ack_irq(struct gic_chip_data *gic) +{ + u32 irqstat; + + local_fiq_disable(); + irqstat = readl_relaxed(gic_data_cpu_base(gic) + GIC_CPU_INTACK); + irqstat = gic_handle_spurious_group_0(gic, irqstat); + local_fiq_enable(); + + return irqstat; +} +#else +static u32 gic_ack_irq(struct gic_chip_data *gic) +{ + return readl_relaxed(gic_data_cpu_base(gic) + GIC_CPU_INTACK); +} +#endif + static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { u32 irqstat, irqnr; struct gic_chip_data *gic = &gic_data[0]; - void __iomem *cpu_base = gic_data_cpu_base(gic); do { - irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); + irqstat = gic_ack_irq(gic); irqnr = irqstat & GICC_IAR_INT_ID_MASK; if (likely(irqnr > 15 && irqnr < 1021)) { @@ -295,7 +340,8 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) continue; } if (irqnr < 16) { - writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); + writel_relaxed(irqstat, + gic_data_cpu_base(gic) + GIC_CPU_EOI); #ifdef CONFIG_SMP handle_IPI(irqnr, regs); #endif -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists