summaryrefslogtreecommitdiff
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2018-03-09 14:53:19 +0000
committerMarc Zyngier <marc.zyngier@arm.com>2018-03-14 11:11:29 +0000
commitd6062a6d62c643a06c393745d032da3e6441d4bd (patch)
treeecc4745282e90a4eab388ab137307ff22bc4fe94 /drivers/irqchip
parentc5e1035c9687025373b7c48a08efb37f5329916b (diff)
downloadlinux-d6062a6d62c643a06c393745d032da3e6441d4bd.tar.gz
linux-d6062a6d62c643a06c393745d032da3e6441d4bd.tar.xz
irqchip/gic-v3: Reset APgRn registers at boot time
Booting a crash kernel while in an interrupt handler is likely to leave the Active Priority Registers with some state that is not relevant to the new kernel, and is likely to lead to erratic behaviours such as interrupts not firing as their priority is already active. As a sanity measure, wipe the APRs clean on startup. We make sure to wipe both group 0 and 1 registers in order to avoid any surprise. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-gic-v3.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index d99cc07903ec..0ea02504115d 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -532,6 +532,7 @@ static void gic_cpu_sys_reg_init(void)
int i, cpu = smp_processor_id();
u64 mpidr = cpu_logical_map(cpu);
u64 need_rss = MPIDR_RS(mpidr);
+ u32 val;
/*
* Need to check that the SRE bit has actually been set. If
@@ -562,6 +563,28 @@ static void gic_cpu_sys_reg_init(void)
gic_write_ctlr(ICC_CTLR_EL1_EOImode_drop_dir);
}
+ val = gic_read_ctlr();
+ val &= ICC_CTLR_EL1_PRI_BITS_MASK;
+ val >>= ICC_CTLR_EL1_PRI_BITS_SHIFT;
+
+ switch(val + 1) {
+ case 8:
+ case 7:
+ write_gicreg(0, ICC_AP0R3_EL1);
+ write_gicreg(0, ICC_AP1R3_EL1);
+ write_gicreg(0, ICC_AP0R2_EL1);
+ write_gicreg(0, ICC_AP1R2_EL1);
+ case 6:
+ write_gicreg(0, ICC_AP0R1_EL1);
+ write_gicreg(0, ICC_AP1R1_EL1);
+ case 5:
+ case 4:
+ write_gicreg(0, ICC_AP0R0_EL1);
+ write_gicreg(0, ICC_AP1R0_EL1);
+ }
+
+ isb();
+
/* ... and let's hit the road... */
gic_write_grpen1(1);