aboutsummaryrefslogtreecommitdiff
path: root/drivers/irqchip/irq-gic-v3.c
diff options
context:
space:
mode:
authorDaniel Thompson <daniel.thompson@linaro.org>2015-03-17 16:33:22 +0000
committerDaniel Thompson <daniel.thompson@linaro.org>2015-03-18 14:17:59 +0000
commiteabea3fe7b903a843e0486a2adfff041bd9f38cf (patch)
treea701ef9fb7c49f062ff3097c5ffc8834a1411602 /drivers/irqchip/irq-gic-v3.c
parentd9e2a965e0abfe9a4a91f595a368aaa1698445b2 (diff)
downloadlinux-eabea3fe7b903a843e0486a2adfff041bd9f38cf.tar.gz
irqchip: gic-v3: Reset BPR during initialization
Currently, when running on FVP, CPU 0 boots up with its BPR changed from the reset value. This renders it impossible to (preemptively) prioritize interrupts on CPU 0. This is harmless on normal systems but prevents preemption by NMIs on systems with CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS enabled. Many thanks to Andrew Thoelke for suggesting the BPR as having the potential to harm preemption. Suggested-by: Andrew Thoelke <andrew.thoelke@arm.com> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Diffstat (limited to 'drivers/irqchip/irq-gic-v3.c')
-rw-r--r--drivers/irqchip/irq-gic-v3.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index fd8850def1b8..32533650494c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -120,6 +120,11 @@ static void __maybe_unused gic_write_pmr(u64 val)
asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" (val));
}
+static void __maybe_unused gic_write_bpr1(u64 val)
+{
+ asm volatile("msr_s " __stringify(ICC_BPR1_EL1) ", %0" : : "r" (val));
+}
+
static void __maybe_unused gic_write_ctlr(u64 val)
{
asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" (val));
@@ -383,6 +388,14 @@ static void gic_cpu_sys_reg_init(void)
/* Set priority mask register */
gic_write_pmr(DEFAULT_PMR_VALUE);
+ /*
+ * On FVP, CPU 0 arrives in the kernel with its BPR changed from the
+ * reset value (and the value is large enough to prevent pre-emptive
+ * interrupts from working at all). Writing a zero to BPR restores the
+ * reset value.
+ */
+ gic_write_bpr1(0);
+
/* EOI deactivates interrupt too (mode 0) */
gic_write_ctlr(ICC_CTLR_EL1_EOImode_drop_dir);