diff options
author | Daniel Thompson <daniel.thompson@linaro.org> | 2017-01-27 16:07:13 +0000 |
---|---|---|
committer | Daniel Thompson <daniel.thompson@linaro.org> | 2017-03-30 19:29:03 +0100 |
commit | 9d9c6c34f93859d01b6201bf69301a69a0663c44 (patch) | |
tree | 4dab97f3eb63db3a93d1753e51568bcabc9adb0f | |
parent | 0ab44db1752bb96ae49726a386ead41b3298c5e9 (diff) |
WIP: Migrating PMR interrupt locking away from kernel_entrydev/arm64_nmi-v4.11
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
-rw-r--r-- | arch/arm64/kernel/entry.S | 14 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 27 | ||||
-rw-r--r-- | kernel/rcu/tree.c | 1 |
3 files changed, 39 insertions, 3 deletions
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index c71405d3c814..e22b7a04dc1a 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -125,8 +125,6 @@ alternative_endif lsl x20, x20, #PSR_G_PMR_G_SHIFT // Shift to a PSTATE RES0 bit eor x20, x20, #PSR_G_BIT // Invert bit orr x23, x20, x23 // Store PMR within PSTATE - mov x20, #ICC_PMR_EL1_MASKED - msr_s ICC_PMR_EL1, x20 // Mask normal interrupts at PMR 1: #endif @@ -371,6 +369,8 @@ tsk .req x28 // current thread_info * Interrupt handling. */ .macro irq_handler + mov x20, #ICC_PMR_EL1_MASKED + msr_s ICC_PMR_EL1, x20 // Mask normal interrupts at PMR ldr_l x1, handle_arch_irq mov x0, sp irq_stack_entry @@ -420,6 +420,8 @@ END(vectors) */ .macro inv_entry, el, reason, regsize = 64 kernel_entry \el, \regsize + mov x20, #ICC_PMR_EL1_MASKED + msr_s ICC_PMR_EL1, x20 // Mask normal interrupts at PMR mov x0, sp mov x1, #\reason mrs x2, esr_el1 @@ -474,6 +476,8 @@ ENDPROC(el1_error_invalid) .align 6 el1_sync: kernel_entry 1 + mov x20, #ICC_PMR_EL1_MASKED + msr_s ICC_PMR_EL1, x20 // Mask normal interrupts at PMR mrs x1, esr_el1 // read the syndrome register lsr x24, x1, #ESR_ELx_EC_SHIFT // exception class cmp x24, #ESR_ELx_EC_DABT_CUR // data abort in EL1 @@ -509,11 +513,13 @@ alternative_if_not ARM64_HAS_SYSREG_GIC_CPUIF tbnz x23, #7, 1f // PSR_I_BIT msr daifclr, #2 nop + nop 1: alternative_else tbnz x23, #PSR_G_SHIFT, 1f // PSR_G_BIT mov x2, #ICC_PMR_EL1_UNMASKED msr_s ICC_PMR_EL1, x2 + dsb sy 1: alternative_endif #else @@ -606,6 +612,8 @@ el1_preempt: .align 6 el0_sync: kernel_entry 0 + mov x20, #ICC_PMR_EL1_MASKED + msr_s ICC_PMR_EL1, x20 // Mask normal interrupts at PMR mrs x25, esr_el1 // read the syndrome register lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class cmp x24, #ESR_ELx_EC_SVC64 // SVC in 64-bit state @@ -634,6 +642,8 @@ el0_sync: .align 6 el0_sync_compat: kernel_entry 0, 32 + mov x20, #ICC_PMR_EL1_MASKED + msr_s ICC_PMR_EL1, x20 // Mask normal interrupts at PMR mrs x25, esr_el1 // read the syndrome register lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class cmp x24, #ESR_ELx_EC_SVC32 // SVC in 32-bit state diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 39232014d200..9ca08aa9e3ba 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -343,7 +343,7 @@ static u64 gic_mpidr_to_affinity(unsigned long mpidr) } #ifdef CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS -static bool gic_handle_nmi(struct pt_regs *regs) +static bool __maybe_unused gic_handle_nmi(struct pt_regs *regs) { u64 irqnr; struct pt_regs *old_regs; @@ -393,12 +393,37 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs { u32 irqnr; +#if 1 + local_irq_disable(); + if (gic_handle_nmi(regs)) return; +#endif do { irqnr = gic_read_iar(); +#if 0 + printk_ratelimited(KERN_INFO "irqnr %d\n", irqnr); + + if (unlikely(SMP_IPI_NMI_MASK & (1 << irqnr))) { + struct pt_regs *old_regs; + + old_regs = set_irq_regs(regs); + nmi_enter(); + + gic_write_eoir(irqnr); + if (static_key_true(&supports_deactivate)) + gic_write_dir(irqnr); + + nmi_cpu_backtrace(regs); + + nmi_exit(); + set_irq_regs(old_regs); + continue; + } +#endif + if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) { int err; diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 50fee7689e71..6f1ce868969f 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -1474,6 +1474,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) } print_cpu_stall_info_end(); + trigger_all_cpu_backtrace(); for_each_possible_cpu(cpu) totqlen += per_cpu_ptr(rsp->rda, cpu)->qlen; pr_cont("(detected by %d, t=%ld jiffies, g=%ld, c=%ld, q=%lu)\n", |