diff options
author | Daniel Thompson <daniel.thompson@linaro.org> | 2015-03-18 11:07:42 +0000 |
---|---|---|
committer | Daniel Thompson <daniel.thompson@linaro.org> | 2015-03-18 14:18:01 +0000 |
commit | a02fe5da35a5188596b3290806cfbc5941444844 (patch) | |
tree | c406c23df74c7be817c9a693dc58770994eb3ace /drivers/irqchip/irq-gic-v3.c | |
parent | d4796e458e69a0d52f8ea017cb424d0a09312130 (diff) | |
download | linux-dev/arm64_nmi-v4.0.tar.gz |
arm64: Add support for on-demand backtrace of other CPUsdev/arm64_nmi-v4.0
Currently arm64 has no implementation of arch_trigger_all_cpu_backtace.
The patch provides one for arm64 systems that are built with
CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS (i.e. those that have a pseudo-NMI).
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.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 3923b2a2150c..bdb134ed4519 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -34,6 +34,16 @@ #include "irq-gic-common.h" #include "irqchip.h" +#ifndef SMP_IPI_NMI_MASK +#define SMP_IPI_NMI_MASK 0 +#endif + +/* + * Copied from arm-gic.h (which we cannot include here because it conflicts + * with arm-gic-v3.h) + */ +#define GIC_DIST_PRI 0x400 + struct redist_region { void __iomem *redist_base; phys_addr_t phys_base; @@ -438,6 +448,7 @@ static int gic_dist_supports_lpis(void) static void gic_cpu_init(void) { void __iomem *rbase; + unsigned long nmimask, hwirq; /* Register ourselves with the rest of the world */ if (gic_populate_rdist()) @@ -455,6 +466,23 @@ static void gic_cpu_init(void) /* initialise system registers */ gic_cpu_sys_reg_init(); + + /* Boost the priority of any IPI in the mask */ + nmimask = SMP_IPI_NMI_MASK; + for_each_set_bit(hwirq, &nmimask, 16) { + unsigned int pri_reg = (hwirq / 4) * 4; + u32 pri_mask = BIT(6 + ((hwirq % 4) * 8)); + u32 pri_val = readl_relaxed(rbase + GIC_DIST_PRI + pri_reg); + u32 actual; + + pri_mask |= BIT(7 + ((hwirq % 4) * 8)); + pri_val &= ~pri_mask; /* priority boost */ + writel_relaxed(pri_val, rbase + GIC_DIST_PRI + pri_reg); + + actual = readl_relaxed(rbase + GIC_DIST_PRI + pri_reg); + } + gic_dist_wait_for_rwp(); + gic_redist_wait_for_rwp(); } #ifdef CONFIG_SMP |