* Re: [RESEND PATCH 4.0-rc5 v19 3/6] irqchip: gic: Introduce plumbing for IPI FIQ [not found] <088701d071d3$ec642a90$c52c7fb0$@alibaba-inc.com> @ 2015-04-08 8:19 ` Hillf Danton 0 siblings, 0 replies; 6+ messages in thread From: Hillf Danton @ 2015-04-08 8:19 UTC (permalink / raw) To: 'Daniel Thompson' Cc: linux-kernel, linux-arm-kernel, 'Russell King' > +/* > + * Fully acknowledge (both ack and eoi) any outstanding FIQ-based IPI, > + * otherwise do nothing. > + */ > +void gic_handle_fiq_ipi(void) > +{ > + struct gic_chip_data *gic = &gic_data[0]; > + void __iomem *cpu_base = gic_data_cpu_base(gic); > + unsigned long irqstat, irqnr; > + > + if (WARN_ON(!in_nmi())) > + return; > + > + while ((1u << readl_relaxed(cpu_base + GIC_CPU_HIGHPRI)) & > + SMP_IPI_FIQ_MASK) { > + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); > + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); > + > + irqnr = irqstat & GICC_IAR_INT_ID_MASK; > + WARN_RATELIMIT(irqnr > 16, > + "Unexpected irqnr %lu (bad prioritization?)\n", Help more if s/Unexpected/Unexpected FIQ/ ? > + irqnr); > + } > +} > + ^ permalink raw reply [flat|nested] 6+ messages in thread
* [RESEND PATCH 4.0-rc5 v19 3/6] irqchip: gic: Introduce plumbing for IPI FIQ @ 2015-04-08 8:19 ` Hillf Danton 0 siblings, 0 replies; 6+ messages in thread From: Hillf Danton @ 2015-04-08 8:19 UTC (permalink / raw) To: linux-arm-kernel > +/* > + * Fully acknowledge (both ack and eoi) any outstanding FIQ-based IPI, > + * otherwise do nothing. > + */ > +void gic_handle_fiq_ipi(void) > +{ > + struct gic_chip_data *gic = &gic_data[0]; > + void __iomem *cpu_base = gic_data_cpu_base(gic); > + unsigned long irqstat, irqnr; > + > + if (WARN_ON(!in_nmi())) > + return; > + > + while ((1u << readl_relaxed(cpu_base + GIC_CPU_HIGHPRI)) & > + SMP_IPI_FIQ_MASK) { > + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); > + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); > + > + irqnr = irqstat & GICC_IAR_INT_ID_MASK; > + WARN_RATELIMIT(irqnr > 16, > + "Unexpected irqnr %lu (bad prioritization?)\n", Help more if s/Unexpected/Unexpected FIQ/ ? > + irqnr); > + } > +} > + ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RESEND PATCH 4.0-rc5 v19 3/6] irqchip: gic: Introduce plumbing for IPI FIQ 2015-04-08 8:19 ` Hillf Danton @ 2015-04-08 10:23 ` Daniel Thompson -1 siblings, 0 replies; 6+ messages in thread From: Daniel Thompson @ 2015-04-08 10:23 UTC (permalink / raw) To: Hillf Danton; +Cc: linux-kernel, linux-arm-kernel, 'Russell King' On 08/04/15 09:19, Hillf Danton wrote: >> +/* >> + * Fully acknowledge (both ack and eoi) any outstanding FIQ-based IPI, >> + * otherwise do nothing. >> + */ >> +void gic_handle_fiq_ipi(void) >> +{ >> + struct gic_chip_data *gic = &gic_data[0]; >> + void __iomem *cpu_base = gic_data_cpu_base(gic); >> + unsigned long irqstat, irqnr; >> + >> + if (WARN_ON(!in_nmi())) >> + return; >> + >> + while ((1u << readl_relaxed(cpu_base + GIC_CPU_HIGHPRI)) & >> + SMP_IPI_FIQ_MASK) { >> + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); >> + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); >> + >> + irqnr = irqstat & GICC_IAR_INT_ID_MASK; >> + WARN_RATELIMIT(irqnr > 16, >> + "Unexpected irqnr %lu (bad prioritization?)\n", > > Help more if s/Unexpected/Unexpected FIQ/ ? The GIC logic to prioritize interrupts is independent of the logic to route interrupt sources to IRQ or FIQ. Thus if this code acknowledges an unexpected interrupt source then we really don't know whether it is an IRQ or a FIQ so we cannot accurately describe this is an unexpected FIQ. If there is bad prioritization then we cannot predict what type of interrupt INTACK will give use. ^ permalink raw reply [flat|nested] 6+ messages in thread
* [RESEND PATCH 4.0-rc5 v19 3/6] irqchip: gic: Introduce plumbing for IPI FIQ @ 2015-04-08 10:23 ` Daniel Thompson 0 siblings, 0 replies; 6+ messages in thread From: Daniel Thompson @ 2015-04-08 10:23 UTC (permalink / raw) To: linux-arm-kernel On 08/04/15 09:19, Hillf Danton wrote: >> +/* >> + * Fully acknowledge (both ack and eoi) any outstanding FIQ-based IPI, >> + * otherwise do nothing. >> + */ >> +void gic_handle_fiq_ipi(void) >> +{ >> + struct gic_chip_data *gic = &gic_data[0]; >> + void __iomem *cpu_base = gic_data_cpu_base(gic); >> + unsigned long irqstat, irqnr; >> + >> + if (WARN_ON(!in_nmi())) >> + return; >> + >> + while ((1u << readl_relaxed(cpu_base + GIC_CPU_HIGHPRI)) & >> + SMP_IPI_FIQ_MASK) { >> + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); >> + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); >> + >> + irqnr = irqstat & GICC_IAR_INT_ID_MASK; >> + WARN_RATELIMIT(irqnr > 16, >> + "Unexpected irqnr %lu (bad prioritization?)\n", > > Help more if s/Unexpected/Unexpected FIQ/ ? The GIC logic to prioritize interrupts is independent of the logic to route interrupt sources to IRQ or FIQ. Thus if this code acknowledges an unexpected interrupt source then we really don't know whether it is an IRQ or a FIQ so we cannot accurately describe this is an unexpected FIQ. If there is bad prioritization then we cannot predict what type of interrupt INTACK will give use. ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 4.0-rc5 v19 0/6] irq/arm: Implement arch_trigger_all_cpu_backtrace @ 2015-03-24 16:53 Daniel Thompson 2015-04-07 15:37 ` [RESEND PATCH " Daniel Thompson 0 siblings, 1 reply; 6+ messages in thread From: Daniel Thompson @ 2015-03-24 16:53 UTC (permalink / raw) To: Thomas Gleixner, Jason Cooper Cc: Daniel Thompson, Russell King, Will Deacon, Catalin Marinas, Marc Zyngier, Stephen Boyd, John Stultz, Steven Rostedt, linux-kernel, linux-arm-kernel, patches, linaro-kernel, Sumit Semwal, Dirk Behme, Daniel Drake, Dmitry Pervushin, Tim Sander Jason/Thomas: This would be a resend except Steven Rostedt noticed a redundant memory barrier I had copied from the x86 code. The redundant barrier is now removed and there are no other changes since the code was posted a fortnight ago. Any chance of taking the first five of these patches via the irqchip route? The x86 patch has an ack from Ingo, printk has no explicit maintainer and I've done plenty of bisectability tests on the patchset so leaving the last patch for the next dev. cycle should be no trouble. This patchset modifies the GIC driver to allow it, on supported platforms, to route IPI interrupts to FIQ. It then uses this feature to implement arch_trigger_all_cpu_backtrace for arm. In order to neatly bring in the changes for the arm we also rearrange some of the existing x86 NMI code to make it architecture neutral. The patchset http://thread.gmane.org/gmane.linux.kernel/1897765 , which makes sched_clock() NMI/FIQ-safe, should be treated as a prerequisite for the sixth and final patch in the series (which enables the feature on ARM). Although sched_clock() is not called directly by any of the code that runs from a FIQ handler it is possible for sched_clock() to be called indirectly when the function tracer is enabled. The patches have been runtime tested on two systems capable of supporting FIQ (Freescale i.MX6 and STiH416) and two that do not (vexpress-a9 and Qualcomm Snapdragon 600), the changes to the x86 logic were tested on qemu and all patches have been compile tested on x86, arm and arm64. Note: On platforms not capable of supporting FIQ, the IPI to generate a backtrace will fall back to using IRQ for propagation instead. The backtrace logic contains a timeout to we will not permanently wedge the requesting CPU if other CPUs are not responsive. v19: * Remove redundant memory barrier inherited from the x86 code (Steven Rostedt). v18: * Move printk_nmi_ functions out of printk.c and into their own file, nmi_callback.c (Joe Perches/Steven Rostedt). * Rename printk_nmi_ functions so their name matches their new home (Joe Perches) v17: * Rename bl_migration_lock/unlock to gic_migration_lock/unlock (Nicolas Pitre). v16: * Significant clean up of the printk patches (Thomas Gleixner). Replacing macros with real functions, CONFIG_ARCH_WANT_NMI_PRINTK -> CONFIG_PRINTK_NMI, prefixing global functions with printk_nmi, removing pointless exports, removing cpu_mask from the interfaces, removal of just-in-time initialization of trace buffers, prevented call sites having to save state, rolled up variable declarations into single lines. * Dropped the sched_clock() patches from *this* patchset and managed them separately (http://thread.gmane.org/gmane.linux.kernel/1879261 ). The cross-dependancies between the patches are minimal; the backtrace code only calls sched_clock() if we are ftracing and backtracing is normally only triggered to report information about about a broken system (although users can type SysRq-l for amusement, most use it to find out why the system it dead). * Squashed together the final two patches. Essentially these duplicated the x86 code and slavishly avoided changing it before, in the next patch, fixing it to work better on ARM. It seems better that the code just works first time! v15: * Added a patch to make sched_clock safe to call from NMI (Stephen Boyd). Note that sched_clock() is not called by the NMI handlers that have been added for the arm but it could be called if tools such as ftrace are deployed. * Fixed some warnings picked up during bisectability testing. v14: * Moved a nmi_vprintk() and friends from arch/x86/kernel/apic/hw_nmi.c to printk.c (Steven Rostedt) v13: * Updated the code to print the backtrace to replicate Steven Rostedt's x86 work to make SysRq-l safe. This is pretty much a total rewrite of patches 4 and 5. v12: * Squash first two patches into a single one and re-describe (Thomas Gleixner). * Improve description of "irqchip: gic: Make gic_raise_softirq FIQ-safe" (Thomas Gleixner). v11: * Optimized gic_raise_softirq() by replacing a register read with a memory read (Jason Cooper). v10: * Add a further patch to optimize away some of the locking on systems where CONFIG_BL_SWITCHER is not set (Marc Zyngier). Compiles OK with exynos_defconfig (which is the only defconfig to set this option). * Whitespace fixes in patch 4. That patch previously used spaces for alignment of new constants but the rest of the file used tabs. v9: * Improved documentation and structure of initial patch (now initial two patches) to make gic_raise_softirq() safe to call from FIQ (Thomas Gleixner). * Avoid masking interrupts during gic_raise_softirq(). The use of the read lock makes this redundant (because we can safely re-enter the function). v8: * Fixed build on arm64 causes by a spurious include file in irq-gic.c. v7-2 (accidentally released twice with same number): * Fixed boot regression on vexpress-a9 (reported by Russell King). * Rebased on v3.18-rc3; removed one patch from set that is already included in mainline. * Dropped arm64/fiq.h patch from the set (still useful but not related to issuing backtraces). v7: * Re-arranged code within the patch series to fix a regression introduced midway through the series and corrected by a later patch (testing by Olof's autobuilder). Tested offending patch in isolation using defconfig identified by the autobuilder. v6: * Renamed svc_entry's call_trace argument to just trace (example code from Russell King). * Fixed mismatched ENDPROC() in __fiq_abt (example code from Russell King). * Modified usr_entry to optional avoid calling into the trace code and used this in FIQ entry from usr path. Modified corresponding exit code to avoid calling into trace code and the scheduler (example code from Russell King). * Ensured the default FIQ register state is restored when the default FIQ handler is reinstalled (example code from Russell King). * Renamed no_fiq_insn to dfl_fiq_insn to reflect the effect of adopting a default FIQ handler. * Re-instated fiq_safe_migration_lock and associated logic in gic_raise_softirq(). gic_raise_softirq() is called by wake_up_klogd() in the console unlock logic. v5: * Rebased on 3.17-rc4. * Removed a spurious line from the final "glue it together" patch that broke the build. v4: * Replaced push/pop with stmfd/ldmfd respectively (review of Nicolas Pitre). * Really fix bad pt_regs pointer generation in __fiq_abt. * Remove fiq_safe_migration_lock and associated logic in gic_raise_softirq() (review of Russell King) * Restructured to introduce the default FIQ handler first, before the new features (review of Russell King). v3: * Removed redundant header guards from arch/arm64/include/asm/fiq.h (review of Catalin Marinas). * Moved svc_exit_via_fiq macro to entry-header.S (review of Nicolas Pitre). v2: * Restructured to sit nicely on a similar FYI patchset from Russell King. It now effectively replaces the work in progress final patch with something much more complete. * Implemented (and tested) a Thumb-2 implementation of svc_exit_via_fiq (review of Nicolas Pitre) * Dropped the GIC group 0 workaround patch. The issue of FIQ interrupts being acknowledged by the IRQ handler does still exist but should be harmless because the IRQ handler will still wind up calling ipi_cpu_backtrace(). * Removed any dependency on CONFIG_FIQ; all cpu backtrace effectively becomes a platform feature (although the use of non-maskable interrupts to implement it is best effort rather than guaranteed). * Better comments highlighting usage of RAZ/WI registers (and parts of registers) in the GIC code. Changes *before* v1: * This patchset is a hugely cut-down successor to "[PATCH v11 00/19] arm: KGDB NMI/FIQ support". Thanks to Thomas Gleixner for suggesting the new structure. For historic details see: https://lkml.org/lkml/2014/9/2/227 * Fix bug in __fiq_abt (no longer passes a bad struct pt_regs value). In fixing this we also remove the useless indirection previously found in the fiq_handler macro. * Make default fiq handler "always on" by migrating from fiq.c to traps.c and replace do_unexp_fiq with the new handler (review of Russell King). * Add arm64 version of fiq.h (review of Russell King) * Removed conditional branching and code from irq-gic.c, this is replaced by much simpler code that relies on the GIC specification's heavy use of read-as-zero/write-ignored (review of Russell King) Daniel Thompson (6): irqchip: gic: Optimize locking in gic_raise_softirq irqchip: gic: Make gic_raise_softirq FIQ-safe irqchip: gic: Introduce plumbing for IPI FIQ printk: Simple implementation for NMI backtracing x86/nmi: Use common printk functions ARM: Add support for on-demand backtrace of other CPUs arch/arm/Kconfig | 1 + arch/arm/include/asm/hardirq.h | 2 +- arch/arm/include/asm/irq.h | 5 + arch/arm/include/asm/smp.h | 3 + arch/arm/kernel/smp.c | 81 ++++++++++++++++ arch/arm/kernel/traps.c | 8 +- arch/x86/Kconfig | 1 + arch/x86/kernel/apic/hw_nmi.c | 101 ++------------------ drivers/irqchip/irq-gic.c | 203 +++++++++++++++++++++++++++++++++++++--- include/linux/irqchip/arm-gic.h | 8 ++ include/linux/printk.h | 20 ++++ init/Kconfig | 3 + kernel/printk/Makefile | 1 + kernel/printk/nmi_backtrace.c | 147 +++++++++++++++++++++++++++++ 14 files changed, 473 insertions(+), 111 deletions(-) create mode 100644 kernel/printk/nmi_backtrace.c -- 2.1.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [RESEND PATCH 4.0-rc5 v19 0/6] irq/arm: Implement arch_trigger_all_cpu_backtrace 2015-03-24 16:53 [PATCH 4.0-rc5 v19 0/6] irq/arm: Implement arch_trigger_all_cpu_backtrace Daniel Thompson @ 2015-04-07 15:37 ` Daniel Thompson 2015-04-07 15:38 ` Daniel Thompson 0 siblings, 1 reply; 6+ messages in thread From: Daniel Thompson @ 2015-04-07 15:37 UTC (permalink / raw) To: Thomas Gleixner, Jason Cooper Cc: Daniel Thompson, Russell King, Will Deacon, Catalin Marinas, Marc Zyngier, Stephen Boyd, John Stultz, Steven Rostedt, linux-kernel, linux-arm-kernel, patches, linaro-kernel, Sumit Semwal, Dirk Behme, Daniel Drake, Dmitry Pervushin, Tim Sander Jason/Thomas: Any chance of taking the first five of these patches via the irqchip route? The x86 patch has an ack from Ingo, printk has no explicit maintainer and I've done plenty of bisectability tests on the patchset so leaving the last patch for the next dev. cycle should be no trouble. This patchset modifies the GIC driver to allow it, on supported platforms, to route IPI interrupts to FIQ. It then uses this feature to implement arch_trigger_all_cpu_backtrace for arm. In order to neatly bring in the changes for the arm we also rearrange some of the existing x86 NMI code to make it architecture neutral. The patchset http://thread.gmane.org/gmane.linux.kernel/1897765 , which makes sched_clock() NMI/FIQ-safe, should be treated as a prerequisite for the sixth and final patch in the series (which enables the feature on ARM). Although sched_clock() is not called directly by any of the code that runs from a FIQ handler it is possible for sched_clock() to be called indirectly when the function tracer is enabled. The patches have been runtime tested on two systems capable of supporting FIQ (Freescale i.MX6 and STiH416) and two that do not (vexpress-a9 and Qualcomm Snapdragon 600), the changes to the x86 logic were tested on qemu and all patches have been compile tested on x86, arm and arm64. Note: On platforms not capable of supporting FIQ, the IPI to generate a backtrace will fall back to using IRQ for propagation instead. The backtrace logic contains a timeout to we will not permanently wedge the requesting CPU if other CPUs are not responsive. v19: * Remove redundant memory barrier inherited from the x86 code (Steven Rostedt). v18: * Move printk_nmi_ functions out of printk.c and into their own file, nmi_callback.c (Joe Perches/Steven Rostedt). * Rename printk_nmi_ functions so their name matches their new home (Joe Perches) v17: * Rename bl_migration_lock/unlock to gic_migration_lock/unlock (Nicolas Pitre). v16: * Significant clean up of the printk patches (Thomas Gleixner). Replacing macros with real functions, CONFIG_ARCH_WANT_NMI_PRINTK -> CONFIG_PRINTK_NMI, prefixing global functions with printk_nmi, removing pointless exports, removing cpu_mask from the interfaces, removal of just-in-time initialization of trace buffers, prevented call sites having to save state, rolled up variable declarations into single lines. * Dropped the sched_clock() patches from *this* patchset and managed them separately (http://thread.gmane.org/gmane.linux.kernel/1879261 ). The cross-dependancies between the patches are minimal; the backtrace code only calls sched_clock() if we are ftracing and backtracing is normally only triggered to report information about about a broken system (although users can type SysRq-l for amusement, most use it to find out why the system it dead). * Squashed together the final two patches. Essentially these duplicated the x86 code and slavishly avoided changing it before, in the next patch, fixing it to work better on ARM. It seems better that the code just works first time! v15: * Added a patch to make sched_clock safe to call from NMI (Stephen Boyd). Note that sched_clock() is not called by the NMI handlers that have been added for the arm but it could be called if tools such as ftrace are deployed. * Fixed some warnings picked up during bisectability testing. v14: * Moved a nmi_vprintk() and friends from arch/x86/kernel/apic/hw_nmi.c to printk.c (Steven Rostedt) v13: * Updated the code to print the backtrace to replicate Steven Rostedt's x86 work to make SysRq-l safe. This is pretty much a total rewrite of patches 4 and 5. v12: * Squash first two patches into a single one and re-describe (Thomas Gleixner). * Improve description of "irqchip: gic: Make gic_raise_softirq FIQ-safe" (Thomas Gleixner). v11: * Optimized gic_raise_softirq() by replacing a register read with a memory read (Jason Cooper). v10: * Add a further patch to optimize away some of the locking on systems where CONFIG_BL_SWITCHER is not set (Marc Zyngier). Compiles OK with exynos_defconfig (which is the only defconfig to set this option). * Whitespace fixes in patch 4. That patch previously used spaces for alignment of new constants but the rest of the file used tabs. v9: * Improved documentation and structure of initial patch (now initial two patches) to make gic_raise_softirq() safe to call from FIQ (Thomas Gleixner). * Avoid masking interrupts during gic_raise_softirq(). The use of the read lock makes this redundant (because we can safely re-enter the function). v8: * Fixed build on arm64 causes by a spurious include file in irq-gic.c. v7-2 (accidentally released twice with same number): * Fixed boot regression on vexpress-a9 (reported by Russell King). * Rebased on v3.18-rc3; removed one patch from set that is already included in mainline. * Dropped arm64/fiq.h patch from the set (still useful but not related to issuing backtraces). v7: * Re-arranged code within the patch series to fix a regression introduced midway through the series and corrected by a later patch (testing by Olof's autobuilder). Tested offending patch in isolation using defconfig identified by the autobuilder. v6: * Renamed svc_entry's call_trace argument to just trace (example code from Russell King). * Fixed mismatched ENDPROC() in __fiq_abt (example code from Russell King). * Modified usr_entry to optional avoid calling into the trace code and used this in FIQ entry from usr path. Modified corresponding exit code to avoid calling into trace code and the scheduler (example code from Russell King). * Ensured the default FIQ register state is restored when the default FIQ handler is reinstalled (example code from Russell King). * Renamed no_fiq_insn to dfl_fiq_insn to reflect the effect of adopting a default FIQ handler. * Re-instated fiq_safe_migration_lock and associated logic in gic_raise_softirq(). gic_raise_softirq() is called by wake_up_klogd() in the console unlock logic. v5: * Rebased on 3.17-rc4. * Removed a spurious line from the final "glue it together" patch that broke the build. v4: * Replaced push/pop with stmfd/ldmfd respectively (review of Nicolas Pitre). * Really fix bad pt_regs pointer generation in __fiq_abt. * Remove fiq_safe_migration_lock and associated logic in gic_raise_softirq() (review of Russell King) * Restructured to introduce the default FIQ handler first, before the new features (review of Russell King). v3: * Removed redundant header guards from arch/arm64/include/asm/fiq.h (review of Catalin Marinas). * Moved svc_exit_via_fiq macro to entry-header.S (review of Nicolas Pitre). v2: * Restructured to sit nicely on a similar FYI patchset from Russell King. It now effectively replaces the work in progress final patch with something much more complete. * Implemented (and tested) a Thumb-2 implementation of svc_exit_via_fiq (review of Nicolas Pitre) * Dropped the GIC group 0 workaround patch. The issue of FIQ interrupts being acknowledged by the IRQ handler does still exist but should be harmless because the IRQ handler will still wind up calling ipi_cpu_backtrace(). * Removed any dependency on CONFIG_FIQ; all cpu backtrace effectively becomes a platform feature (although the use of non-maskable interrupts to implement it is best effort rather than guaranteed). * Better comments highlighting usage of RAZ/WI registers (and parts of registers) in the GIC code. Changes *before* v1: * This patchset is a hugely cut-down successor to "[PATCH v11 00/19] arm: KGDB NMI/FIQ support". Thanks to Thomas Gleixner for suggesting the new structure. For historic details see: https://lkml.org/lkml/2014/9/2/227 * Fix bug in __fiq_abt (no longer passes a bad struct pt_regs value). In fixing this we also remove the useless indirection previously found in the fiq_handler macro. * Make default fiq handler "always on" by migrating from fiq.c to traps.c and replace do_unexp_fiq with the new handler (review of Russell King). * Add arm64 version of fiq.h (review of Russell King) * Removed conditional branching and code from irq-gic.c, this is replaced by much simpler code that relies on the GIC specification's heavy use of read-as-zero/write-ignored (review of Russell King) Daniel Thompson (6): irqchip: gic: Optimize locking in gic_raise_softirq irqchip: gic: Make gic_raise_softirq FIQ-safe irqchip: gic: Introduce plumbing for IPI FIQ printk: Simple implementation for NMI backtracing x86/nmi: Use common printk functions ARM: Add support for on-demand backtrace of other CPUs arch/arm/Kconfig | 1 + arch/arm/include/asm/hardirq.h | 2 +- arch/arm/include/asm/irq.h | 5 + arch/arm/include/asm/smp.h | 3 + arch/arm/kernel/smp.c | 81 ++++++++++++++++ arch/arm/kernel/traps.c | 8 +- arch/x86/Kconfig | 1 + arch/x86/kernel/apic/hw_nmi.c | 101 ++------------------ drivers/irqchip/irq-gic.c | 203 +++++++++++++++++++++++++++++++++++++--- include/linux/irqchip/arm-gic.h | 8 ++ include/linux/printk.h | 20 ++++ init/Kconfig | 3 + kernel/printk/Makefile | 1 + kernel/printk/nmi_backtrace.c | 147 +++++++++++++++++++++++++++++ 14 files changed, 473 insertions(+), 111 deletions(-) create mode 100644 kernel/printk/nmi_backtrace.c -- 2.1.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [RESEND PATCH 4.0-rc5 v19 3/6] irqchip: gic: Introduce plumbing for IPI FIQ 2015-04-07 15:37 ` [RESEND PATCH " Daniel Thompson @ 2015-04-07 15:38 ` Daniel Thompson 0 siblings, 0 replies; 6+ messages in thread From: Daniel Thompson @ 2015-04-07 15:38 UTC (permalink / raw) To: Thomas Gleixner, Jason Cooper Cc: Daniel Thompson, Russell King, Will Deacon, Catalin Marinas, Marc Zyngier, Stephen Boyd, John Stultz, Steven Rostedt, linux-kernel, linux-arm-kernel, patches, linaro-kernel, Sumit Semwal, Dirk Behme, Daniel Drake, Dmitry Pervushin, Tim Sander Currently it is not possible to exploit FIQ for systems with a GIC, even if the systems are otherwise capable of it. This patch makes it possible for IPIs to be delivered using FIQ. To do so it modifies the register state so that normal interrupts are placed in group 1 and specific IPIs are placed into group 0. It also configures the controller to raise group 0 interrupts using the FIQ signal. It provides a means for architecture code to define which IPIs shall use FIQ and to acknowledge any IPIs that are raised. All GIC hardware except GICv1-without-TrustZone support provides a means to group exceptions into group 0 and group 1 but the hardware functionality is unavailable to the kernel when a secure monitor is present because access to the grouping registers are prohibited outside "secure world". However when grouping is not available (or in the case of early GICv1 implementations is very hard to configure) the code to change groups does not deploy and all IPIs will be raised via IRQ. It has been tested and shown working on two systems capable of supporting grouping (Freescale i.MX6 and STiH416). It has also been tested for boot regressions on two systems that do not support grouping (vexpress-a9 and Qualcomm Snapdragon 600). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Russell King <linux@arm.linux.org.uk> Cc: Marc Zyngier <marc.zyngier@arm.com> Tested-by: Jon Medhurst <tixy@linaro.org> --- arch/arm/kernel/traps.c | 5 +- drivers/irqchip/irq-gic.c | 151 +++++++++++++++++++++++++++++++++++++--- include/linux/irqchip/arm-gic.h | 8 +++ 3 files changed, 153 insertions(+), 11 deletions(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 788e23fe64d8..b35e220ae1b1 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/irq.h> +#include <linux/irqchip/arm-gic.h> #include <linux/atomic.h> #include <asm/cacheflush.h> @@ -479,7 +480,9 @@ asmlinkage void __exception_irq_entry handle_fiq_as_nmi(struct pt_regs *regs) nmi_enter(); - /* nop. FIQ handlers for special arch/arm features can be added here. */ +#ifdef CONFIG_ARM_GIC + gic_handle_fiq_ipi(); +#endif nmi_exit(); diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 578ffc5ec087..ffd1c0fe44b2 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -39,6 +39,7 @@ #include <linux/slab.h> #include <linux/irqchip/chained_irq.h> #include <linux/irqchip/arm-gic.h> +#include <linux/ratelimit.h> #include <asm/cputype.h> #include <asm/irq.h> @@ -48,6 +49,10 @@ #include "irq-gic-common.h" #include "irqchip.h" +#ifndef SMP_IPI_FIQ_MASK +#define SMP_IPI_FIQ_MASK 0 +#endif + union gic_base { void __iomem *common_base; void __percpu * __iomem *percpu_base; @@ -65,6 +70,7 @@ struct gic_chip_data { #endif struct irq_domain *domain; unsigned int gic_irqs; + u32 igroup0_shadow; #ifdef CONFIG_GIC_NON_BANKED void __iomem *(*get_base)(union gic_base *); #endif @@ -355,6 +361,83 @@ static struct irq_chip gic_chip = { .irq_set_wake = gic_set_wake, }; +/* + * Shift an interrupt between Group 0 and Group 1. + * + * In addition to changing the group we also modify the priority to + * match what "ARM strongly recommends" for a system where no Group 1 + * interrupt must ever preempt a Group 0 interrupt. + * + * If is safe to call this function on systems which do not support + * grouping (it will have no effect). + */ +static void gic_set_group_irq(struct gic_chip_data *gic, unsigned int hwirq, + int group) +{ + void __iomem *base = gic_data_dist_base(gic); + unsigned int grp_reg = hwirq / 32 * 4; + u32 grp_mask = BIT(hwirq % 32); + u32 grp_val; + + unsigned int pri_reg = (hwirq / 4) * 4; + u32 pri_mask = BIT(7 + ((hwirq % 4) * 8)); + u32 pri_val; + + /* + * Systems which do not support grouping will have not have + * the EnableGrp1 bit set. + */ + if (!(GICD_ENABLE_GRP1 & readl_relaxed(base + GIC_DIST_CTRL))) + return; + + raw_spin_lock(&irq_controller_lock); + + grp_val = readl_relaxed(base + GIC_DIST_IGROUP + grp_reg); + pri_val = readl_relaxed(base + GIC_DIST_PRI + pri_reg); + + if (group) { + grp_val |= grp_mask; + pri_val |= pri_mask; + } else { + grp_val &= ~grp_mask; + pri_val &= ~pri_mask; + } + + writel_relaxed(grp_val, base + GIC_DIST_IGROUP + grp_reg); + if (grp_reg == 0) + gic->igroup0_shadow = grp_val; + + writel_relaxed(pri_val, base + GIC_DIST_PRI + pri_reg); + + raw_spin_unlock(&irq_controller_lock); +} + + +/* + * Fully acknowledge (both ack and eoi) any outstanding FIQ-based IPI, + * otherwise do nothing. + */ +void gic_handle_fiq_ipi(void) +{ + struct gic_chip_data *gic = &gic_data[0]; + void __iomem *cpu_base = gic_data_cpu_base(gic); + unsigned long irqstat, irqnr; + + if (WARN_ON(!in_nmi())) + return; + + while ((1u << readl_relaxed(cpu_base + GIC_CPU_HIGHPRI)) & + SMP_IPI_FIQ_MASK) { + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); + + irqnr = irqstat & GICC_IAR_INT_ID_MASK; + WARN_RATELIMIT(irqnr > 16, + "Unexpected irqnr %lu (bad prioritization?)\n", + irqnr); + } +} + void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) { if (gic_nr >= MAX_GIC_NR) @@ -386,15 +469,24 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic) static void gic_cpu_if_up(void) { void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); - u32 bypass = 0; + void __iomem *dist_base = gic_data_dist_base(&gic_data[0]); + u32 ctrl = 0; /* - * Preserve bypass disable bits to be written back later - */ - bypass = readl(cpu_base + GIC_CPU_CTRL); - bypass &= GICC_DIS_BYPASS_MASK; + * Preserve bypass disable bits to be written back later + */ + ctrl = readl(cpu_base + GIC_CPU_CTRL); + ctrl &= GICC_DIS_BYPASS_MASK; - writel_relaxed(bypass | GICC_ENABLE, cpu_base + GIC_CPU_CTRL); + /* + * If EnableGrp1 is set in the distributor then enable group 1 + * support for this CPU (and route group 0 interrupts to FIQ). + */ + if (GICD_ENABLE_GRP1 & readl_relaxed(dist_base + GIC_DIST_CTRL)) + ctrl |= GICC_COMMON_BPR | GICC_FIQ_EN | GICC_ACK_CTL | + GICC_ENABLE_GRP1; + + writel_relaxed(ctrl | GICC_ENABLE, cpu_base + GIC_CPU_CTRL); } @@ -418,7 +510,23 @@ static void __init gic_dist_init(struct gic_chip_data *gic) gic_dist_config(base, gic_irqs, NULL); - writel_relaxed(GICD_ENABLE, base + GIC_DIST_CTRL); + /* + * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only, + * bit 1 ignored) depending on current mode. + */ + writel_relaxed(GICD_ENABLE_GRP1 | GICD_ENABLE, base + GIC_DIST_CTRL); + + /* + * Set all global interrupts to be group 1 if (and only if) it + * is possible to enable group 1 interrupts. This register is RAZ/WI + * if not accessible or not implemented, however some GICv1 devices + * do not implement the EnableGrp1 bit making it unsafe to set + * this register unconditionally. + */ + if (GICD_ENABLE_GRP1 & readl_relaxed(base + GIC_DIST_CTRL)) + for (i = 32; i < gic_irqs; i += 32) + writel_relaxed(0xffffffff, + base + GIC_DIST_IGROUP + i * 4 / 32); } static void gic_cpu_init(struct gic_chip_data *gic) @@ -427,6 +535,7 @@ static void gic_cpu_init(struct gic_chip_data *gic) void __iomem *base = gic_data_cpu_base(gic); unsigned int cpu_mask, cpu = smp_processor_id(); int i; + unsigned long secure_irqs, secure_irq; /* * Get what the GIC says our CPU mask is. @@ -445,6 +554,20 @@ static void gic_cpu_init(struct gic_chip_data *gic) gic_cpu_config(dist_base, NULL); + /* + * If the distributor is configured to support interrupt grouping + * then set any PPI and SGI interrupts not set in SMP_IPI_FIQ_MASK + * to be group1 and ensure any remaining group 0 interrupts have + * the right priority. + */ + if (GICD_ENABLE_GRP1 & readl_relaxed(dist_base + GIC_DIST_CTRL)) { + secure_irqs = SMP_IPI_FIQ_MASK; + writel_relaxed(~secure_irqs, dist_base + GIC_DIST_IGROUP + 0); + gic->igroup0_shadow = ~secure_irqs; + for_each_set_bit(secure_irq, &secure_irqs, 16) + gic_set_group_irq(gic, secure_irq, 0); + } + writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK); gic_cpu_if_up(); } @@ -534,7 +657,8 @@ static void gic_dist_restore(unsigned int gic_nr) writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], dist_base + GIC_DIST_ENABLE_SET + i * 4); - writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL); + writel_relaxed(GICD_ENABLE_GRP1 | GICD_ENABLE, + dist_base + GIC_DIST_CTRL); } static void gic_cpu_save(unsigned int gic_nr) @@ -662,6 +786,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { int cpu; unsigned long map = 0; + unsigned long softint; gic_migration_lock(); @@ -675,8 +800,14 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) */ dmb(ishst); - /* this always happens on GIC0 */ - writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); + /* We avoid a readl here by using the shadow copy of IGROUP[0] */ + softint = map << 16 | irq; + if (gic_data[0].igroup0_shadow & BIT(irq)) + softint |= 0x8000; + + /* This always happens on GIC0 */ + writel_relaxed(softint, + gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); gic_migration_unlock(); } diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 71d706d5f169..7690f70049a3 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -22,6 +22,10 @@ #define GIC_CPU_IDENT 0xfc #define GICC_ENABLE 0x1 +#define GICC_ENABLE_GRP1 0x2 +#define GICC_ACK_CTL 0x4 +#define GICC_FIQ_EN 0x8 +#define GICC_COMMON_BPR 0x10 #define GICC_INT_PRI_THRESHOLD 0xf0 #define GICC_IAR_INT_ID_MASK 0x3ff #define GICC_INT_SPURIOUS 1023 @@ -44,6 +48,7 @@ #define GIC_DIST_SGI_PENDING_SET 0xf20 #define GICD_ENABLE 0x1 +#define GICD_ENABLE_GRP1 0x2 #define GICD_DISABLE 0x0 #define GICD_INT_ACTLOW_LVLTRIG 0x0 #define GICD_INT_EN_CLR_X32 0xffffffff @@ -121,5 +126,8 @@ static inline void __init register_routable_domain_ops { gic_routable_irq_domain_ops = ops; } + +void gic_handle_fiq_ipi(void); + #endif /* __ASSEMBLY */ #endif -- 2.1.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RESEND PATCH 4.0-rc5 v19 3/6] irqchip: gic: Introduce plumbing for IPI FIQ @ 2015-04-07 15:38 ` Daniel Thompson 0 siblings, 0 replies; 6+ messages in thread From: Daniel Thompson @ 2015-04-07 15:38 UTC (permalink / raw) To: linux-arm-kernel Currently it is not possible to exploit FIQ for systems with a GIC, even if the systems are otherwise capable of it. This patch makes it possible for IPIs to be delivered using FIQ. To do so it modifies the register state so that normal interrupts are placed in group 1 and specific IPIs are placed into group 0. It also configures the controller to raise group 0 interrupts using the FIQ signal. It provides a means for architecture code to define which IPIs shall use FIQ and to acknowledge any IPIs that are raised. All GIC hardware except GICv1-without-TrustZone support provides a means to group exceptions into group 0 and group 1 but the hardware functionality is unavailable to the kernel when a secure monitor is present because access to the grouping registers are prohibited outside "secure world". However when grouping is not available (or in the case of early GICv1 implementations is very hard to configure) the code to change groups does not deploy and all IPIs will be raised via IRQ. It has been tested and shown working on two systems capable of supporting grouping (Freescale i.MX6 and STiH416). It has also been tested for boot regressions on two systems that do not support grouping (vexpress-a9 and Qualcomm Snapdragon 600). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Russell King <linux@arm.linux.org.uk> Cc: Marc Zyngier <marc.zyngier@arm.com> Tested-by: Jon Medhurst <tixy@linaro.org> --- arch/arm/kernel/traps.c | 5 +- drivers/irqchip/irq-gic.c | 151 +++++++++++++++++++++++++++++++++++++--- include/linux/irqchip/arm-gic.h | 8 +++ 3 files changed, 153 insertions(+), 11 deletions(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 788e23fe64d8..b35e220ae1b1 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/sched.h> #include <linux/irq.h> +#include <linux/irqchip/arm-gic.h> #include <linux/atomic.h> #include <asm/cacheflush.h> @@ -479,7 +480,9 @@ asmlinkage void __exception_irq_entry handle_fiq_as_nmi(struct pt_regs *regs) nmi_enter(); - /* nop. FIQ handlers for special arch/arm features can be added here. */ +#ifdef CONFIG_ARM_GIC + gic_handle_fiq_ipi(); +#endif nmi_exit(); diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 578ffc5ec087..ffd1c0fe44b2 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -39,6 +39,7 @@ #include <linux/slab.h> #include <linux/irqchip/chained_irq.h> #include <linux/irqchip/arm-gic.h> +#include <linux/ratelimit.h> #include <asm/cputype.h> #include <asm/irq.h> @@ -48,6 +49,10 @@ #include "irq-gic-common.h" #include "irqchip.h" +#ifndef SMP_IPI_FIQ_MASK +#define SMP_IPI_FIQ_MASK 0 +#endif + union gic_base { void __iomem *common_base; void __percpu * __iomem *percpu_base; @@ -65,6 +70,7 @@ struct gic_chip_data { #endif struct irq_domain *domain; unsigned int gic_irqs; + u32 igroup0_shadow; #ifdef CONFIG_GIC_NON_BANKED void __iomem *(*get_base)(union gic_base *); #endif @@ -355,6 +361,83 @@ static struct irq_chip gic_chip = { .irq_set_wake = gic_set_wake, }; +/* + * Shift an interrupt between Group 0 and Group 1. + * + * In addition to changing the group we also modify the priority to + * match what "ARM strongly recommends" for a system where no Group 1 + * interrupt must ever preempt a Group 0 interrupt. + * + * If is safe to call this function on systems which do not support + * grouping (it will have no effect). + */ +static void gic_set_group_irq(struct gic_chip_data *gic, unsigned int hwirq, + int group) +{ + void __iomem *base = gic_data_dist_base(gic); + unsigned int grp_reg = hwirq / 32 * 4; + u32 grp_mask = BIT(hwirq % 32); + u32 grp_val; + + unsigned int pri_reg = (hwirq / 4) * 4; + u32 pri_mask = BIT(7 + ((hwirq % 4) * 8)); + u32 pri_val; + + /* + * Systems which do not support grouping will have not have + * the EnableGrp1 bit set. + */ + if (!(GICD_ENABLE_GRP1 & readl_relaxed(base + GIC_DIST_CTRL))) + return; + + raw_spin_lock(&irq_controller_lock); + + grp_val = readl_relaxed(base + GIC_DIST_IGROUP + grp_reg); + pri_val = readl_relaxed(base + GIC_DIST_PRI + pri_reg); + + if (group) { + grp_val |= grp_mask; + pri_val |= pri_mask; + } else { + grp_val &= ~grp_mask; + pri_val &= ~pri_mask; + } + + writel_relaxed(grp_val, base + GIC_DIST_IGROUP + grp_reg); + if (grp_reg == 0) + gic->igroup0_shadow = grp_val; + + writel_relaxed(pri_val, base + GIC_DIST_PRI + pri_reg); + + raw_spin_unlock(&irq_controller_lock); +} + + +/* + * Fully acknowledge (both ack and eoi) any outstanding FIQ-based IPI, + * otherwise do nothing. + */ +void gic_handle_fiq_ipi(void) +{ + struct gic_chip_data *gic = &gic_data[0]; + void __iomem *cpu_base = gic_data_cpu_base(gic); + unsigned long irqstat, irqnr; + + if (WARN_ON(!in_nmi())) + return; + + while ((1u << readl_relaxed(cpu_base + GIC_CPU_HIGHPRI)) & + SMP_IPI_FIQ_MASK) { + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); + + irqnr = irqstat & GICC_IAR_INT_ID_MASK; + WARN_RATELIMIT(irqnr > 16, + "Unexpected irqnr %lu (bad prioritization?)\n", + irqnr); + } +} + void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) { if (gic_nr >= MAX_GIC_NR) @@ -386,15 +469,24 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic) static void gic_cpu_if_up(void) { void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); - u32 bypass = 0; + void __iomem *dist_base = gic_data_dist_base(&gic_data[0]); + u32 ctrl = 0; /* - * Preserve bypass disable bits to be written back later - */ - bypass = readl(cpu_base + GIC_CPU_CTRL); - bypass &= GICC_DIS_BYPASS_MASK; + * Preserve bypass disable bits to be written back later + */ + ctrl = readl(cpu_base + GIC_CPU_CTRL); + ctrl &= GICC_DIS_BYPASS_MASK; - writel_relaxed(bypass | GICC_ENABLE, cpu_base + GIC_CPU_CTRL); + /* + * If EnableGrp1 is set in the distributor then enable group 1 + * support for this CPU (and route group 0 interrupts to FIQ). + */ + if (GICD_ENABLE_GRP1 & readl_relaxed(dist_base + GIC_DIST_CTRL)) + ctrl |= GICC_COMMON_BPR | GICC_FIQ_EN | GICC_ACK_CTL | + GICC_ENABLE_GRP1; + + writel_relaxed(ctrl | GICC_ENABLE, cpu_base + GIC_CPU_CTRL); } @@ -418,7 +510,23 @@ static void __init gic_dist_init(struct gic_chip_data *gic) gic_dist_config(base, gic_irqs, NULL); - writel_relaxed(GICD_ENABLE, base + GIC_DIST_CTRL); + /* + * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only, + * bit 1 ignored) depending on current mode. + */ + writel_relaxed(GICD_ENABLE_GRP1 | GICD_ENABLE, base + GIC_DIST_CTRL); + + /* + * Set all global interrupts to be group 1 if (and only if) it + * is possible to enable group 1 interrupts. This register is RAZ/WI + * if not accessible or not implemented, however some GICv1 devices + * do not implement the EnableGrp1 bit making it unsafe to set + * this register unconditionally. + */ + if (GICD_ENABLE_GRP1 & readl_relaxed(base + GIC_DIST_CTRL)) + for (i = 32; i < gic_irqs; i += 32) + writel_relaxed(0xffffffff, + base + GIC_DIST_IGROUP + i * 4 / 32); } static void gic_cpu_init(struct gic_chip_data *gic) @@ -427,6 +535,7 @@ static void gic_cpu_init(struct gic_chip_data *gic) void __iomem *base = gic_data_cpu_base(gic); unsigned int cpu_mask, cpu = smp_processor_id(); int i; + unsigned long secure_irqs, secure_irq; /* * Get what the GIC says our CPU mask is. @@ -445,6 +554,20 @@ static void gic_cpu_init(struct gic_chip_data *gic) gic_cpu_config(dist_base, NULL); + /* + * If the distributor is configured to support interrupt grouping + * then set any PPI and SGI interrupts not set in SMP_IPI_FIQ_MASK + * to be group1 and ensure any remaining group 0 interrupts have + * the right priority. + */ + if (GICD_ENABLE_GRP1 & readl_relaxed(dist_base + GIC_DIST_CTRL)) { + secure_irqs = SMP_IPI_FIQ_MASK; + writel_relaxed(~secure_irqs, dist_base + GIC_DIST_IGROUP + 0); + gic->igroup0_shadow = ~secure_irqs; + for_each_set_bit(secure_irq, &secure_irqs, 16) + gic_set_group_irq(gic, secure_irq, 0); + } + writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK); gic_cpu_if_up(); } @@ -534,7 +657,8 @@ static void gic_dist_restore(unsigned int gic_nr) writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], dist_base + GIC_DIST_ENABLE_SET + i * 4); - writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL); + writel_relaxed(GICD_ENABLE_GRP1 | GICD_ENABLE, + dist_base + GIC_DIST_CTRL); } static void gic_cpu_save(unsigned int gic_nr) @@ -662,6 +786,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { int cpu; unsigned long map = 0; + unsigned long softint; gic_migration_lock(); @@ -675,8 +800,14 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) */ dmb(ishst); - /* this always happens on GIC0 */ - writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); + /* We avoid a readl here by using the shadow copy of IGROUP[0] */ + softint = map << 16 | irq; + if (gic_data[0].igroup0_shadow & BIT(irq)) + softint |= 0x8000; + + /* This always happens on GIC0 */ + writel_relaxed(softint, + gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); gic_migration_unlock(); } diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 71d706d5f169..7690f70049a3 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -22,6 +22,10 @@ #define GIC_CPU_IDENT 0xfc #define GICC_ENABLE 0x1 +#define GICC_ENABLE_GRP1 0x2 +#define GICC_ACK_CTL 0x4 +#define GICC_FIQ_EN 0x8 +#define GICC_COMMON_BPR 0x10 #define GICC_INT_PRI_THRESHOLD 0xf0 #define GICC_IAR_INT_ID_MASK 0x3ff #define GICC_INT_SPURIOUS 1023 @@ -44,6 +48,7 @@ #define GIC_DIST_SGI_PENDING_SET 0xf20 #define GICD_ENABLE 0x1 +#define GICD_ENABLE_GRP1 0x2 #define GICD_DISABLE 0x0 #define GICD_INT_ACTLOW_LVLTRIG 0x0 #define GICD_INT_EN_CLR_X32 0xffffffff @@ -121,5 +126,8 @@ static inline void __init register_routable_domain_ops { gic_routable_irq_domain_ops = ops; } + +void gic_handle_fiq_ipi(void); + #endif /* __ASSEMBLY */ #endif -- 2.1.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-04-08 10:23 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <088701d071d3$ec642a90$c52c7fb0$@alibaba-inc.com> 2015-04-08 8:19 ` [RESEND PATCH 4.0-rc5 v19 3/6] irqchip: gic: Introduce plumbing for IPI FIQ Hillf Danton 2015-04-08 8:19 ` Hillf Danton 2015-04-08 10:23 ` Daniel Thompson 2015-04-08 10:23 ` Daniel Thompson 2015-03-24 16:53 [PATCH 4.0-rc5 v19 0/6] irq/arm: Implement arch_trigger_all_cpu_backtrace Daniel Thompson 2015-04-07 15:37 ` [RESEND PATCH " Daniel Thompson 2015-04-07 15:38 ` [RESEND PATCH 4.0-rc5 v19 3/6] irqchip: gic: Introduce plumbing for IPI FIQ Daniel Thompson 2015-04-07 15:38 ` Daniel Thompson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.