* [RFC 0/8] kgdb: NMI/FIQ support for ARM @ 2014-05-14 15:58 Daniel Thompson 2014-05-14 15:58 ` [RFC 1/8] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson ` (8 more replies) 0 siblings, 9 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman This patchset makes it possible to use the kgdb NMI infrastructure on ARM platforms. The kgdb NMI infrastructure works by re-routing an UARTs interrupt signal from IRQ to FIQ. The UART will no longer function normally and will instead be managed by kgdb using the polled I/O functions. Any character delivered to the UART causes the kgdb handler function to be called. Each serial driver explicitly consents (or not) to this abuse by calling the appropriate registration functions. [PATCH 1/8] arm: fiq: Allow EOI to be communicated to the intc [PATCH 2/8] irqchip: gic: Provide support for interrupt grouping Both these patches lay the ground work to allow modern ARM interrupt controllers to support FIQ correctly. [PATCH 3/8] ARM: Move some macros from entry-armv to entry-header [PATCH 4/8] ARM: Add KGDB/KDB FIQ debugger generic code This is the heart of the patch series, allowing FIQs to be registered with KGDB and handled by KGDB. [PATCH 5/8] serial: amba-pl011: Pass on FIQ information to KGDB. [PATCH 6/8] serial: asc: Add support for KGDB's FIQ/NMI mode Extend to UART drivers to allow the register the appropriate FIQ (implicitly promising to behave properly when their own IRQ handler is cut off). [PATCH 7/8] ARM: VIC: Add vic_set_fiq function to select if an... [PATCH 8/8] arm: fiq: Hack FIQ routing backdoors into GIC and VIC Here we hit the serious request-for-comment section. It is not clear what the best way to get the interrupt controller to re-route an interrupt source from the IRQ signal to the FIQ signal. Clearly the approach here is wrong but it has been enough for me to test my work so far. Anton Vorontsov (2): ARM: Move some macros from entry-armv to entry-header ARM: Add KGDB/KDB FIQ debugger generic code Arve Hjønnevåg (1): ARM: VIC: Add vic_set_fiq function to select if an interrupt should generate an IRQ or FIQ Daniel Thompson (5): arm: fiq: Allow EOI to be communicated to the intc irqchip: gic: Provide support for interrupt grouping serial: amba-pl011: Pass on FIQ information to KGDB. serial: asc: Add support for KGDB's FIQ/NMI mode arm: fiq: Hack FIQ routing backdoors into GIC and VIC arch/arm/Kconfig | 2 + arch/arm/Kconfig.debug | 18 ++++ arch/arm/boot/dts/stih416.dtsi | 2 +- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 2 +- arch/arm/include/asm/fiq.h | 1 + arch/arm/include/asm/kgdb.h | 7 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/entry-armv.S | 151 +---------------------------- arch/arm/kernel/entry-header.S | 164 ++++++++++++++++++++++++++++++++ arch/arm/kernel/fiq.c | 50 ++++++++++ arch/arm/kernel/kgdb_fiq.c | 117 +++++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++++ drivers/irqchip/irq-gic.c | 62 +++++++++++- drivers/irqchip/irq-vic.c | 23 +++++ drivers/tty/serial/amba-pl011.c | 18 +++- drivers/tty/serial/st-asc.c | 25 +++++ include/linux/irqchip/arm-gic.h | 3 + include/linux/irqchip/arm-vic.h | 1 + 18 files changed, 576 insertions(+), 158 deletions(-) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S -- 1.9.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC 1/8] arm: fiq: Allow EOI to be communicated to the intc 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson @ 2014-05-14 15:58 ` Daniel Thompson 2014-05-14 15:58 ` [RFC 2/8] irqchip: gic: Provide support for interrupt grouping Daniel Thompson ` (7 subsequent siblings) 8 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman Modern ARM systems require an EOI to be sent to the interrupt controller on completion of both IRQ and FIQ. The FIQ code currently does not permit this requiring nasty register poke hacks from the FIQ handler. This patch provides a simple interface for C based handlers to complete a FIQ. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> --- arch/arm/include/asm/fiq.h | 1 + arch/arm/kernel/fiq.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h index d493d0b..5a2a9b9 100644 --- a/arch/arm/include/asm/fiq.h +++ b/arch/arm/include/asm/fiq.h @@ -38,6 +38,7 @@ extern void release_fiq(struct fiq_handler *f); extern void set_fiq_handler(void *start, unsigned int length); extern void enable_fiq(int fiq); extern void disable_fiq(int fiq); +extern void eoi_fiq(int fiq); /* helpers defined in fiqasm.S: */ extern void __set_fiq_regs(unsigned long const *regs); diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 918875d..defbe85 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -40,6 +40,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/seq_file.h> +#include <linux/irq.h> #include <asm/cacheflush.h> #include <asm/cp15.h> @@ -139,6 +140,15 @@ void disable_fiq(int fiq) disable_irq(fiq + fiq_start); } +void eoi_fiq(int fiq) +{ + struct irq_data *irq_data = irq_get_irq_data(fiq + fiq_start); + struct irq_chip *chip = irq_data_get_irq_chip(irq_data); + + if (chip->irq_eoi) + chip->irq_eoi(irq_data); +} + EXPORT_SYMBOL(set_fiq_handler); EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ @@ -146,6 +156,7 @@ EXPORT_SYMBOL(claim_fiq); EXPORT_SYMBOL(release_fiq); EXPORT_SYMBOL(enable_fiq); EXPORT_SYMBOL(disable_fiq); +EXPORT_SYMBOL(eoi_fiq); void __init init_FIQ(int start) { -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC 2/8] irqchip: gic: Provide support for interrupt grouping 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-05-14 15:58 ` [RFC 1/8] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson @ 2014-05-14 15:58 ` Daniel Thompson 2014-05-14 15:58 ` [RFC 3/8] ARM: Move some macros from entry-armv to entry-header Daniel Thompson ` (6 subsequent siblings) 8 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman GICv2+ implementions that do not implement security extensions (and devices that boot in secure mode by default) allow the interrupt group registers (used for FIQ/IRQ selection) to be accessed from kernel code. However the current gic support does not initialize the controller to make interrupt grouping effective. The registers involved are RAZ/WI when unimplemented or protected by security policy then it should be safe to set up the grouping unconditionally. Tested on a (self-written) qemu GICv2 model (written from ARM spec) and an STiH416 (ARM Cortex A9). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Acked-by: Dirk Behme <dirk.behme@de.bosch.com> --- drivers/irqchip/irq-gic.c | 35 ++++++++++++++++++++++++++++++----- include/linux/irqchip/arm-gic.h | 3 +++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 57d165e..aa8efe4 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -408,13 +408,27 @@ static void __init gic_dist_init(struct gic_chip_data *gic) writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); /* + * Set all global interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers a read-as-zero/write-ignored. + */ + for (i = 32; i < gic_irqs; i += 32) + writel_relaxed(0xffffffff, base + GIC_DIST_IGROUP + i * 4 / 32); + + /* * Disable all interrupts. Leave the PPI and SGIs alone * as these enables are banked registers. */ for (i = 32; i < gic_irqs; i += 32) writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); - writel_relaxed(1, base + GIC_DIST_CTRL); + /* + * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only, + * bit 1 ignored) + */ + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | + GIC_DIST_CTRL_ENABLE_GRP1_BIT, base + GIC_DIST_CTRL); } static void gic_cpu_init(struct gic_chip_data *gic) @@ -452,8 +466,16 @@ static void gic_cpu_init(struct gic_chip_data *gic) for (i = 0; i < 32; i += 4) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4); + /* + * Set all PPI and SGI interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers are read-as-zero/write-ignored. + */ + writel_relaxed(0xffffffff, dist_base + GIC_DIST_IGROUP + 0); + writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); - writel_relaxed(1, base + GIC_CPU_CTRL); + writel_relaxed(0x1f, base + GIC_CPU_CTRL); } void gic_cpu_if_down(void) @@ -537,7 +559,9 @@ 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(1, dist_base + GIC_DIST_CTRL); + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | + GIC_DIST_CTRL_ENABLE_GRP1_BIT, + dist_base + GIC_DIST_CTRL); } static void gic_cpu_save(unsigned int gic_nr) @@ -594,7 +618,7 @@ static void gic_cpu_restore(unsigned int gic_nr) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); - writel_relaxed(1, cpu_base + GIC_CPU_CTRL); + writel_relaxed(0x1f, cpu_base + GIC_CPU_CTRL); } static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) @@ -670,7 +694,8 @@ 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); + writel_relaxed(map << 16 | irq | 0x8000, + gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); raw_spin_unlock_irqrestore(&irq_controller_lock, flags); } diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 7ed92d0..919502f 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -37,6 +37,9 @@ #define GIC_DIST_SGI_PENDING_CLEAR 0xf10 #define GIC_DIST_SGI_PENDING_SET 0xf20 +#define GIC_DIST_CTRL_ENABLE_GRP0_BIT (1 << 0) +#define GIC_DIST_CTRL_ENABLE_GRP1_BIT (1 << 1) + #define GICH_HCR 0x0 #define GICH_VTR 0x4 #define GICH_VMCR 0x8 -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC 3/8] ARM: Move some macros from entry-armv to entry-header 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-05-14 15:58 ` [RFC 1/8] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson 2014-05-14 15:58 ` [RFC 2/8] irqchip: gic: Provide support for interrupt grouping Daniel Thompson @ 2014-05-14 15:58 ` Daniel Thompson 2014-05-14 15:58 ` [RFC 4/8] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson ` (5 subsequent siblings) 8 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman From: Anton Vorontsov <anton.vorontsov@linaro.org> Just move the macros into header file as we would want to use them for KGDB FIQ entry code. The following macros were moved: - svc_entry - usr_entry - kuser_cmpxchg_check - vector_stub To make kuser_cmpxchg_check actually work across different files, we also have to make kuser_cmpxchg64_fixup global. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> --- arch/arm/kernel/entry-armv.S | 151 +------------------------------------ arch/arm/kernel/entry-header.S | 164 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 150 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 1879e8d..ed95b95 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -140,53 +140,6 @@ ENDPROC(__und_invalid) * SVC mode handlers */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) -#define SPFIX(code...) code -#else -#define SPFIX(code...) -#endif - - .macro svc_entry, stack_hole=0 - UNWIND(.fnstart ) - UNWIND(.save {r0 - pc} ) - sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) -#ifdef CONFIG_THUMB2_KERNEL - SPFIX( str r0, [sp] ) @ temporarily saved - SPFIX( mov r0, sp ) - SPFIX( tst r0, #4 ) @ test original stack alignment - SPFIX( ldr r0, [sp] ) @ restored -#else - SPFIX( tst sp, #4 ) -#endif - SPFIX( subeq sp, sp, #4 ) - stmia sp, {r1 - r12} - - ldmia r0, {r3 - r5} - add r7, sp, #S_SP - 4 @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) - SPFIX( addeq r2, r2, #4 ) - str r3, [sp, #-4]! @ save the "real" r0 copied - @ from the exception stack - - mov r3, lr - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r2 - sp_svc - @ r3 - lr_svc - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - stmia r7, {r2 - r6} - -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif - .endm - .align 5 __dabt_svc: svc_entry @@ -306,73 +259,8 @@ ENDPROC(__pabt_svc) /* * User mode handlers - * - * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - - .macro usr_entry - UNWIND(.fnstart ) - UNWIND(.cantunwind ) @ don't unwind the user space - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - r12} ) - THUMB( stmia sp, {r0 - r12} ) - - ldmia r0, {r3 - r5} - add r0, sp, #S_PC @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - - str r3, [sp] @ save the "real" r0 copied - @ from the exception stack - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - @ Also, separately save sp_usr and lr_usr - @ - stmia r0, {r4 - r6} - ARM( stmdb r0, {sp, lr}^ ) - THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) - - @ - @ Enable the alignment trap while in kernel mode - @ - alignment_trap r0 - - @ - @ Clear FP to mark the first stack frame - @ - zero_fp - -#ifdef CONFIG_IRQSOFF_TRACER - bl trace_hardirqs_off -#endif - ct_user_exit save = 0 - .endm - - .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ - !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ Make sure our user space atomic helper is restarted - @ if it was interrupted in a critical region. Here we - @ perform a quick test inline since it should be false - @ 99.9999% of the time. The rest is done out of line. - cmp r4, #TASK_SIZE - blhs kuser_cmpxchg64_fixup -#endif -#endif - .endm - .align 5 __dabt_usr: usr_entry @@ -819,6 +707,7 @@ __kuser_cmpxchg64: @ 0xffff0f60 ldmfd sp!, {r4, r5, r6, pc} .text + .global kuser_cmpxchg64_fixup kuser_cmpxchg64_fixup: @ Called from kuser_cmpxchg_fixup. @ r4 = address of interrupted insn (must be preserved). @@ -960,44 +849,6 @@ __kuser_helper_end: * SP points to a minimal amount of processor-private memory, the address * of which is copied into r0 for the mode specific abort handler. */ - .macro vector_stub, name, mode, correction=0 - .align 5 - -vector_\name: - .if \correction - sub lr, lr, #\correction - .endif - - @ - @ Save r0, lr_<exception> (parent PC) and spsr_<exception> - @ (parent CPSR) - @ - stmia sp, {r0, lr} @ save r0, lr - mrs lr, spsr - str lr, [sp, #8] @ save spsr - - @ - @ Prepare for SVC32 mode. IRQs remain disabled. - @ - mrs r0, cpsr - eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) - msr spsr_cxsf, r0 - - @ - @ the branch table must immediately follow this code - @ - and lr, lr, #0x0f - THUMB( adr r0, 1f ) - THUMB( ldr lr, [r0, lr, lsl #2] ) - mov r0, sp - ARM( ldr lr, [pc, lr, lsl #2] ) - movs pc, lr @ branch to handler in SVC mode -ENDPROC(vector_\name) - - .align 2 - @ handler addresses follow this label -1: - .endm .section .stubs, "ax", %progbits __stubs_start: diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 1420725..ab04a67 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -352,3 +352,167 @@ scno .req r7 @ syscall number tbl .req r8 @ syscall table pointer why .req r8 @ Linux syscall (!= 0) tsk .req r9 @ current thread_info + +/* + * SVC mode handler macros + */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) +#define SPFIX(code...) code +#else +#define SPFIX(code...) +#endif + + .macro svc_entry, stack_hole=0 + UNWIND(.fnstart ) + UNWIND(.save {r0 - pc} ) + sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) +#ifdef CONFIG_THUMB2_KERNEL + SPFIX( str r0, [sp] ) @ temporarily saved + SPFIX( mov r0, sp ) + SPFIX( tst r0, #4 ) @ test original stack alignment + SPFIX( ldr r0, [sp] ) @ restored +#else + SPFIX( tst sp, #4 ) +#endif + SPFIX( subeq sp, sp, #4 ) + stmia sp, {r1 - r12} + + ldmia r0, {r3 - r5} + add r7, sp, #S_SP - 4 @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) + SPFIX( addeq r2, r2, #4 ) + str r3, [sp, #-4]! @ save the "real" r0 copied + @ from the exception stack + + mov r3, lr + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r2 - sp_svc + @ r3 - lr_svc + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + stmia r7, {r2 - r6} + +#ifdef CONFIG_TRACE_IRQFLAGS + bl trace_hardirqs_off +#endif + .endm + +/* + * User mode handler macros + * + * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE + */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) +#error "sizeof(struct pt_regs) must be a multiple of 8" +#endif + + .macro usr_entry + UNWIND(.fnstart ) + UNWIND(.cantunwind ) @ don't unwind the user space + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) + + ldmia r0, {r3 - r5} + add r0, sp, #S_PC @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + + str r3, [sp] @ save the "real" r0 copied + @ from the exception stack + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + @ Also, separately save sp_usr and lr_usr + @ + stmia r0, {r4 - r6} + ARM( stmdb r0, {sp, lr}^ ) + THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) + + @ + @ Enable the alignment trap while in kernel mode + @ + alignment_trap r0 + + @ + @ Clear FP to mark the first stack frame + @ + zero_fp + +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + ct_user_exit save = 0 + .endm + + .macro kuser_cmpxchg_check +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r4, #TASK_SIZE + blhs kuser_cmpxchg64_fixup +#endif +#endif + .endm + +/* + * Vector stubs macro. + */ + .macro vector_stub, name, mode, correction=0 + .align 5 + +vector_\name: + .if \correction + sub lr, lr, #\correction + .endif + + @ + @ Save r0, lr_<exception> (parent PC) and spsr_<exception> + @ (parent CPSR) + @ + stmia sp, {r0, lr} @ save r0, lr + mrs lr, spsr + str lr, [sp, #8] @ save spsr + + @ + @ Prepare for SVC32 mode. IRQs remain disabled. + @ + mrs r0, cpsr + eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) + msr spsr_cxsf, r0 + + @ + @ the branch table must immediately follow this code + @ + and lr, lr, #0x0f + THUMB( adr r0, 1f ) + THUMB( ldr lr, [r0, lr, lsl #2] ) + mov r0, sp + ARM( ldr lr, [pc, lr, lsl #2] ) + movs pc, lr @ branch to handler in SVC mode +ENDPROC(vector_\name) + + .align 2 + @ handler addresses follow this label +1: + .endm + + -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC 4/8] ARM: Add KGDB/KDB FIQ debugger generic code 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (2 preceding siblings ...) 2014-05-14 15:58 ` [RFC 3/8] ARM: Move some macros from entry-armv to entry-header Daniel Thompson @ 2014-05-14 15:58 ` Daniel Thompson 2014-05-14 15:58 ` [RFC 5/8] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson ` (4 subsequent siblings) 8 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman From: Anton Vorontsov <anton.vorontsov@linaro.org> The FIQ debugger may be used to debug situations when the kernel stuck in uninterruptable sections, e.g. the kernel infinitely loops or deadlocked in an interrupt or with interrupts disabled. By default KGDB FIQ is disabled in runtime, but can be enabled with kgdb_fiq.enable=1 kernel command line option. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> --- arch/arm/Kconfig | 2 + arch/arm/Kconfig.debug | 18 ++++++ arch/arm/include/asm/kgdb.h | 7 +++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/kgdb_fiq.c | 117 +++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++++++++++++++++ 6 files changed, 232 insertions(+) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db3c541..419fd0a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -307,6 +307,7 @@ choice config ARCH_MULTIPLATFORM bool "Allow multiple platforms to be selected" depends on MMU + select ARCH_MIGHT_HAVE_KGDB_FIQ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_HAS_SG_CHAIN select ARM_PATCH_PHYS_VIRT @@ -356,6 +357,7 @@ config ARCH_REALVIEW config ARCH_VERSATILE bool "ARM Ltd. Versatile family" + select ARCH_MIGHT_HAVE_KGDB_FIQ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_AMBA select ARM_TIMER_SP804 diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 6a2bcfd..1f1bec1 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -2,6 +2,24 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config ARCH_MIGHT_HAVE_KGDB_FIQ + bool + +config KGDB_FIQ + bool "KGDB FIQ support" + depends on KGDB_KDB && ARCH_MIGHT_HAVE_KGDB_FIQ && !THUMB2_KERNEL + select FIQ + help + The FIQ debugger may be used to debug situations when the + kernel stuck in uninterruptable sections, e.g. the kernel + infinitely loops or deadlocked in an interrupt or with + interrupts disabled. + + By default KGDB FIQ is disabled at runtime, but can be + enabled with kgdb_fiq.enable=1 kernel command line option. + + If unsure, say N. + config ARM_PTDUMP bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 0a9d5dd..5de21f01 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h @@ -11,7 +11,9 @@ #define __ARM_KGDB_H__ #include <linux/ptrace.h> +#include <linux/linkage.h> #include <asm/opcodes.h> +#include <asm/exception.h> /* * GDB assumes that we're a user process being debugged, so @@ -48,6 +50,11 @@ static inline void arch_kgdb_breakpoint(void) extern void kgdb_handle_bus_error(void); extern int kgdb_fault_expected; +extern char kgdb_fiq_handler; +extern char kgdb_fiq_handler_end; +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs); +extern int kgdb_register_fiq(unsigned int fiq); + #endif /* !__ASSEMBLY__ */ /* diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 040619c..251f651 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -67,6 +67,7 @@ endif obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o +obj-$(CONFIG_KGDB_FIQ) += kgdb_fiq_entry.o kgdb_fiq.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_HAVE_TCM) += tcm.o obj-$(CONFIG_OF) += devtree.o diff --git a/arch/arm/kernel/kgdb_fiq.c b/arch/arm/kernel/kgdb_fiq.c new file mode 100644 index 0000000..b236409 --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq.c @@ -0,0 +1,117 @@ +/* + * KGDB FIQ + * + * Copyright 2010 Google, Inc. + * Arve Hjønnevåg <arve@android.com> + * Colin Cross <ccross@android.com> + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov <anton.vorontsov@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <linux/hardirq.h> +#include <linux/atomic.h> +#include <linux/kdb.h> +#include <linux/kgdb.h> +#include <asm/fiq.h> +#include <asm/exception.h> + +static int kgdb_fiq_enabled; +module_param_named(enable, kgdb_fiq_enabled, int, 0600); +MODULE_PARM_DESC(enable, "set to 1 to enable FIQ KGDB"); + +static unsigned int kgdb_fiq; + +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs) +{ + if (kgdb_nmi_poll_knock()) { + nmi_enter(); + kgdb_handle_exception(1, 0, 0, regs); + nmi_exit(); + } + + eoi_fiq(kgdb_fiq); +} + +static struct fiq_handler kgdb_fiq_desc = { + .name = "kgdb", +}; + +static long kgdb_fiq_setup_stack(void *info) +{ + struct pt_regs regs; + + regs.ARM_sp = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER) + + THREAD_START_SP; + WARN_ON(!regs.ARM_sp); + + set_fiq_regs(®s); + return 0; +} + +/** + * kgdb_fiq_enable_nmi - Manage NMI-triggered entry to KGDB + * @on: Flag to either enable or disable an NMI + * + * This function manages NMIs that usually cause KGDB to enter. That is, not + * all NMIs should be enabled or disabled, but only those that issue + * kgdb_handle_exception(). + * + * The call counts disable requests, and thus allows to nest disables. But + * trying to enable already enabled NMI is an error. + */ +static void kgdb_fiq_enable_nmi(bool on) +{ + static atomic_t cnt; + int ret; + + ret = atomic_add_return(on ? 1 : -1, &cnt); + if (ret > 1 && on) { + /* + * There should be only one instance that calls this function + * in "enable, disable" order. All other users must call + * disable first, then enable. If not, something is wrong. + */ + WARN_ON(1); + return; + } + + if (ret > 0) + enable_fiq(kgdb_fiq); + else + disable_fiq(kgdb_fiq); +} + +int kgdb_register_fiq(unsigned int fiq) +{ + int err; + int cpu; + + if (!kgdb_fiq_enabled) + return -ENODEV; + + kgdb_fiq = fiq; + + err = claim_fiq(&kgdb_fiq_desc); + if (err) { + pr_warn("%s: unable to claim fiq", __func__); + return err; + } + + for_each_possible_cpu(cpu) + work_on_cpu(cpu, kgdb_fiq_setup_stack, NULL); + + set_fiq_handler(&kgdb_fiq_handler, + &kgdb_fiq_handler_end - &kgdb_fiq_handler); + + arch_kgdb_ops.enable_nmi = kgdb_fiq_enable_nmi; + return 0; +} diff --git a/arch/arm/kernel/kgdb_fiq_entry.S b/arch/arm/kernel/kgdb_fiq_entry.S new file mode 100644 index 0000000..d6becca --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq_entry.S @@ -0,0 +1,87 @@ +/* + * KGDB FIQ entry + * + * Copyright 1996,1997,1998 Russell King. + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov <anton.vorontsov@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/memory.h> +#include <asm/unwind.h> +#include "entry-header.S" + + .text + +@ This is needed for usr_entry/alignment_trap +.LCcralign: + .long cr_alignment +.LCdohandle: + .long kgdb_fiq_do_handle + + .macro fiq_handler + ldr r1, =.LCdohandle + mov r0, sp + adr lr, BSYM(9997f) + ldr pc, [r1] +9997: + .endm + + .align 5 +__fiq_svc: + svc_entry + fiq_handler + mov r0, sp + ldmib r0, {r1 - r14} + msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT + add r8, r0, #S_PC + ldr r9, [r0, #S_PSR] + msr spsr_cxsf, r9 + ldr r0, [r0, #S_R0] + ldmia r8, {pc}^ + + UNWIND(.fnend ) +ENDPROC(__fiq_svc) + .ltorg + + .align 5 +__fiq_usr: + usr_entry + kuser_cmpxchg_check + fiq_handler + get_thread_info tsk + mov why, #0 + b ret_to_user_from_irq + UNWIND(.fnend ) +ENDPROC(__fiq_usr) + .ltorg + + .global kgdb_fiq_handler +kgdb_fiq_handler: + + vector_stub fiq, FIQ_MODE, 4 + + .long __fiq_usr @ 0 (USR_26 / USR_32) + .long __fiq_svc @ 1 (FIQ_26 / FIQ_32) + .long __fiq_svc @ 2 (IRQ_26 / IRQ_32) + .long __fiq_svc @ 3 (SVC_26 / SVC_32) + .long __fiq_svc @ 4 + .long __fiq_svc @ 5 + .long __fiq_svc @ 6 + .long __fiq_svc @ 7 + .long __fiq_svc @ 8 + .long __fiq_svc @ 9 + .long __fiq_svc @ a + .long __fiq_svc @ b + .long __fiq_svc @ c + .long __fiq_svc @ d + .long __fiq_svc @ e + .long __fiq_svc @ f + + .global kgdb_fiq_handler_end +kgdb_fiq_handler_end: -- 1.9.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC 5/8] serial: amba-pl011: Pass on FIQ information to KGDB. 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (3 preceding siblings ...) 2014-05-14 15:58 ` [RFC 4/8] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson @ 2014-05-14 15:58 ` Daniel Thompson 2014-05-14 15:58 ` [RFC 6/8] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson ` (3 subsequent siblings) 8 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman It is important this information comes from the serial driver because, by doing so, the driver offers "permission" for KGDB to route its interrupt signal from the drivers own handler to KGDBs FIQ handler (which will handle the interrupt signal by making polled I/O callbacks). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> --- drivers/tty/serial/amba-pl011.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index dacf0a0..aac817a 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -58,6 +58,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/sizes.h> #include <linux/io.h> +#include <linux/kgdb.h> #define UART_NR 14 @@ -2091,6 +2092,18 @@ static int pl011_probe_dt_alias(int index, struct device *dev) return ret; } +#ifdef CONFIG_KGDB_FIQ +/* Register with KGDB if there is a FIQ linked to this device */ +static void pl011_register_fiq(struct amba_device *dev) +{ + int fiq = dev->irq[1]; + if (fiq > 0) + kgdb_register_fiq(fiq); +} +#else +static void pl011_register_fiq(struct platform_device *pdev) {} +#endif + static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; @@ -2164,11 +2177,14 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) } ret = uart_add_one_port(&amba_reg, &uap->port); - if (ret) { + if (0 == ret) { + pl011_register_fiq(dev); + } else { amba_ports[i] = NULL; uart_unregister_driver(&amba_reg); pl011_dma_remove(uap); } + out: return ret; } -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC 6/8] serial: asc: Add support for KGDB's FIQ/NMI mode 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (4 preceding siblings ...) 2014-05-14 15:58 ` [RFC 5/8] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson @ 2014-05-14 15:58 ` Daniel Thompson 2014-05-14 15:58 ` [RFC 7/8] ARM: VIC: Add vic_set_fiq function to select if an interrupt should generate an IRQ or FIQ Daniel Thompson ` (2 subsequent siblings) 8 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman For a serial driver to support FIQ/NMI debugging it must enable the RX interrupt when a polling client attaches itself (otherwise the FIQ signal will never be asserted). This concept is copied from similar code in amba-pl011.c . It must also register the appropriate FIQ number with kgdb. kgdb will use this to make calls to enable_fiq/disable_fiq/eoi_fiq. The FIQ number must be supplied via the devices bus (in this case platform bus). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> --- drivers/tty/serial/st-asc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index c7f61ac..e93803f 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -30,6 +30,7 @@ #include <linux/of_platform.h> #include <linux/serial_core.h> #include <linux/clk.h> +#include <linux/kgdb.h> #define DRIVER_NAME "st-asc" #define ASC_SERIAL_NAME "ttyAS" @@ -613,6 +614,14 @@ asc_verify_port(struct uart_port *port, struct serial_struct *ser) } #ifdef CONFIG_CONSOLE_POLL +static int asc_poll_init(struct uart_port *port) +{ + /* enable RX interrupts in case the interrupt is used for NMI entry. */ + asc_enable_rx_interrupts(port); + + return 0; +} + /* * Console polling routines for writing and reading from the uart while * in an interrupt or debug context (i.e. kgdb). @@ -656,11 +665,25 @@ static struct uart_ops asc_uart_ops = { .verify_port = asc_verify_port, .pm = asc_pm, #ifdef CONFIG_CONSOLE_POLL + .poll_init = asc_poll_init, .poll_get_char = asc_get_poll_char, .poll_put_char = asc_put_poll_char, #endif /* CONFIG_CONSOLE_POLL */ }; +#ifdef CONFIG_KGDB_FIQ +/* Register with KGDB if there is a FIQ linked to this device */ +static void asc_register_fiq(struct platform_device *pdev) +{ + int fiq = platform_get_irq(pdev, 1); + if (fiq >= 0) + kgdb_register_fiq(fiq); +} +#else +static void asc_register_fiq(struct platform_device *pdev) {} +#endif + + static int asc_init_port(struct asc_port *ascport, struct platform_device *pdev) { @@ -692,6 +715,8 @@ static int asc_init_port(struct asc_port *ascport, WARN_ON(ascport->port.uartclk == 0); clk_disable_unprepare(ascport->clk); + asc_register_fiq(pdev); + return 0; } -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC 7/8] ARM: VIC: Add vic_set_fiq function to select if an interrupt should generate an IRQ or FIQ 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (5 preceding siblings ...) 2014-05-14 15:58 ` [RFC 6/8] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson @ 2014-05-14 15:58 ` Daniel Thompson 2014-05-14 15:58 ` [RFC 8/8] arm: fiq: Hack FIQ routing backdoors into GIC and VIC Daniel Thompson 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson 8 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman From: Arve Hjønnevåg <arve@android.com> Signed-off-by: Arve Hjønnevåg <arve@android.com> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> --- drivers/irqchip/irq-vic.c | 23 +++++++++++++++++++++++ include/linux/irqchip/arm-vic.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index 7d35287..3eaa2e4 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c @@ -337,6 +337,29 @@ static void vic_unmask_irq(struct irq_data *d) writel(1 << irq, base + VIC_INT_ENABLE); } +static DEFINE_SPINLOCK(vic_intselect_lock); +int vic_set_fiq(unsigned int irq, bool enable) +{ + u32 int_select; + u32 mask; + unsigned long irq_flags; + void __iomem *base = irq_get_chip_data(irq); + irq &= 31; + mask = 1 << irq; + + spin_lock_irqsave(&vic_intselect_lock, irq_flags); + int_select = readl(base + VIC_INT_SELECT); + if (enable) + int_select |= mask; + else + int_select &= ~mask; + writel(int_select, base + VIC_INT_SELECT); + spin_unlock_irqrestore(&vic_intselect_lock, irq_flags); + + return 0; +} +EXPORT_SYMBOL(vic_set_fiq); + #if defined(CONFIG_PM) static struct vic_device *vic_from_irq(unsigned int irq) { diff --git a/include/linux/irqchip/arm-vic.h b/include/linux/irqchip/arm-vic.h index ba46c79..61ee4c9 100644 --- a/include/linux/irqchip/arm-vic.h +++ b/include/linux/irqchip/arm-vic.h @@ -34,5 +34,6 @@ void __vic_init(void __iomem *base, int parent_irq, int irq_start, void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); int vic_init_cascaded(void __iomem *base, unsigned int parent_irq, u32 vic_sources, u32 resume_sources); +int vic_set_fiq(unsigned int irq, bool enable); #endif -- 1.9.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC 8/8] arm: fiq: Hack FIQ routing backdoors into GIC and VIC 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (6 preceding siblings ...) 2014-05-14 15:58 ` [RFC 7/8] ARM: VIC: Add vic_set_fiq function to select if an interrupt should generate an IRQ or FIQ Daniel Thompson @ 2014-05-14 15:58 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson 8 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-14 15:58 UTC (permalink / raw) To: Jason Wessel, kgdb-bugreport Cc: Mark Rutland, kernel, Frederic Weisbecker, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman This is a hack to make it easy to check that the other interfaces in the patchset make sense. It needs to be replaced by code to get the interrupt controllers to expose FIQs. Unless a better option presents itself I plan to double up each interrupt source (so we get two virqs, one for regular interrupt and one for FIQ). This is what most of the prior art around FIQ in Linux has done in the past. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> --- arch/arm/boot/dts/stih416.dtsi | 2 +- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 2 +- arch/arm/kernel/fiq.c | 39 +++++++++++++++++++++++++++++++++ drivers/irqchip/irq-gic.c | 27 +++++++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi index 78746d2..a288898 100644 --- a/arch/arm/boot/dts/stih416.dtsi +++ b/arch/arm/boot/dts/stih416.dtsi @@ -99,7 +99,7 @@ compatible = "st,asc"; status = "disabled"; reg = <0xfe531000 0x2c>; - interrupts = <0 210 0>; + interrupts = <0 210 0>, <0 210 0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sbc_serial1>; clocks = <&CLK_SYSIN>; diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi index ac870fb..fab2a40 100644 --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi @@ -140,7 +140,7 @@ v2m_serial0: uart@090000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x090000 0x1000>; - interrupts = <5>; + interrupts = <5>, <5>; clocks = <&v2m_oscclk2>, <&smbclk>; clock-names = "uartclk", "apb_pclk"; }; diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index defbe85..efce321 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -41,6 +41,7 @@ #include <linux/interrupt.h> #include <linux/seq_file.h> #include <linux/irq.h> +#include <linux/irqchip/arm-vic.h> #include <asm/cacheflush.h> #include <asm/cp15.h> @@ -130,14 +131,52 @@ void release_fiq(struct fiq_handler *f) static int fiq_start; +/* These hacks use backdoors into the interrupt controller to perform FIQ/IRQ + * routing. These hacks are nasty and completely incompatible with (working) + * multiarch kernels. Additionally these hacks don't count enable/disable + * properly... + * + * This should probably all be replaced with virtual interrupt numbers + * that the intc already knows to bind to FIQ. + */ +#ifdef CONFIG_ARCH_VERSATILE +#define USE_VIC_HACK +#else +#define USE_GIC_HACK +#endif + void enable_fiq(int fiq) { +#ifdef USE_VIC_HACK + vic_set_fiq(fiq, true); +#endif +#ifdef USE_GIC_HACK +{ + struct irq_data *irq_data = irq_get_irq_data(fiq); + + extern void gic_set_group_irq(struct irq_data *d, int group); + gic_set_group_irq(irq_data, 0); +} +#endif + enable_irq(fiq + fiq_start); } void disable_fiq(int fiq) { disable_irq(fiq + fiq_start); + +#ifdef USE_VIC_HACK + vic_set_fiq(fiq, false); +#endif +#ifdef USE_GIC_HACK +{ + struct irq_data *irq_data = irq_get_irq_data(fiq); + + extern void gic_set_group_irq(struct irq_data *d, int group); + gic_set_group_irq(irq_data, 1); +} +#endif } void eoi_fiq(int fiq) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index aa8efe4..c25632b 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -173,6 +173,33 @@ static void gic_unmask_irq(struct irq_data *d) raw_spin_unlock(&irq_controller_lock); } +/*static*/ void gic_set_group_irq(struct irq_data *d, int group) +{ + unsigned long flags; + unsigned int reg = gic_irq(d) / 32 * 4; + u32 mask = 1 << (gic_irq(d) % 32); + u32 val; + + raw_spin_lock_irqsave(&irq_controller_lock, flags); + val = readl_relaxed(gic_dist_base(d) + GIC_DIST_IGROUP + reg); + if (group) + val |= mask; + else + val &= ~mask; + writel_relaxed(val, gic_dist_base(d) + GIC_DIST_IGROUP + reg); + raw_spin_unlock_irqrestore(&irq_controller_lock, flags); +} + +/*static*/ int gic_get_group_irq(struct irq_data *d) +{ + unsigned int reg = gic_irq(d) / 32 * 4; + u32 mask = 1 << (gic_irq(d) % 32); + u32 val; + + val = readl_relaxed(gic_dist_base(d) + GIC_DIST_IGROUP + reg); + return !!(val & mask); +} + static void gic_eoi_irq(struct irq_data *d) { if (gic_arch_extn.irq_eoi) { -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v2 00/10] kgdb: NMI/FIQ support for ARM 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (7 preceding siblings ...) 2014-05-14 15:58 ` [RFC 8/8] arm: fiq: Hack FIQ routing backdoors into GIC and VIC Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson ` (10 more replies) 8 siblings, 11 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman This patchset makes it possible to use the kgdb NMI infrastructure on ARM platforms by providing a mutli-arch compatible means for drivers to manage FIQ routings. First a quick summary of how the mainline kgdb NMI infrastructure (mostly found in drivers/tty/serial/kgdb_nmi.c) works. The kgdb infrastructure will re-route the kgdb console UART's interrupt signal from IRQ to FIQ. Naturally the UART will no longer function normally and will instead be managed by kgdb using the polled I/O functions. Any character delivered to the UART causes the kgdb handler function to be called. Note that, within this patchset a serial driver explicitly consents (or not) to the abuse outlined by calling the appropriate registration during the .poll_init() callback. The patch set is structured as follows: The first six patches modify the interrupt system to make it easier to describe FIQ. The key concept is that a call to enable_fiq() must modify the IRQ/FIQ routing to that the FIQ really is enabled (rather than spuriously delivering the signal on the IRQ). To achieve this each interrupt controller registers two virqs for each hwirq (allowing IRQ and FIQ to be readily distinguished). The next two patches (7 and 8) provide kgdb with a FIQ handler and a means for serial drivers to register their FIQ with kgdb. Finally two example serial drivers are modified in order to register their FIQs with kgdb. Major remaining TODO item is to modify the code to halt the other CPUs; at present this code sends IPIs (which use a normal IRQ) and busy waits for the other CPUs to halt. This means the benefits of invoking the debugger via NMI are not support realized on SMP systems. However I plan to tackle that later (i.e. when there's some consensus on whether this approach is the right way to handle FIQ). Changes since v1: * Fully fledged multi-arch support. * Tested for correct FIQ operation on STiH416/B2020 (Cortex A9), qemu/versatile and qemu/vexpress-a15 (with self-written mods to the GIC model to support FIQ). * Regression tested (and resulting bugs fixed) on qemu/versatile+DT and qemu/integreatorcp. Anton Vorontsov (2): ARM: Move some macros from entry-armv to entry-header ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson (8): arm: fiq: Allow EOI to be communicated to the intc irqchip: gic: Provide support for interrupt grouping irqchip: gic: Introduce shadow irqs for FIQ ARM: vexpress: Extend UART with FIQ support ARM: STi: STiH41x: Extend UART with FIQ support. irqchip: vic: Introduce shadow irqs for FIQ serial: amba-pl011: Pass on FIQ information to KGDB. serial: asc: Add support for KGDB's FIQ/NMI mode arch/arm/Kconfig | 2 + arch/arm/Kconfig.debug | 18 +++ arch/arm/boot/dts/stih415.dtsi | 4 +- arch/arm/boot/dts/stih416.dtsi | 4 +- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 8 +- arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | 10 +- arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 8 +- arch/arm/boot/dts/vexpress-v2p-ca5s.dts | 10 +- arch/arm/include/asm/fiq.h | 1 + arch/arm/include/asm/kgdb.h | 7 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/entry-armv.S | 151 +------------------------ arch/arm/kernel/entry-header.S | 164 ++++++++++++++++++++++++++++ arch/arm/kernel/fiq.c | 11 ++ arch/arm/kernel/kgdb_fiq.c | 117 ++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++ arch/arm/mach-ep93xx/core.c | 6 +- arch/arm/mach-netx/generic.c | 3 +- arch/arm/mach-s3c64xx/common.c | 6 +- arch/arm/mach-versatile/core.c | 9 +- arch/arm/mach-versatile/include/mach/irqs.h | 76 ++++++------- arch/arm/plat-samsung/s5p-irq.c | 3 +- drivers/irqchip/irq-gic.c | 81 ++++++++++++-- drivers/irqchip/irq-vic.c | 87 ++++++++++++--- drivers/tty/serial/amba-pl011.c | 101 ++++++++++------- drivers/tty/serial/st-asc.c | 27 +++++ include/linux/irqchip/arm-gic.h | 3 + include/linux/irqchip/arm-vic.h | 8 +- 28 files changed, 733 insertions(+), 280 deletions(-) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S -- 1.9.0 ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 14:59 ` Srinivas Kandagatla 2014-05-23 15:00 ` Russell King - ARM Linux 2014-05-23 13:57 ` [RFC v2 02/10] irqchip: gic: Provide support for interrupt grouping Daniel Thompson ` (9 subsequent siblings) 10 siblings, 2 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel Modern ARM systems require an EOI to be sent to the interrupt controller on completion of both IRQ and FIQ. The FIQ code currently does not provide any API to perform this. This patch provides this API, implemented by hooking into main irq driver in a similar way to the existing enable_fiq()/disable_fiq(). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Fabio Estevam <festevam@gmail.com> Cc: Nicolas Pitre <nico@linaro.org> --- arch/arm/include/asm/fiq.h | 1 + arch/arm/kernel/fiq.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h index d493d0b..5a2a9b9 100644 --- a/arch/arm/include/asm/fiq.h +++ b/arch/arm/include/asm/fiq.h @@ -38,6 +38,7 @@ extern void release_fiq(struct fiq_handler *f); extern void set_fiq_handler(void *start, unsigned int length); extern void enable_fiq(int fiq); extern void disable_fiq(int fiq); +extern void eoi_fiq(int fiq); /* helpers defined in fiqasm.S: */ extern void __set_fiq_regs(unsigned long const *regs); diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 918875d..defbe85 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -40,6 +40,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/seq_file.h> +#include <linux/irq.h> #include <asm/cacheflush.h> #include <asm/cp15.h> @@ -139,6 +140,15 @@ void disable_fiq(int fiq) disable_irq(fiq + fiq_start); } +void eoi_fiq(int fiq) +{ + struct irq_data *irq_data = irq_get_irq_data(fiq + fiq_start); + struct irq_chip *chip = irq_data_get_irq_chip(irq_data); + + if (chip->irq_eoi) + chip->irq_eoi(irq_data); +} + EXPORT_SYMBOL(set_fiq_handler); EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ @@ -146,6 +156,7 @@ EXPORT_SYMBOL(claim_fiq); EXPORT_SYMBOL(release_fiq); EXPORT_SYMBOL(enable_fiq); EXPORT_SYMBOL(disable_fiq); +EXPORT_SYMBOL(eoi_fiq); void __init init_FIQ(int start) { -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc 2014-05-23 13:57 ` [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson @ 2014-05-23 14:59 ` Srinivas Kandagatla 2014-05-23 15:00 ` Russell King - ARM Linux 1 sibling, 0 replies; 68+ messages in thread From: Srinivas Kandagatla @ 2014-05-23 14:59 UTC (permalink / raw) To: Daniel Thompson, Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Fabio Estevam, Dirk Behme, Russell King, Nicolas Pitre, Jiri Slaby, patches, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Colin Cross, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman On 23/05/14 14:57, Daniel Thompson wrote: > + > + if (chip->irq_eoi) > + chip->irq_eoi(irq_data); > +} > + Looks like an extra tab here.. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc 2014-05-23 13:57 ` [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson 2014-05-23 14:59 ` Srinivas Kandagatla @ 2014-05-23 15:00 ` Russell King - ARM Linux 2014-05-28 15:47 ` Daniel Thompson 1 sibling, 1 reply; 68+ messages in thread From: Russell King - ARM Linux @ 2014-05-23 15:00 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, Catalin Marinas, Linus Walleij, Jiri Slaby, Dirk Behme, Nicolas Pitre, Fabio Estevam, patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial, kgdb-bugreport, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman On Fri, May 23, 2014 at 02:57:49PM +0100, Daniel Thompson wrote: > +void eoi_fiq(int fiq) > +{ > + struct irq_data *irq_data = irq_get_irq_data(fiq + fiq_start); > + struct irq_chip *chip = irq_data_get_irq_chip(irq_data); > + > + if (chip->irq_eoi) > + chip->irq_eoi(irq_data); > +} So what if the IRQ chip takes a spinlock? You can't take spinlocks in FIQ context... Who checks for that kind of stuff - just hoping that the IRQ driver doesn't take a spinlock sounds real fragile. -- FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc 2014-05-23 15:00 ` Russell King - ARM Linux @ 2014-05-28 15:47 ` Daniel Thompson 0 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-28 15:47 UTC (permalink / raw) To: Russell King - ARM Linux Cc: Mark Rutland, kernel, Catalin Marinas, Linus Walleij, Jiri Slaby, Dirk Behme, Nicolas Pitre, Fabio Estevam, patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial, kgdb-bugreport, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman On 23/05/14 16:00, Russell King - ARM Linux wrote: > On Fri, May 23, 2014 at 02:57:49PM +0100, Daniel Thompson wrote: >> +void eoi_fiq(int fiq) >> +{ >> + struct irq_data *irq_data = irq_get_irq_data(fiq + fiq_start); >> + struct irq_chip *chip = irq_data_get_irq_chip(irq_data); >> + >> + if (chip->irq_eoi) >> + chip->irq_eoi(irq_data); >> +} > > So what if the IRQ chip takes a spinlock? You can't take spinlocks in > FIQ context... Who checks for that kind of stuff - just hoping that > the IRQ driver doesn't take a spinlock sounds real fragile. I'll certainly do a better code review before pushing on. I certainly did overlook a spinlock in the GIC code which (I think) is actually reachable on a Tegra platform. I'll have to do something about that. I've spent a bit of time this week seeing whether lock dep can be provoked into triggering if it sees a spin lock in this code but that isn't turning out very well (it needs CONFIG_LOCKDEP_DEBUG, relies on lockdep believing the FIQ handling state isn't a hardirq and still doesn't work properly). Fortunately architectures using EOI appear to be pretty rare (I count five in drivers/irqchip/ and three in arch/arm/) so traditional code review and yelling might be sufficient. Daniel. ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC v2 02/10] irqchip: gic: Provide support for interrupt grouping 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-05-23 13:57 ` [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 03/10] irqchip: gic: Introduce shadow irqs for FIQ Daniel Thompson ` (8 subsequent siblings) 10 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, Nicolas Pitre, kernel, kgdb-bugreport, Linus Walleij, Sricharan R, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz All GIC hardware except GICv1 without TrustZone support provides a means to group exceptions into group 0 (which can optionally be signally using use FIQ) and group 1. The kernel currently provides no means to exploit this. This patch alters the initialization of the GIC to place all interrupts into group 1, this is a foundational requirement to meaningfully use FIQ. Note that 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". This allows grouping to be used to allow hardware peripherals to send interrupts into the secure world. On systems without TrustZone support the kernel has the power to route interrupt sources to FIQ, potentially allowing a driver to exploit the NMI-like properties of FIQ. The registers involved are RAZ/WI when unimplemented or protected by security policy. This patch therefore applies grouping unconditionally. Tested on a qemu GICv2 model (self-written from GICv2 spec) and an STiH416 (ARM Cortex A9, GICv1, TZ). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Christoffer Dall <christoffer.dall@linaro.org> Cc: Sricharan R <r.sricharan@ti.com> Acked-by: Dirk Behme <dirk.behme@de.bosch.com> --- drivers/irqchip/irq-gic.c | 35 ++++++++++++++++++++++++++++++----- include/linux/irqchip/arm-gic.h | 3 +++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 57d165e..aa8efe4 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -408,13 +408,27 @@ static void __init gic_dist_init(struct gic_chip_data *gic) writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); /* + * Set all global interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers a read-as-zero/write-ignored. + */ + for (i = 32; i < gic_irqs; i += 32) + writel_relaxed(0xffffffff, base + GIC_DIST_IGROUP + i * 4 / 32); + + /* * Disable all interrupts. Leave the PPI and SGIs alone * as these enables are banked registers. */ for (i = 32; i < gic_irqs; i += 32) writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); - writel_relaxed(1, base + GIC_DIST_CTRL); + /* + * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only, + * bit 1 ignored) + */ + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | + GIC_DIST_CTRL_ENABLE_GRP1_BIT, base + GIC_DIST_CTRL); } static void gic_cpu_init(struct gic_chip_data *gic) @@ -452,8 +466,16 @@ static void gic_cpu_init(struct gic_chip_data *gic) for (i = 0; i < 32; i += 4) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4); + /* + * Set all PPI and SGI interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers are read-as-zero/write-ignored. + */ + writel_relaxed(0xffffffff, dist_base + GIC_DIST_IGROUP + 0); + writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); - writel_relaxed(1, base + GIC_CPU_CTRL); + writel_relaxed(0x1f, base + GIC_CPU_CTRL); } void gic_cpu_if_down(void) @@ -537,7 +559,9 @@ 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(1, dist_base + GIC_DIST_CTRL); + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | + GIC_DIST_CTRL_ENABLE_GRP1_BIT, + dist_base + GIC_DIST_CTRL); } static void gic_cpu_save(unsigned int gic_nr) @@ -594,7 +618,7 @@ static void gic_cpu_restore(unsigned int gic_nr) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); - writel_relaxed(1, cpu_base + GIC_CPU_CTRL); + writel_relaxed(0x1f, cpu_base + GIC_CPU_CTRL); } static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) @@ -670,7 +694,8 @@ 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); + writel_relaxed(map << 16 | irq | 0x8000, + gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); raw_spin_unlock_irqrestore(&irq_controller_lock, flags); } diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 7ed92d0..919502f 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -37,6 +37,9 @@ #define GIC_DIST_SGI_PENDING_CLEAR 0xf10 #define GIC_DIST_SGI_PENDING_SET 0xf20 +#define GIC_DIST_CTRL_ENABLE_GRP0_BIT (1 << 0) +#define GIC_DIST_CTRL_ENABLE_GRP1_BIT (1 << 1) + #define GICH_HCR 0x0 #define GICH_VTR 0x4 #define GICH_VMCR 0x8 -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v2 03/10] irqchip: gic: Introduce shadow irqs for FIQ 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-05-23 13:57 ` [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson 2014-05-23 13:57 ` [RFC v2 02/10] irqchip: gic: Provide support for interrupt grouping Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support Daniel Thompson ` (7 subsequent siblings) 10 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, Nicolas Pitre, kernel, kgdb-bugreport, Linus Walleij, Sricharan R, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz This patch registers two virqs for each interrupt source it supports. Using multiple virqs allows the GIC driver to automatically modify the group register, allowing the new virqs to be used as argument to enable_fiq(). This also allows FIQ resources to be described in the device tree's interrupt list using a special flag (currently 0x80). Both these aspects combine and allow a driver to deploy a FIQ handler without any machine specific knowledge; it can be used effectively on multi-arch kernels. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc:: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Christoffer Dall <christoffer.dall@linaro.org> Cc: Sricharan R <r.sricharan@ti.com> --- drivers/irqchip/irq-gic.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index aa8efe4..0c259ac 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -48,6 +48,8 @@ #include "irqchip.h" +#define GIC_INTSPEC_IRQ_IS_FIQ (1 << 7) + union gic_base { void __iomem *common_base; void __percpu * __iomem *percpu_base; @@ -65,6 +67,7 @@ struct gic_chip_data { #endif struct irq_domain *domain; unsigned int gic_irqs; + unsigned int fiq_shadow_offset; #ifdef CONFIG_GIC_NON_BANKED void __iomem *(*get_base)(union gic_base *); #endif @@ -143,11 +146,34 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d) return gic_data_cpu_base(gic_data); } +static inline bool gic_is_fiq(struct irq_data *d) +{ + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); + return d->hwirq > gic_data->gic_irqs; +} + static inline unsigned int gic_irq(struct irq_data *d) { + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); + if (gic_is_fiq(d)) + return d->hwirq - gic_data->fiq_shadow_offset; return d->hwirq; } +static void gic_set_group_irq(struct irq_data *d, int group) +{ + unsigned int reg = gic_irq(d) / 32 * 4; + u32 mask = 1 << (gic_irq(d) % 32); + u32 val; + + val = readl_relaxed(gic_dist_base(d) + GIC_DIST_IGROUP + reg); + if (group) + val |= mask; + else + val &= ~mask; + writel_relaxed(val, gic_dist_base(d) + GIC_DIST_IGROUP + reg); +} + /* * Routines to acknowledge, disable and enable interrupts */ @@ -159,6 +185,8 @@ static void gic_mask_irq(struct irq_data *d) writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); if (gic_arch_extn.irq_mask) gic_arch_extn.irq_mask(d); + if (gic_is_fiq(d)) + gic_set_group_irq(d, 1); raw_spin_unlock(&irq_controller_lock); } @@ -167,6 +195,8 @@ static void gic_unmask_irq(struct irq_data *d) u32 mask = 1 << (gic_irq(d) % 32); raw_spin_lock(&irq_controller_lock); + if (gic_is_fiq(d)) + gic_set_group_irq(d, 0); if (gic_arch_extn.irq_unmask) gic_arch_extn.irq_unmask(d); writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); @@ -940,7 +970,12 @@ static int gic_routable_irq_domain_xlate(struct irq_domain *d, unsigned long *out_hwirq, unsigned int *out_type) { + struct gic_chip_data *gic_data = d->host_data; *out_hwirq += 16; + + if (intspec[2] & GIC_INTSPEC_IRQ_IS_FIQ) + *out_hwirq += gic_data->fiq_shadow_offset; + return 0; } @@ -1026,10 +1061,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, gic->gic_irqs = gic_irqs; gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ + gic->fiq_shadow_offset = gic_irqs; if (of_property_read_u32(node, "arm,routable-irqs", &nr_routable_irqs)) { - irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, + irq_base = irq_alloc_descs(irq_start, 16, 2 * gic_irqs, numa_node_id()); if (IS_ERR_VALUE(irq_base)) { WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", @@ -1037,12 +1073,12 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, irq_base = irq_start; } - gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, - hwirq_base, &gic_irq_domain_ops, gic); + gic->domain = + irq_domain_add_legacy(node, 2 * gic_irqs, irq_base, + hwirq_base, &gic_irq_domain_ops, gic); } else { gic->domain = irq_domain_add_linear(node, nr_routable_irqs, - &gic_irq_domain_ops, - gic); + &gic_irq_domain_ops, gic); } if (WARN_ON(!gic->domain)) -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (2 preceding siblings ...) 2014-05-23 13:57 ` [RFC v2 03/10] irqchip: gic: Introduce shadow irqs for FIQ Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 15:04 ` Russell King - ARM Linux 2014-05-23 13:57 ` [RFC v2 05/10] ARM: STi: STiH41x: " Daniel Thompson ` (6 subsequent siblings) 10 siblings, 1 reply; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman This patch provides the UART with a second interrupt resource that can be used to route the UARTs interrupt to FIQ. The size of the interrupt map is doubled and new mappings for the FIQ shadows added (demarked by setting bit 7 in the final item in the tuple). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Rob Herring <robh+dt@kernel.org> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk> Cc: Kumar Gala <galak@codeaurora.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: devicetree@vger.kernel.org --- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 8 ++++---- arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | 10 ++++++++-- arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 8 +++++++- arch/arm/boot/dts/vexpress-v2p-ca5s.dts | 10 ++++++++-- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi index ac870fb..e86936c 100644 --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi @@ -140,7 +140,7 @@ v2m_serial0: uart@090000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x090000 0x1000>; - interrupts = <5>; + interrupts = <5>, <69>; clocks = <&v2m_oscclk2>, <&smbclk>; clock-names = "uartclk", "apb_pclk"; }; @@ -148,7 +148,7 @@ v2m_serial1: uart@0a0000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x0a0000 0x1000>; - interrupts = <6>; + interrupts = <6>, <70>; clocks = <&v2m_oscclk2>, <&smbclk>; clock-names = "uartclk", "apb_pclk"; }; @@ -156,7 +156,7 @@ v2m_serial2: uart@0b0000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x0b0000 0x1000>; - interrupts = <7>; + interrupts = <7>, <71>; clocks = <&v2m_oscclk2>, <&smbclk>; clock-names = "uartclk", "apb_pclk"; }; @@ -164,7 +164,7 @@ v2m_serial3: uart@0c0000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x0c0000 0x1000>; - interrupts = <8>; + interrupts = <8>, <72>; clocks = <&v2m_oscclk2>, <&smbclk>; clock-names = "uartclk", "apb_pclk"; }; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts index 9420053..9c489fa 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts @@ -233,7 +233,7 @@ <5 0 0 0x10000000 0x04000000>; #interrupt-cells = <1>; - interrupt-map-mask = <0 0 63>; + interrupt-map-mask = <0 0 127>; interrupt-map = <0 0 0 &gic 0 0 4>, <0 0 1 &gic 0 1 4>, <0 0 2 &gic 0 2 4>, @@ -276,7 +276,13 @@ <0 0 39 &gic 0 39 4>, <0 0 40 &gic 0 40 4>, <0 0 41 &gic 0 41 4>, - <0 0 42 &gic 0 42 4>; + <0 0 42 &gic 0 42 4>, + + /* FIQ shadow routings */ + <0 0 69 &gic 0 5 0x84>, + <0 0 70 &gic 0 6 0x84>, + <0 0 71 &gic 0 7 0x84>, + <0 0 72 &gic 0 8 0x84>; /include/ "vexpress-v2m-rs1.dtsi" }; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 15f98cb..75821d2 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -390,7 +390,13 @@ <0 0 39 &gic 0 39 4>, <0 0 40 &gic 0 40 4>, <0 0 41 &gic 0 41 4>, - <0 0 42 &gic 0 42 4>; + <0 0 42 &gic 0 42 4>, + + /* FIQ shadow routings */ + <0 0 69 &gic 0 5 0x84>, + <0 0 70 &gic 0 6 0x84>, + <0 0 71 &gic 0 7 0x84>, + <0 0 72 &gic 0 8 0x84>; /include/ "vexpress-v2m-rs1.dtsi" }; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts index c544a55..930e2ef 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts @@ -195,7 +195,7 @@ <5 0 0x10000000 0x04000000>; #interrupt-cells = <1>; - interrupt-map-mask = <0 0 63>; + interrupt-map-mask = <0 0 127>; interrupt-map = <0 0 0 &gic 0 0 4>, <0 0 1 &gic 0 1 4>, <0 0 2 &gic 0 2 4>, @@ -238,7 +238,13 @@ <0 0 39 &gic 0 39 4>, <0 0 40 &gic 0 40 4>, <0 0 41 &gic 0 41 4>, - <0 0 42 &gic 0 42 4>; + <0 0 42 &gic 0 42 4>, + + /* FIQ shadow routings */ + <0 0 69 &gic 0 5 0x84>, + <0 0 70 &gic 0 6 0x84>, + <0 0 71 &gic 0 7 0x84>, + <0 0 72 &gic 0 8 0x84>; /include/ "vexpress-v2m-rs1.dtsi" }; -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support 2014-05-23 13:57 ` [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support Daniel Thompson @ 2014-05-23 15:04 ` Russell King - ARM Linux 2014-05-29 10:31 ` Daniel Thompson 0 siblings, 1 reply; 68+ messages in thread From: Russell King - ARM Linux @ 2014-05-23 15:04 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, Catalin Marinas, Linus Walleij, Jiri Slaby, Dirk Behme, Nicolas Pitre, patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial, kgdb-bugreport, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman, linux-kernel On Fri, May 23, 2014 at 02:57:52PM +0100, Daniel Thompson wrote: > @@ -140,7 +140,7 @@ > v2m_serial0: uart@090000 { > compatible = "arm,pl011", "arm,primecell"; > reg = <0x090000 0x1000>; > - interrupts = <5>; > + interrupts = <5>, <69>; NAK. This is obviously a Linux implementation detail - the second number is your "FIQ" number which you've decided will be offset by 64. -- FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support 2014-05-23 15:04 ` Russell King - ARM Linux @ 2014-05-29 10:31 ` Daniel Thompson 2014-05-29 13:44 ` Rob Herring 0 siblings, 1 reply; 68+ messages in thread From: Daniel Thompson @ 2014-05-29 10:31 UTC (permalink / raw) To: Russell King - ARM Linux Cc: Mark Rutland, kernel, Catalin Marinas, Linus Walleij, Jiri Slaby, Dirk Behme, Nicolas Pitre, patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial, kgdb-bugreport, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman, linux-kernel On 23/05/14 16:04, Russell King - ARM Linux wrote: > On Fri, May 23, 2014 at 02:57:52PM +0100, Daniel Thompson wrote: >> @@ -140,7 +140,7 @@ >> v2m_serial0: uart@090000 { >> compatible = "arm,pl011", "arm,primecell"; >> reg = <0x090000 0x1000>; >> - interrupts = <5>; >> + interrupts = <5>, <69>; > > NAK. This is obviously a Linux implementation detail - the second > number is your "FIQ" number which you've decided will be offset by > 64. Certainly the offset of 64 is a more or less meaningless magic number that I decided on, however I don't think it originates within Linux. It is both introduced and consumed within the device tree itself. I've proposed adding a flag to the gic bindings to mark a FIQ; the GIC calls interrupt 69 (above) <0 5 0x84> (where 0x80 is the flag to request FIQ routing alongside 0x04 which is the trigger type). However vexpress-a15 has an interrupt-map between the UART and the GIC. Thus far I've not found a way, other by offset, to allow a UART sitting on a child bus to be provided with both IRQ and FIQ versions of an interrupt. > --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts > +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts > @@ -233,7 +233,7 @@ > <5 0 0 0x10000000 0x04000000>; > > #interrupt-cells = <1>; > - interrupt-map-mask = <0 0 63>; > + interrupt-map-mask = <0 0 127>; ^^^^^ The 64 offset is introduced here. Nothing in Linux imposes anything on the value (I originally had the shadow routings from 59 to 63 and this also worked). My code may still be inappropriate but, right now, I'm unsure whether the proposed changes to the gic bindings are included in the NAK, not in the NAK or whether they sit in the middle ground where I have to provide better argumentation. Daniel. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support 2014-05-29 10:31 ` Daniel Thompson @ 2014-05-29 13:44 ` Rob Herring 2014-06-03 12:41 ` Daniel Thompson 0 siblings, 1 reply; 68+ messages in thread From: Rob Herring @ 2014-05-29 13:44 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Dirk Behme, Russell King - ARM Linux, Nicolas Pitre, Linaro Patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial@vger.kernel.org, Catalin Marinas, kernel-team, devicetree@vger.kernel.org, linaro-kernel@lists.linaro.org, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz <john.stultz> On Thu, May 29, 2014 at 5:31 AM, Daniel Thompson <daniel.thompson@linaro.org> wrote: > On 23/05/14 16:04, Russell King - ARM Linux wrote: >> On Fri, May 23, 2014 at 02:57:52PM +0100, Daniel Thompson wrote: >>> @@ -140,7 +140,7 @@ >>> v2m_serial0: uart@090000 { >>> compatible = "arm,pl011", "arm,primecell"; >>> reg = <0x090000 0x1000>; >>> - interrupts = <5>; >>> + interrupts = <5>, <69>; >> >> NAK. This is obviously a Linux implementation detail - the second >> number is your "FIQ" number which you've decided will be offset by >> 64. +1 > Certainly the offset of 64 is a more or less meaningless magic number > that I decided on, however I don't think it originates within Linux. It > is both introduced and consumed within the device tree itself. > > I've proposed adding a flag to the gic bindings to mark a FIQ; the GIC > calls interrupt 69 (above) <0 5 0x84> (where 0x80 is the flag to request > FIQ routing alongside 0x04 which is the trigger type). That would be better than the magic number, but I'm not convinced that belongs in the DT either. Whether the uart uses FIQ is not dependent on this DT setting, but based on whether the user wants to use the uart for kdb or not. You have enough information already to figure out which interrupt. What's missing is whether you have the capability to use FIQ or not. I don't recall if you can tell that from the GIC or not. Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support 2014-05-29 13:44 ` Rob Herring @ 2014-06-03 12:41 ` Daniel Thompson 0 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-03 12:41 UTC (permalink / raw) To: Rob Herring Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Dirk Behme, Russell King - ARM Linux, Nicolas Pitre, Linaro Patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial@vger.kernel.org, Catalin Marinas, kernel-team, devicetree@vger.kernel.org, linaro-kernel@lists.linaro.org, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz <john.stultz> On 29/05/14 14:44, Rob Herring wrote: > On Thu, May 29, 2014 at 5:31 AM, Daniel Thompson > <daniel.thompson@linaro.org> wrote: >> On 23/05/14 16:04, Russell King - ARM Linux wrote: >>> On Fri, May 23, 2014 at 02:57:52PM +0100, Daniel Thompson wrote: >>>> @@ -140,7 +140,7 @@ >>>> v2m_serial0: uart@090000 { >>>> compatible = "arm,pl011", "arm,primecell"; >>>> reg = <0x090000 0x1000>; >>>> - interrupts = <5>; >>>> + interrupts = <5>, <69>; >>> >>> NAK. This is obviously a Linux implementation detail - the second >>> number is your "FIQ" number which you've decided will be offset by >>> 64. > > +1 > >> Certainly the offset of 64 is a more or less meaningless magic number >> that I decided on, however I don't think it originates within Linux. It >> is both introduced and consumed within the device tree itself. >> >> I've proposed adding a flag to the gic bindings to mark a FIQ; the GIC >> calls interrupt 69 (above) <0 5 0x84> (where 0x80 is the flag to request >> FIQ routing alongside 0x04 which is the trigger type). > > That would be better than the magic number, but I'm not convinced that > belongs in the DT either. > > Whether the uart uses FIQ is not dependent on this DT setting, but > based on whether the user wants to use the uart for kdb or not. You > have enough information already to figure out which interrupt. What's > missing is whether you have the capability to use FIQ or not. I don't > recall if you can tell that from the GIC or not. Ok. I've just started playing with an idea that keeps the shadow virqw for FIQ idea but doesn't require any device tree changes... Another RFC will follow in due course. Daniel. ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC v2 05/10] ARM: STi: STiH41x: Extend UART with FIQ support. 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (3 preceding siblings ...) 2014-05-23 13:57 ` [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 06/10] irqchip: vic: Introduce shadow irqs for FIQ Daniel Thompson ` (5 subsequent siblings) 10 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Patrice Chotard, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel This patch provides the UART with a second interrupt resource that can be used to route the UARTs interrupt to FIQ (demarked by setting bit 7 in the third item in the tuple). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> Cc: Maxime Coquelin <maxime.coquelin@st.com> Cc: Patrice Chotard <patrice.chotard@st.com> Cc: Rob Herring <robh+dt@kernel.org> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk> Cc: Kumar Gala <galak@codeaurora.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: kernel@stlinux.com Cc: devicetree@vger.kernel.org --- arch/arm/boot/dts/stih415.dtsi | 4 ++-- arch/arm/boot/dts/stih416.dtsi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi index d89064c..b2c9df4 100644 --- a/arch/arm/boot/dts/stih415.dtsi +++ b/arch/arm/boot/dts/stih415.dtsi @@ -79,7 +79,7 @@ compatible = "st,asc"; status = "disabled"; reg = <0xfed32000 0x2c>; - interrupts = <0 197 0>; + interrupts = <0 197 0>, <0 197 0x80>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_serial2>; clocks = <&CLKS_ICN_REG_0>; @@ -90,7 +90,7 @@ compatible = "st,asc"; status = "disabled"; reg = <0xfe531000 0x2c>; - interrupts = <0 210 0>; + interrupts = <0 210 0>, <0 197 0x80>; clocks = <&CLK_SYSIN>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sbc_serial1>; diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi index 78746d2..fdf7b43 100644 --- a/arch/arm/boot/dts/stih416.dtsi +++ b/arch/arm/boot/dts/stih416.dtsi @@ -88,7 +88,7 @@ compatible = "st,asc"; status = "disabled"; reg = <0xfed32000 0x2c>; - interrupts = <0 197 0>; + interrupts = <0 197 0>, <0 210 0x80>; clocks = <&CLK_S_ICN_REG_0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_serial2 &pinctrl_serial2_oe>; @@ -99,7 +99,7 @@ compatible = "st,asc"; status = "disabled"; reg = <0xfe531000 0x2c>; - interrupts = <0 210 0>; + interrupts = <0 210 0>, <0 210 0x80>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sbc_serial1>; clocks = <&CLK_SYSIN>; -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v2 06/10] irqchip: vic: Introduce shadow irqs for FIQ 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (4 preceding siblings ...) 2014-05-23 13:57 ` [RFC v2 05/10] ARM: STi: STiH41x: " Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 07/10] ARM: Move some macros from entry-armv to entry-header Daniel Thompson ` (4 subsequent siblings) 10 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Kukjin Kim, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, linux-samsung-soc, Ben Currently on the ARM Versatile machine both FIQ and IRQ signals share the same irq number. The effect of this is that enable_fiq() will enable an interrupt but will leave it routed to IRQ. This requires a driver utilizing FIQ to employ machine specific knowledge (i.e. that the machine has a VIC). By introducing shadow irqs to describe FIQs the VIC driver is able to update the routing automatically during enable_fiq()/disable_fiq(). Changes to the vic_init() API allow individual machines to choose where to fit the shadow irqs in the interrupt map and also to choose not to have shadows at all. This patch introduces shadows for mach-versatile whilst mach-ep93xx, mach-netx, mach-s3c64xx and plat-samsung retain unmodified interrupt maps. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ryan Mallon <rmallon@gmail.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Ben Dooks <ben-linux@fluff.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: linux-samsung-soc@vger.kernel.org --- arch/arm/mach-ep93xx/core.c | 6 +- arch/arm/mach-netx/generic.c | 3 +- arch/arm/mach-s3c64xx/common.c | 6 +- arch/arm/mach-versatile/core.c | 9 +-- arch/arm/mach-versatile/include/mach/irqs.h | 76 ++++++++++++------------- arch/arm/plat-samsung/s5p-irq.c | 3 +- drivers/irqchip/irq-vic.c | 87 +++++++++++++++++++++++------ include/linux/irqchip/arm-vic.h | 8 ++- 8 files changed, 132 insertions(+), 66 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 0e571f1..aa26411 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -185,8 +185,10 @@ void __init ep93xx_timer_init(void) *************************************************************************/ void __init ep93xx_init_irq(void) { - vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); - vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); + vic_init(EP93XX_VIC1_BASE, 0, VIC_FIQ_START_NONE, + EP93XX_VIC1_VALID_IRQ_MASK, 0); + vic_init(EP93XX_VIC2_BASE, 32, VIC_FIQ_START_NONE, + EP93XX_VIC2_VALID_IRQ_MASK, 0); } diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index db25b0c..5398dcd 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -169,7 +169,8 @@ void __init netx_init_irq(void) { int irq; - vic_init(io_p2v(NETX_PA_VIC), NETX_IRQ_VIC_START, ~0, 0); + vic_init(io_p2v(NETX_PA_VIC), NETX_IRQ_VIC_START, VIC_FIQ_START_NONE, + ~0, 0); for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { irq_set_chip_and_handler(irq, &netx_hif_chip, diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c index 5c45aae..b98dd48 100644 --- a/arch/arm/mach-s3c64xx/common.c +++ b/arch/arm/mach-s3c64xx/common.c @@ -242,8 +242,10 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); /* initialise the pair of VICs */ - vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME); - vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME); + vic_init(VA_VIC0, IRQ_VIC0_BASE, VIC_FIQ_START_NONE, vic0_valid, + IRQ_VIC0_RESUME); + vic_init(VA_VIC1, IRQ_VIC1_BASE, VIC_FIQ_START_NONE, vic1_valid, + IRQ_VIC1_RESUME); } #define eint_offset(irq) ((irq) - IRQ_EINT(0)) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index f2c89fb..3444ca8 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -108,7 +108,8 @@ void __init versatile_init_irq(void) np = of_find_matching_node_by_address(NULL, vic_of_match, VERSATILE_VIC_BASE); - __vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, ~0, 0, np); + __vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, + np ? -1 : FIQ_VIC_START, ~0, 0, np); writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); @@ -614,9 +615,9 @@ static struct pl022_ssp_controller ssp0_plat_data = { * These devices are connected via the DMA APB bridge */ #define SCI_IRQ { IRQ_SCIINT } -#define UART0_IRQ { IRQ_UARTINT0 } -#define UART1_IRQ { IRQ_UARTINT1 } -#define UART2_IRQ { IRQ_UARTINT2 } +#define UART0_IRQ { IRQ_UARTINT0, FIQ_UARTINT0 } +#define UART1_IRQ { IRQ_UARTINT1, FIQ_UARTINT1 } +#define UART2_IRQ { IRQ_UARTINT2, FIQ_UARTINT2 } #define SSP_IRQ { IRQ_SSPINT } /* FPGA Primecells */ diff --git a/arch/arm/mach-versatile/include/mach/irqs.h b/arch/arm/mach-versatile/include/mach/irqs.h index 0fd771c..da3f919 100644 --- a/arch/arm/mach-versatile/include/mach/irqs.h +++ b/arch/arm/mach-versatile/include/mach/irqs.h @@ -60,43 +60,6 @@ #define IRQ_VICSOURCE31 (IRQ_VIC_START + INT_VICSOURCE31) #define IRQ_VIC_END (IRQ_VIC_START + 31) -/* - * FIQ interrupts definitions are the same as the INT definitions. - */ -#define FIQ_WDOGINT INT_WDOGINT -#define FIQ_SOFTINT INT_SOFTINT -#define FIQ_COMMRx INT_COMMRx -#define FIQ_COMMTx INT_COMMTx -#define FIQ_TIMERINT0_1 INT_TIMERINT0_1 -#define FIQ_TIMERINT2_3 INT_TIMERINT2_3 -#define FIQ_GPIOINT0 INT_GPIOINT0 -#define FIQ_GPIOINT1 INT_GPIOINT1 -#define FIQ_GPIOINT2 INT_GPIOINT2 -#define FIQ_GPIOINT3 INT_GPIOINT3 -#define FIQ_RTCINT INT_RTCINT -#define FIQ_SSPINT INT_SSPINT -#define FIQ_UARTINT0 INT_UARTINT0 -#define FIQ_UARTINT1 INT_UARTINT1 -#define FIQ_UARTINT2 INT_UARTINT2 -#define FIQ_SCIINT INT_SCIINT -#define FIQ_CLCDINT INT_CLCDINT -#define FIQ_DMAINT INT_DMAINT -#define FIQ_PWRFAILINT INT_PWRFAILINT -#define FIQ_MBXINT INT_MBXINT -#define FIQ_GNDINT INT_GNDINT -#define FIQ_VICSOURCE21 INT_VICSOURCE21 -#define FIQ_VICSOURCE22 INT_VICSOURCE22 -#define FIQ_VICSOURCE23 INT_VICSOURCE23 -#define FIQ_VICSOURCE24 INT_VICSOURCE24 -#define FIQ_VICSOURCE25 INT_VICSOURCE25 -#define FIQ_VICSOURCE26 INT_VICSOURCE26 -#define FIQ_VICSOURCE27 INT_VICSOURCE27 -#define FIQ_VICSOURCE28 INT_VICSOURCE28 -#define FIQ_VICSOURCE29 INT_VICSOURCE29 -#define FIQ_VICSOURCE30 INT_VICSOURCE30 -#define FIQ_VICSOURCE31 INT_VICSOURCE31 - - /* * Secondary interrupt controller */ @@ -131,4 +94,41 @@ #define IRQ_GPIO3_START (IRQ_GPIO2_END + 1) #define IRQ_GPIO3_END (IRQ_GPIO3_START + 31) -#define NR_IRQS (IRQ_GPIO3_END + 1) +/* + * FIQ interrupts definitions shadow the VIC INT definitions. + */ +#define FIQ_VIC_START (IRQ_GPIO3_END + 1) +#define FIQ_WDOGINT (INT_WDOGINT + FIQ_VIC_START) +#define FIQ_SOFTINT (INT_SOFTINT + FIQ_VIC_START) +#define FIQ_COMMRx (INT_COMMRx + FIQ_VIC_START) +#define FIQ_COMMTx (INT_COMMTx + FIQ_VIC_START) +#define FIQ_TIMERINT0_1 (INT_TIMERINT0_1 + FIQ_VIC_START) +#define FIQ_TIMERINT2_3 (INT_TIMERINT2_3 + FIQ_VIC_START) +#define FIQ_GPIOINT0 (INT_GPIOINT0 + FIQ_VIC_START) +#define FIQ_GPIOINT1 (INT_GPIOINT1 + FIQ_VIC_START) +#define FIQ_GPIOINT2 (INT_GPIOINT2 + FIQ_VIC_START) +#define FIQ_GPIOINT3 (INT_GPIOINT3 + FIQ_VIC_START) +#define FIQ_RTCINT (INT_RTCINT + FIQ_VIC_START) +#define FIQ_SSPINT (INT_SSPINT + FIQ_VIC_START) +#define FIQ_UARTINT0 (INT_UARTINT0 + FIQ_VIC_START) +#define FIQ_UARTINT1 (INT_UARTINT1 + FIQ_VIC_START) +#define FIQ_UARTINT2 (INT_UARTINT2 + FIQ_VIC_START) +#define FIQ_SCIINT (INT_SCIINT + FIQ_VIC_START) +#define FIQ_CLCDINT (INT_CLCDINT + FIQ_VIC_START) +#define FIQ_DMAINT (INT_DMAINT + FIQ_VIC_START) +#define FIQ_PWRFAILINT (INT_PWRFAILINT + FIQ_VIC_START) +#define FIQ_MBXINT (INT_MBXINT + FIQ_VIC_START) +#define FIQ_GNDINT (INT_GNDINT + FIQ_VIC_START) +#define FIQ_VICSOURCE21 (INT_VICSOURCE21 + FIQ_VIC_START) +#define FIQ_VICSOURCE22 (INT_VICSOURCE22 + FIQ_VIC_START) +#define FIQ_VICSOURCE23 (INT_VICSOURCE23 + FIQ_VIC_START) +#define FIQ_VICSOURCE24 (INT_VICSOURCE24 + FIQ_VIC_START) +#define FIQ_VICSOURCE25 (INT_VICSOURCE25 + FIQ_VIC_START) +#define FIQ_VICSOURCE26 (INT_VICSOURCE26 + FIQ_VIC_START) +#define FIQ_VICSOURCE27 (INT_VICSOURCE27 + FIQ_VIC_START) +#define FIQ_VICSOURCE28 (INT_VICSOURCE28 + FIQ_VIC_START) +#define FIQ_VICSOURCE29 (INT_VICSOURCE29 + FIQ_VIC_START) +#define FIQ_VICSOURCE30 (INT_VICSOURCE30 + FIQ_VIC_START) +#define FIQ_VICSOURCE31 (INT_VICSOURCE31 + FIQ_VIC_START) + +#define NR_IRQS (FIQ_VICSOURCE31 + 1) diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c index ddfaca9..ddb1138 100644 --- a/arch/arm/plat-samsung/s5p-irq.c +++ b/arch/arm/plat-samsung/s5p-irq.c @@ -26,6 +26,7 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic) /* initialize the VICs */ for (irq = 0; irq < num_vic; irq++) - vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); + vic_init(VA_VIC(irq), VIC_BASE(irq), VIC_FIQ_START_NONE, + vic[irq], 0); #endif } diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index 7d35287..82bce53 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c @@ -56,6 +56,8 @@ #define VIC_PL192_VECT_ADDR 0xF00 +#define VIC_FIQ_SHADOW_OFFSET 32 + /** * struct vic_device - VIC PM device * @parent_irq: The parent IRQ number of the VIC if cascaded, or 0. @@ -81,8 +83,11 @@ struct vic_device { u32 soft_int; u32 protect; struct irq_domain *domain; + struct irq_domain *fiq_domain; }; +static DEFINE_RAW_SPINLOCK(irq_controller_lock); + /* we cannot allocate memory when VICs are initially registered */ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; @@ -197,6 +202,9 @@ static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq, { struct vic_device *v = d->host_data; + if (hwirq > VIC_FIQ_SHADOW_OFFSET) + hwirq -= VIC_FIQ_SHADOW_OFFSET; + /* Skip invalid IRQs, only register handlers for the real ones */ if (!(v->valid_sources & (1 << hwirq))) return -EPERM; @@ -277,7 +285,7 @@ static struct irq_domain_ops vic_irqdomain_ops = { * This also configures the IRQ domain for the VIC. */ static void __init vic_register(void __iomem *base, unsigned int parent_irq, - unsigned int irq, + unsigned int irq, int fiq, u32 valid_sources, u32 resume_sources, struct device_node *node) { @@ -307,6 +315,19 @@ static void __init vic_register(void __iomem *base, unsigned int parent_irq, for (i = 0; i < fls(valid_sources); i++) if (valid_sources & (1 << i)) irq_create_mapping(v->domain, i); + + /* create FIQ shadow mapping for each IRQ */ + if (fiq >= 0) { + v->fiq_domain = irq_domain_add_legacy( + node, fls(valid_sources), fiq, + VIC_FIQ_SHADOW_OFFSET, &vic_irqdomain_ops, v); + /* create an IRQ mapping for each valid IRQ */ + for (i = 0; i < fls(valid_sources); i++) + if (valid_sources & (1 << i)) + irq_create_mapping(v->fiq_domain, + i + VIC_FIQ_SHADOW_OFFSET); + } + /* If no base IRQ was passed, figure out our allocated base */ if (irq) v->irq = irq; @@ -314,10 +335,36 @@ static void __init vic_register(void __iomem *base, unsigned int parent_irq, v->irq = irq_find_mapping(v->domain, 0); } +static inline bool vic_is_fiq(struct irq_data *d) +{ + return d->hwirq >= VIC_FIQ_SHADOW_OFFSET; +} + +static inline unsigned int vic_irq(struct irq_data *d) +{ + return d->hwirq & (VIC_FIQ_SHADOW_OFFSET-1); +} + +static void vic_set_fiq(struct irq_data *d, bool enable) +{ + void __iomem *base = irq_data_get_irq_chip_data(d); + unsigned int irq = vic_irq(d); + u32 val; + + raw_spin_lock(&irq_controller_lock); + val = readl(base + VIC_INT_SELECT); + if (enable) + val |= 1 << irq; + else + val &= ~(1 << irq); + writel(val, base + VIC_INT_SELECT); + raw_spin_unlock(&irq_controller_lock); +} + static void vic_ack_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->hwirq; + unsigned int irq = vic_irq(d); writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); /* moreover, clear the soft-triggered, in case it was the reason */ writel(1 << irq, base + VIC_INT_SOFT_CLEAR); @@ -326,17 +373,22 @@ static void vic_ack_irq(struct irq_data *d) static void vic_mask_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->hwirq; + unsigned int irq = vic_irq(d); + if (vic_is_fiq(d)) + vic_set_fiq(d, false); writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); } static void vic_unmask_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->hwirq; + unsigned int irq = vic_irq(d); + if (vic_is_fiq(d)) + vic_set_fiq(d, true); writel(1 << irq, base + VIC_INT_ENABLE); } + #if defined(CONFIG_PM) static struct vic_device *vic_from_irq(unsigned int irq) { @@ -355,7 +407,7 @@ static struct vic_device *vic_from_irq(unsigned int irq) static int vic_set_wake(struct irq_data *d, unsigned int on) { struct vic_device *v = vic_from_irq(d->irq); - unsigned int off = d->hwirq; + unsigned int off = vic_irq(d); u32 bit = 1 << off; if (!v) @@ -413,7 +465,8 @@ static void __init vic_clear_interrupts(void __iomem *base) * and 020 within the page. We call this "second block". */ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, - u32 vic_sources, struct device_node *node) + int fiq_start, u32 vic_sources, + struct device_node *node) { unsigned int i; int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; @@ -439,12 +492,12 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, writel(32, base + VIC_PL190_DEF_VECT_ADDR); } - vic_register(base, 0, irq_start, vic_sources, 0, node); + vic_register(base, 0, irq_start, fiq_start, vic_sources, 0, node); } void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, - u32 vic_sources, u32 resume_sources, - struct device_node *node) + int fiq_start, u32 vic_sources, u32 resume_sources, + struct device_node *node) { unsigned int i; u32 cellid = 0; @@ -462,7 +515,7 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, switch(vendor) { case AMBA_VENDOR_ST: - vic_init_st(base, irq_start, vic_sources, node); + vic_init_st(base, irq_start, fiq_start, vic_sources, node); return; default: printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n"); @@ -479,7 +532,8 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, vic_init2(base); - vic_register(base, parent_irq, irq_start, vic_sources, resume_sources, node); + vic_register(base, parent_irq, irq_start, fiq_start, vic_sources, + resume_sources, node); } /** @@ -490,9 +544,9 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, * @resume_sources: bitmask of interrupt sources to allow for resume */ void __init vic_init(void __iomem *base, unsigned int irq_start, - u32 vic_sources, u32 resume_sources) + int fiq_start, u32 vic_sources, u32 resume_sources) { - __vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL); + __vic_init(base, 0, irq_start, -1, vic_sources, resume_sources, NULL); } /** @@ -511,7 +565,7 @@ int __init vic_init_cascaded(void __iomem *base, unsigned int parent_irq, struct vic_device *v; v = &vic_devices[vic_id]; - __vic_init(base, parent_irq, 0, vic_sources, resume_sources, NULL); + __vic_init(base, parent_irq, 0, -1, vic_sources, resume_sources, NULL); /* Return out acquired base */ return v->irq; } @@ -535,9 +589,10 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent) of_property_read_u32(node, "valid-wakeup-mask", &wakeup_mask); /* - * Passing 0 as first IRQ makes the simple domain allocate descriptors + * Passing 0 as first IRQ (and first FIQ) makes the domain allocate + * descriptors. */ - __vic_init(regs, 0, 0, interrupt_mask, wakeup_mask, node); + __vic_init(regs, 0, 0, -1, interrupt_mask, wakeup_mask, node); return 0; } diff --git a/include/linux/irqchip/arm-vic.h b/include/linux/irqchip/arm-vic.h index ba46c79..fae480d 100644 --- a/include/linux/irqchip/arm-vic.h +++ b/include/linux/irqchip/arm-vic.h @@ -26,12 +26,16 @@ #define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */ #define VIC_INT_ENABLE_CLEAR 0x14 +#define VIC_FIQ_START_NONE -1 + struct device_node; struct pt_regs; void __vic_init(void __iomem *base, int parent_irq, int irq_start, - u32 vic_sources, u32 resume_sources, struct device_node *node); -void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); + int fiq_start, u32 vic_sources, u32 resume_sources, + struct device_node *node); +void vic_init(void __iomem *base, unsigned int irq_start, int fiq_start, + u32 vic_sources, u32 resume_sources); int vic_init_cascaded(void __iomem *base, unsigned int parent_irq, u32 vic_sources, u32 resume_sources); -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v2 07/10] ARM: Move some macros from entry-armv to entry-header 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (5 preceding siblings ...) 2014-05-23 13:57 ` [RFC v2 06/10] irqchip: vic: Introduce shadow irqs for FIQ Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 08/10] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson ` (3 subsequent siblings) 10 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman From: Anton Vorontsov <anton.vorontsov@linaro.org> Just move the macros into header file as we would want to use them for KGDB FIQ entry code. The following macros were moved: - svc_entry - usr_entry - kuser_cmpxchg_check - vector_stub To make kuser_cmpxchg_check actually work across different files, we also have to make kuser_cmpxchg64_fixup global. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Nicolas Pitre <nico@linaro.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> --- arch/arm/kernel/entry-armv.S | 151 +------------------------------------ arch/arm/kernel/entry-header.S | 164 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 150 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 1879e8d..ed95b95 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -140,53 +140,6 @@ ENDPROC(__und_invalid) * SVC mode handlers */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) -#define SPFIX(code...) code -#else -#define SPFIX(code...) -#endif - - .macro svc_entry, stack_hole=0 - UNWIND(.fnstart ) - UNWIND(.save {r0 - pc} ) - sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) -#ifdef CONFIG_THUMB2_KERNEL - SPFIX( str r0, [sp] ) @ temporarily saved - SPFIX( mov r0, sp ) - SPFIX( tst r0, #4 ) @ test original stack alignment - SPFIX( ldr r0, [sp] ) @ restored -#else - SPFIX( tst sp, #4 ) -#endif - SPFIX( subeq sp, sp, #4 ) - stmia sp, {r1 - r12} - - ldmia r0, {r3 - r5} - add r7, sp, #S_SP - 4 @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) - SPFIX( addeq r2, r2, #4 ) - str r3, [sp, #-4]! @ save the "real" r0 copied - @ from the exception stack - - mov r3, lr - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r2 - sp_svc - @ r3 - lr_svc - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - stmia r7, {r2 - r6} - -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif - .endm - .align 5 __dabt_svc: svc_entry @@ -306,73 +259,8 @@ ENDPROC(__pabt_svc) /* * User mode handlers - * - * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - - .macro usr_entry - UNWIND(.fnstart ) - UNWIND(.cantunwind ) @ don't unwind the user space - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - r12} ) - THUMB( stmia sp, {r0 - r12} ) - - ldmia r0, {r3 - r5} - add r0, sp, #S_PC @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - - str r3, [sp] @ save the "real" r0 copied - @ from the exception stack - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - @ Also, separately save sp_usr and lr_usr - @ - stmia r0, {r4 - r6} - ARM( stmdb r0, {sp, lr}^ ) - THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) - - @ - @ Enable the alignment trap while in kernel mode - @ - alignment_trap r0 - - @ - @ Clear FP to mark the first stack frame - @ - zero_fp - -#ifdef CONFIG_IRQSOFF_TRACER - bl trace_hardirqs_off -#endif - ct_user_exit save = 0 - .endm - - .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ - !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ Make sure our user space atomic helper is restarted - @ if it was interrupted in a critical region. Here we - @ perform a quick test inline since it should be false - @ 99.9999% of the time. The rest is done out of line. - cmp r4, #TASK_SIZE - blhs kuser_cmpxchg64_fixup -#endif -#endif - .endm - .align 5 __dabt_usr: usr_entry @@ -819,6 +707,7 @@ __kuser_cmpxchg64: @ 0xffff0f60 ldmfd sp!, {r4, r5, r6, pc} .text + .global kuser_cmpxchg64_fixup kuser_cmpxchg64_fixup: @ Called from kuser_cmpxchg_fixup. @ r4 = address of interrupted insn (must be preserved). @@ -960,44 +849,6 @@ __kuser_helper_end: * SP points to a minimal amount of processor-private memory, the address * of which is copied into r0 for the mode specific abort handler. */ - .macro vector_stub, name, mode, correction=0 - .align 5 - -vector_\name: - .if \correction - sub lr, lr, #\correction - .endif - - @ - @ Save r0, lr_<exception> (parent PC) and spsr_<exception> - @ (parent CPSR) - @ - stmia sp, {r0, lr} @ save r0, lr - mrs lr, spsr - str lr, [sp, #8] @ save spsr - - @ - @ Prepare for SVC32 mode. IRQs remain disabled. - @ - mrs r0, cpsr - eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) - msr spsr_cxsf, r0 - - @ - @ the branch table must immediately follow this code - @ - and lr, lr, #0x0f - THUMB( adr r0, 1f ) - THUMB( ldr lr, [r0, lr, lsl #2] ) - mov r0, sp - ARM( ldr lr, [pc, lr, lsl #2] ) - movs pc, lr @ branch to handler in SVC mode -ENDPROC(vector_\name) - - .align 2 - @ handler addresses follow this label -1: - .endm .section .stubs, "ax", %progbits __stubs_start: diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 1420725..ab04a67 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -352,3 +352,167 @@ scno .req r7 @ syscall number tbl .req r8 @ syscall table pointer why .req r8 @ Linux syscall (!= 0) tsk .req r9 @ current thread_info + +/* + * SVC mode handler macros + */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) +#define SPFIX(code...) code +#else +#define SPFIX(code...) +#endif + + .macro svc_entry, stack_hole=0 + UNWIND(.fnstart ) + UNWIND(.save {r0 - pc} ) + sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) +#ifdef CONFIG_THUMB2_KERNEL + SPFIX( str r0, [sp] ) @ temporarily saved + SPFIX( mov r0, sp ) + SPFIX( tst r0, #4 ) @ test original stack alignment + SPFIX( ldr r0, [sp] ) @ restored +#else + SPFIX( tst sp, #4 ) +#endif + SPFIX( subeq sp, sp, #4 ) + stmia sp, {r1 - r12} + + ldmia r0, {r3 - r5} + add r7, sp, #S_SP - 4 @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) + SPFIX( addeq r2, r2, #4 ) + str r3, [sp, #-4]! @ save the "real" r0 copied + @ from the exception stack + + mov r3, lr + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r2 - sp_svc + @ r3 - lr_svc + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + stmia r7, {r2 - r6} + +#ifdef CONFIG_TRACE_IRQFLAGS + bl trace_hardirqs_off +#endif + .endm + +/* + * User mode handler macros + * + * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE + */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) +#error "sizeof(struct pt_regs) must be a multiple of 8" +#endif + + .macro usr_entry + UNWIND(.fnstart ) + UNWIND(.cantunwind ) @ don't unwind the user space + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) + + ldmia r0, {r3 - r5} + add r0, sp, #S_PC @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + + str r3, [sp] @ save the "real" r0 copied + @ from the exception stack + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + @ Also, separately save sp_usr and lr_usr + @ + stmia r0, {r4 - r6} + ARM( stmdb r0, {sp, lr}^ ) + THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) + + @ + @ Enable the alignment trap while in kernel mode + @ + alignment_trap r0 + + @ + @ Clear FP to mark the first stack frame + @ + zero_fp + +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + ct_user_exit save = 0 + .endm + + .macro kuser_cmpxchg_check +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r4, #TASK_SIZE + blhs kuser_cmpxchg64_fixup +#endif +#endif + .endm + +/* + * Vector stubs macro. + */ + .macro vector_stub, name, mode, correction=0 + .align 5 + +vector_\name: + .if \correction + sub lr, lr, #\correction + .endif + + @ + @ Save r0, lr_<exception> (parent PC) and spsr_<exception> + @ (parent CPSR) + @ + stmia sp, {r0, lr} @ save r0, lr + mrs lr, spsr + str lr, [sp, #8] @ save spsr + + @ + @ Prepare for SVC32 mode. IRQs remain disabled. + @ + mrs r0, cpsr + eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) + msr spsr_cxsf, r0 + + @ + @ the branch table must immediately follow this code + @ + and lr, lr, #0x0f + THUMB( adr r0, 1f ) + THUMB( ldr lr, [r0, lr, lsl #2] ) + mov r0, sp + ARM( ldr lr, [pc, lr, lsl #2] ) + movs pc, lr @ branch to handler in SVC mode +ENDPROC(vector_\name) + + .align 2 + @ handler addresses follow this label +1: + .endm + + -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v2 08/10] ARM: Add KGDB/KDB FIQ debugger generic code 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (6 preceding siblings ...) 2014-05-23 13:57 ` [RFC v2 07/10] ARM: Move some macros from entry-armv to entry-header Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 09/10] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson ` (2 subsequent siblings) 10 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, Ben Dooks, David A. Long, linux-serial, Catalin Marinas, kernel-team, Dave Martin, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner From: Anton Vorontsov <anton.vorontsov@linaro.org> The FIQ debugger may be used to debug situations when the kernel stuck in uninterruptable sections, e.g. the kernel infinitely loops or deadlocked in an interrupt or with interrupts disabled. By default KGDB FIQ is disabled in runtime, but can be enabled with kgdb_fiq.enable=1 kernel command line option. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Ben Dooks <ben.dooks@codethink.co.uk> Cc: Dave Martin <Dave.Martin@arm.com> --- arch/arm/Kconfig | 2 + arch/arm/Kconfig.debug | 18 ++++++ arch/arm/include/asm/kgdb.h | 7 +++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/kgdb_fiq.c | 117 +++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++++++++++++++++ 6 files changed, 232 insertions(+) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db3c541..419fd0a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -307,6 +307,7 @@ choice config ARCH_MULTIPLATFORM bool "Allow multiple platforms to be selected" depends on MMU + select ARCH_MIGHT_HAVE_KGDB_FIQ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_HAS_SG_CHAIN select ARM_PATCH_PHYS_VIRT @@ -356,6 +357,7 @@ config ARCH_REALVIEW config ARCH_VERSATILE bool "ARM Ltd. Versatile family" + select ARCH_MIGHT_HAVE_KGDB_FIQ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_AMBA select ARM_TIMER_SP804 diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 6a2bcfd..1f1bec1 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -2,6 +2,24 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config ARCH_MIGHT_HAVE_KGDB_FIQ + bool + +config KGDB_FIQ + bool "KGDB FIQ support" + depends on KGDB_KDB && ARCH_MIGHT_HAVE_KGDB_FIQ && !THUMB2_KERNEL + select FIQ + help + The FIQ debugger may be used to debug situations when the + kernel stuck in uninterruptable sections, e.g. the kernel + infinitely loops or deadlocked in an interrupt or with + interrupts disabled. + + By default KGDB FIQ is disabled at runtime, but can be + enabled with kgdb_fiq.enable=1 kernel command line option. + + If unsure, say N. + config ARM_PTDUMP bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 0a9d5dd..5de21f01 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h @@ -11,7 +11,9 @@ #define __ARM_KGDB_H__ #include <linux/ptrace.h> +#include <linux/linkage.h> #include <asm/opcodes.h> +#include <asm/exception.h> /* * GDB assumes that we're a user process being debugged, so @@ -48,6 +50,11 @@ static inline void arch_kgdb_breakpoint(void) extern void kgdb_handle_bus_error(void); extern int kgdb_fault_expected; +extern char kgdb_fiq_handler; +extern char kgdb_fiq_handler_end; +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs); +extern int kgdb_register_fiq(unsigned int fiq); + #endif /* !__ASSEMBLY__ */ /* diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 040619c..251f651 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -67,6 +67,7 @@ endif obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o +obj-$(CONFIG_KGDB_FIQ) += kgdb_fiq_entry.o kgdb_fiq.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_HAVE_TCM) += tcm.o obj-$(CONFIG_OF) += devtree.o diff --git a/arch/arm/kernel/kgdb_fiq.c b/arch/arm/kernel/kgdb_fiq.c new file mode 100644 index 0000000..b236409 --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq.c @@ -0,0 +1,117 @@ +/* + * KGDB FIQ + * + * Copyright 2010 Google, Inc. + * Arve Hjønnevåg <arve@android.com> + * Colin Cross <ccross@android.com> + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov <anton.vorontsov@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <linux/hardirq.h> +#include <linux/atomic.h> +#include <linux/kdb.h> +#include <linux/kgdb.h> +#include <asm/fiq.h> +#include <asm/exception.h> + +static int kgdb_fiq_enabled; +module_param_named(enable, kgdb_fiq_enabled, int, 0600); +MODULE_PARM_DESC(enable, "set to 1 to enable FIQ KGDB"); + +static unsigned int kgdb_fiq; + +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs) +{ + if (kgdb_nmi_poll_knock()) { + nmi_enter(); + kgdb_handle_exception(1, 0, 0, regs); + nmi_exit(); + } + + eoi_fiq(kgdb_fiq); +} + +static struct fiq_handler kgdb_fiq_desc = { + .name = "kgdb", +}; + +static long kgdb_fiq_setup_stack(void *info) +{ + struct pt_regs regs; + + regs.ARM_sp = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER) + + THREAD_START_SP; + WARN_ON(!regs.ARM_sp); + + set_fiq_regs(®s); + return 0; +} + +/** + * kgdb_fiq_enable_nmi - Manage NMI-triggered entry to KGDB + * @on: Flag to either enable or disable an NMI + * + * This function manages NMIs that usually cause KGDB to enter. That is, not + * all NMIs should be enabled or disabled, but only those that issue + * kgdb_handle_exception(). + * + * The call counts disable requests, and thus allows to nest disables. But + * trying to enable already enabled NMI is an error. + */ +static void kgdb_fiq_enable_nmi(bool on) +{ + static atomic_t cnt; + int ret; + + ret = atomic_add_return(on ? 1 : -1, &cnt); + if (ret > 1 && on) { + /* + * There should be only one instance that calls this function + * in "enable, disable" order. All other users must call + * disable first, then enable. If not, something is wrong. + */ + WARN_ON(1); + return; + } + + if (ret > 0) + enable_fiq(kgdb_fiq); + else + disable_fiq(kgdb_fiq); +} + +int kgdb_register_fiq(unsigned int fiq) +{ + int err; + int cpu; + + if (!kgdb_fiq_enabled) + return -ENODEV; + + kgdb_fiq = fiq; + + err = claim_fiq(&kgdb_fiq_desc); + if (err) { + pr_warn("%s: unable to claim fiq", __func__); + return err; + } + + for_each_possible_cpu(cpu) + work_on_cpu(cpu, kgdb_fiq_setup_stack, NULL); + + set_fiq_handler(&kgdb_fiq_handler, + &kgdb_fiq_handler_end - &kgdb_fiq_handler); + + arch_kgdb_ops.enable_nmi = kgdb_fiq_enable_nmi; + return 0; +} diff --git a/arch/arm/kernel/kgdb_fiq_entry.S b/arch/arm/kernel/kgdb_fiq_entry.S new file mode 100644 index 0000000..d6becca --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq_entry.S @@ -0,0 +1,87 @@ +/* + * KGDB FIQ entry + * + * Copyright 1996,1997,1998 Russell King. + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov <anton.vorontsov@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/memory.h> +#include <asm/unwind.h> +#include "entry-header.S" + + .text + +@ This is needed for usr_entry/alignment_trap +.LCcralign: + .long cr_alignment +.LCdohandle: + .long kgdb_fiq_do_handle + + .macro fiq_handler + ldr r1, =.LCdohandle + mov r0, sp + adr lr, BSYM(9997f) + ldr pc, [r1] +9997: + .endm + + .align 5 +__fiq_svc: + svc_entry + fiq_handler + mov r0, sp + ldmib r0, {r1 - r14} + msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT + add r8, r0, #S_PC + ldr r9, [r0, #S_PSR] + msr spsr_cxsf, r9 + ldr r0, [r0, #S_R0] + ldmia r8, {pc}^ + + UNWIND(.fnend ) +ENDPROC(__fiq_svc) + .ltorg + + .align 5 +__fiq_usr: + usr_entry + kuser_cmpxchg_check + fiq_handler + get_thread_info tsk + mov why, #0 + b ret_to_user_from_irq + UNWIND(.fnend ) +ENDPROC(__fiq_usr) + .ltorg + + .global kgdb_fiq_handler +kgdb_fiq_handler: + + vector_stub fiq, FIQ_MODE, 4 + + .long __fiq_usr @ 0 (USR_26 / USR_32) + .long __fiq_svc @ 1 (FIQ_26 / FIQ_32) + .long __fiq_svc @ 2 (IRQ_26 / IRQ_32) + .long __fiq_svc @ 3 (SVC_26 / SVC_32) + .long __fiq_svc @ 4 + .long __fiq_svc @ 5 + .long __fiq_svc @ 6 + .long __fiq_svc @ 7 + .long __fiq_svc @ 8 + .long __fiq_svc @ 9 + .long __fiq_svc @ a + .long __fiq_svc @ b + .long __fiq_svc @ c + .long __fiq_svc @ d + .long __fiq_svc @ e + .long __fiq_svc @ f + + .global kgdb_fiq_handler_end +kgdb_fiq_handler_end: -- 1.9.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v2 09/10] serial: amba-pl011: Pass on FIQ information to KGDB. 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (7 preceding siblings ...) 2014-05-23 13:57 ` [RFC v2 08/10] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 10/10] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson 10 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman If the AMBA bus has provided the pl011 with a FIQ resource (i.e. a second IRQ) then speculatively register it with KGDB when the polling driver is initialized. By providing this information to KGDB the serial driver offers "permission" for KGDB to route the UART interrupt signal from the drivers own handler to KGDBs FIQ handler (which will eventually use the UART's polled I/O callbacks to interact with the user). This permission also implies the amba-pl011 driver has already unmasked RX interrupts (otherwise the FIQ handler will never trigger). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/amba-pl011.c | 101 ++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index dacf0a0..d34c72c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -58,6 +58,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/sizes.h> #include <linux/io.h> +#include <linux/kgdb.h> #define UART_NR 14 @@ -158,6 +159,7 @@ struct uart_amba_port { unsigned int old_cr; /* state during shutdown */ bool autorts; char type[12]; + int fiq; #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ bool using_tx_dma; @@ -1416,8 +1418,63 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&uap->port.lock, flags); } +static int pl011_hwinit(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + int retval; + + /* Optionaly enable pins to be muxed in and configured */ + pinctrl_pm_select_default_state(port->dev); + + /* + * Try to enable the clock producer. + */ + retval = clk_prepare_enable(uap->clk); + if (retval) + goto out; + + uap->port.uartclk = clk_get_rate(uap->clk); + + /* Clear pending error and receive interrupts */ + writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | + UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); + + /* + * Save interrupts enable mask, and enable RX interrupts in case if + * the interrupt is used for NMI entry. + */ + uap->im = readw(uap->port.membase + UART011_IMSC); + writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); + + if (dev_get_platdata(uap->port.dev)) { + struct amba_pl011_data *plat; + + plat = dev_get_platdata(uap->port.dev); + if (plat->init) + plat->init(); + } + return 0; + out: + return retval; +} + #ifdef CONFIG_CONSOLE_POLL +static int pl011_poll_init(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + int retval; + + retval = pl011_hwinit(port); + +#ifdef CONFIG_KGDB_FIQ + if (retval == 0 && uap->fiq > 0) + kgdb_register_fiq(uap->fiq); +#endif + + return retval; +} + static void pl011_quiesce_irqs(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1471,46 +1528,6 @@ static void pl011_put_poll_char(struct uart_port *port, #endif /* CONFIG_CONSOLE_POLL */ -static int pl011_hwinit(struct uart_port *port) -{ - struct uart_amba_port *uap = (struct uart_amba_port *)port; - int retval; - - /* Optionaly enable pins to be muxed in and configured */ - pinctrl_pm_select_default_state(port->dev); - - /* - * Try to enable the clock producer. - */ - retval = clk_prepare_enable(uap->clk); - if (retval) - goto out; - - uap->port.uartclk = clk_get_rate(uap->clk); - - /* Clear pending error and receive interrupts */ - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | - UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); - - /* - * Save interrupts enable mask, and enable RX interrupts in case if - * the interrupt is used for NMI entry. - */ - uap->im = readw(uap->port.membase + UART011_IMSC); - writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); - - if (dev_get_platdata(uap->port.dev)) { - struct amba_pl011_data *plat; - - plat = dev_get_platdata(uap->port.dev); - if (plat->init) - plat->init(); - } - return 0; - out: - return retval; -} - static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) { writew(lcr_h, uap->port.membase + uap->lcrh_rx); @@ -1890,7 +1907,7 @@ static struct uart_ops amba_pl011_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif @@ -2139,6 +2156,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->port.membase = base; uap->port.iotype = UPIO_MEM; uap->port.irq = dev->irq[0]; + uap->fiq = dev->irq[1]; uap->port.fifosize = uap->fifosize; uap->port.ops = &amba_pl011_pops; uap->port.flags = UPF_BOOT_AUTOCONF; @@ -2169,6 +2187,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uart_unregister_driver(&amba_reg); pl011_dma_remove(uap); } + out: return ret; } -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v2 10/10] serial: asc: Add support for KGDB's FIQ/NMI mode 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (8 preceding siblings ...) 2014-05-23 13:57 ` [RFC v2 09/10] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson @ 2014-05-23 13:57 ` Daniel Thompson 2014-05-23 14:50 ` Srinivas Kandagatla 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson 10 siblings, 1 reply; 68+ messages in thread From: Daniel Thompson @ 2014-05-23 13:57 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Patrice Chotard, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel If the platform bus has provided the st-asc with a FIQ resource (i.e. a second IRQ) then speculatively register it with KGDB when the polling driver is initialized. By providing this information to KGDB the serial driver offers "permission" for KGDB to route the UART interrupt signal from the drivers own handler to KGDBs FIQ handler (which will eventually use the UART's polled I/O callbacks to interact with the user). This permission also implies the st-asc driver has already unmasked RX interrupts (otherwise the FIQ handler will never trigger). This unmask is copied from similar code in amba-pl011.c . Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> Cc: Maxime Coquelin <maxime.coquelin@st.com> Cc: Patrice Chotard <patrice.chotard@st.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: kernel@stlinux.com Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/st-asc.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index c7f61ac..328720f 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -30,6 +30,7 @@ #include <linux/of_platform.h> #include <linux/serial_core.h> #include <linux/clk.h> +#include <linux/kgdb.h> #define DRIVER_NAME "st-asc" #define ASC_SERIAL_NAME "ttyAS" @@ -39,6 +40,7 @@ struct asc_port { struct uart_port port; struct clk *clk; + int fiq; unsigned int hw_flow_control:1; unsigned int force_m1:1; }; @@ -613,6 +615,26 @@ asc_verify_port(struct uart_port *port, struct serial_struct *ser) } #ifdef CONFIG_CONSOLE_POLL + +#ifdef CONFIG_KGDB_FIQ +/* + * Prepare the UART to be used from kgdb's NMI support. + */ +static int asc_poll_init(struct uart_port *port) +{ + struct asc_port *ascport = container_of(port, struct asc_port, port); + + /* register the FIQ with kgdb */ + if (ascport->fiq >= 0) + kgdb_register_fiq(ascport->fiq); + + /* enable RX interrupts in case the interrupt is used for NMI entry. */ + asc_enable_rx_interrupts(port); + + return 0; +} +#endif /* CONFIG_KGDB_FIQ */ + /* * Console polling routines for writing and reading from the uart while * in an interrupt or debug context (i.e. kgdb). @@ -656,11 +678,15 @@ static struct uart_ops asc_uart_ops = { .verify_port = asc_verify_port, .pm = asc_pm, #ifdef CONFIG_CONSOLE_POLL +#ifdef CONFIG_KGDB_FIQ + .poll_init = asc_poll_init, +#endif /* CONFIG_KGDB_FIQ */ .poll_get_char = asc_get_poll_char, .poll_put_char = asc_put_poll_char, #endif /* CONFIG_CONSOLE_POLL */ }; + static int asc_init_port(struct asc_port *ascport, struct platform_device *pdev) { @@ -673,6 +699,7 @@ static int asc_init_port(struct asc_port *ascport, port->fifosize = ASC_FIFO_SIZE; port->dev = &pdev->dev; port->irq = platform_get_irq(pdev, 0); + ascport->fiq = platform_get_irq(pdev, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); port->membase = devm_ioremap_resource(&pdev->dev, res); -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [RFC v2 10/10] serial: asc: Add support for KGDB's FIQ/NMI mode 2014-05-23 13:57 ` [RFC v2 10/10] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson @ 2014-05-23 14:50 ` Srinivas Kandagatla 0 siblings, 0 replies; 68+ messages in thread From: Srinivas Kandagatla @ 2014-05-23 14:50 UTC (permalink / raw) To: Daniel Thompson, Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, linux-kernel, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Colin Cross, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Maxime Coquelin, Greg Hi Dan, On 23/05/14 14:57, Daniel Thompson wrote: > If the platform bus has provided the st-asc with a FIQ resource (i.e. a > second IRQ) then speculatively register it with KGDB when the polling > driver is initialized. > > By providing this information to KGDB the serial driver offers > "permission" for KGDB to route the UART interrupt signal from the > drivers own handler to KGDBs FIQ handler (which will eventually use the > UART's polled I/O callbacks to interact with the user). This permission > also implies the st-asc driver has already unmasked RX interrupts > (otherwise the FIQ handler will never trigger). This unmask is copied > from similar code in amba-pl011.c . > > Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> > Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> > Cc: Maxime Coquelin <maxime.coquelin@st.com> > Cc: Patrice Chotard <patrice.chotard@st.com> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > Cc: Jiri Slaby <jslaby@suse.cz> > Cc: kernel@stlinux.com > Cc: linux-serial@vger.kernel.org > --- > drivers/tty/serial/st-asc.c | 27 +++++++++++++++++++++++++++ > 1 file changed, 27 insertions(+) > Also this new entry should be documented in the st-asc dt bindings. > diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c > index c7f61ac..328720f 100644 > --- a/drivers/tty/serial/st-asc.c > +++ b/drivers/tty/serial/st-asc.c > @@ -30,6 +30,7 @@ > #include <linux/of_platform.h> > #include <linux/serial_core.h> > #include <linux/clk.h> > +#include <linux/kgdb.h> > > #define DRIVER_NAME "st-asc" > #define ASC_SERIAL_NAME "ttyAS" > @@ -39,6 +40,7 @@ > struct asc_port { > struct uart_port port; > struct clk *clk; > + int fiq; > unsigned int hw_flow_control:1; > unsigned int force_m1:1; > }; ... > #ifdef CONFIG_CONSOLE_POLL > +#ifdef CONFIG_KGDB_FIQ > + .poll_init = asc_poll_init, > +#endif /* CONFIG_KGDB_FIQ */ > .poll_get_char = asc_get_poll_char, > .poll_put_char = asc_put_poll_char, > #endif /* CONFIG_CONSOLE_POLL */ > }; > > + no need of extra new line here. > static int asc_init_port(struct asc_port *ascport, > struct platform_device *pdev) > { > @@ -673,6 +699,7 @@ static int asc_init_port(struct asc_port *ascport, > port->fifosize = ASC_FIFO_SIZE; > port->dev = &pdev->dev; > port->irq = platform_get_irq(pdev, 0); > + ascport->fiq = platform_get_irq(pdev, 1); > Probably its better to give names to the irq resources and get them. As forcing the order in DT is always tricky highly possible for an error. Thanks, srini > res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > port->membase = devm_ioremap_resource(&pdev->dev, res); > ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC v3 0/9] kgdb: NMI/FIQ support for ARM 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (9 preceding siblings ...) 2014-05-23 13:57 ` [RFC v2 10/10] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-05 9:53 ` [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs Daniel Thompson ` (9 more replies) 10 siblings, 10 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman This patchset makes it possible to use the kgdb NMI infrastructure on ARM platforms by providing a mutli-platform compatible means for drivers to manage FIQ routings. First a quick summary of how the mainline kgdb NMI infrastructure (mostly found in drivers/tty/serial/kgdb_nmi.c) works. The kgdb infrastructure will re-route the kgdb console UART's interrupt signal from IRQ to FIQ. Naturally the UART will no longer function normally and will instead be managed by kgdb using the polled I/O functions. Any character delivered to the UART causes the kgdb handler function to be called. Note that, within this patchset a serial driver explicitly consents (or not) to the abuse outlined above by calling the appropriate registration during the .poll_init() callback. The patch set is structured as follows: The first five patches modify the interrupt system to make it easier to describe FIQ. The key concept is that a call to enable_fiq() must modify the IRQ/FIQ routing to that the FIQ really is enabled (rather than spuriously delivering the signal on the IRQ). To achieve this each interrupt controller registers two virqs for each hwirq (allowing IRQ and FIQ to be readily distinguished) and registers the mappings using a new call, fiq_add_mapping(). The next two patches (6 and 7) provide kgdb with a FIQ handler and a means for serial drivers to register their FIQ with kgdb. Finally two example serial drivers are modified in order to register their FIQs with kgdb. Major remaining TODO item is to modify the code to halt the other CPUs; at present this code sends IPIs (which use a normal IRQ) and busy waits for the other CPUs to halt. This means the benefits of invoking the debugger via NMI are not yet realized on SMP systems. However I plan to tackle that later (i.e. when there's some consensus on whether this approach is the right way to handle FIQ). Changes since v2: * Use flexible mappings to link a normal virq to a FIQ virq. This replaces the device tree proposals from the previous RFC (thanks Russell King and Rob Herring). * Reviewed all use of spin locks within .irq_eoi callbacks (and fixed the issue identified). Added comments to the FIQ registration functions making clear the requirements imposed on interrupt controller that call the FIQ API (thanks Russell King). * Fixed a few whitespace issues (thanks Srinivas Kandagatla) * ARM64/defconfig build tests (no problems found) Changes since v1: * Fully fledged multi-platform * Tested for correct FIQ operation on STiH416/B2020 (Cortex A9), qemu/versatile and qemu/vexpress-a15 (with self-written mods to the GIC model to support FIQ). * Regression tested (and resulting bugs fixed) on qemu/versatile+DT and qemu/integreatorcp. Anton Vorontsov (2): ARM: Move some macros from entry-armv to entry-header ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson (7): arm: fiq: arbitrary mappings from IRQ to FIQ virqs arm: fiq: Allow EOI to be communicated to the intc irqchip: gic: Provide support for interrupt grouping irqchip: gic: Introduce shadow irqs for FIQ irqchip: vic: Introduce shadow irqs for FIQ serial: amba-pl011: Pass on FIQ information to KGDB. serial: asc: Add support for KGDB's FIQ/NMI mode arch/arm/Kconfig | 2 + arch/arm/Kconfig.debug | 18 +++ arch/arm/include/asm/fiq.h | 4 + arch/arm/include/asm/kgdb.h | 7 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/entry-armv.S | 151 +------------------------ arch/arm/kernel/entry-header.S | 164 ++++++++++++++++++++++++++++ arch/arm/kernel/fiq.c | 85 +++++++++++++- arch/arm/kernel/kgdb_fiq.c | 124 +++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++ arch/arm/mach-ep93xx/core.c | 6 +- arch/arm/mach-netx/generic.c | 3 +- arch/arm/mach-s3c64xx/common.c | 6 +- arch/arm/mach-versatile/core.c | 9 +- arch/arm/mach-versatile/include/mach/irqs.h | 5 +- arch/arm/plat-samsung/s5p-irq.c | 3 +- drivers/irqchip/irq-gic.c | 97 ++++++++++++++-- drivers/irqchip/irq-vic.c | 102 ++++++++++++++--- drivers/tty/serial/amba-pl011.c | 99 ++++++++++------- drivers/tty/serial/st-asc.c | 23 ++++ include/linux/irqchip/arm-gic.h | 3 + include/linux/irqchip/arm-vic.h | 8 +- 22 files changed, 770 insertions(+), 237 deletions(-) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S -- 1.9.0 ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-05 11:51 ` Russell King - ARM Linux ` (2 more replies) 2014-06-05 9:53 ` [RFC v3 2/9] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson ` (8 subsequent siblings) 9 siblings, 3 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel Currently enable_fiq/disable_fiq use a simple offset to convert an IRQ virq into a FIQ virq. This is too inflexible for multi-platform kernels and makes runtime error checking impossible. We solve this by introducing a flexible mapping that allows interrupt controllers that support FIQ to register those mappings. This, in turn, makes it much possible for drivers in DT kernels to gain access to FIQ virqs. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Fabio Estevam <festevam@gmail.com> Cc: Nicolas Pitre <nico@linaro.org> --- arch/arm/include/asm/fiq.h | 2 ++ arch/arm/kernel/fiq.c | 57 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h index d493d0b..75d98c6 100644 --- a/arch/arm/include/asm/fiq.h +++ b/arch/arm/include/asm/fiq.h @@ -36,8 +36,10 @@ struct fiq_handler { extern int claim_fiq(struct fiq_handler *f); extern void release_fiq(struct fiq_handler *f); extern void set_fiq_handler(void *start, unsigned int length); +extern struct irq_data *lookup_fiq_irq_data(int fiq); extern void enable_fiq(int fiq); extern void disable_fiq(int fiq); +extern void fiq_add_mapping(int irq, int fiq_virq, unsigned int length); /* helpers defined in fiqasm.S: */ extern void __set_fiq_regs(unsigned long const *regs); diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 918875d..177939c 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -40,6 +40,8 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/seq_file.h> +#include <linux/irq.h> +#include <linux/radix-tree.h> #include <asm/cacheflush.h> #include <asm/cp15.h> @@ -53,6 +55,9 @@ }) static unsigned long no_fiq_insn; +static int fiq_start = -1; +static RADIX_TREE(fiq_virq_tree, GFP_KERNEL); +static DEFINE_MUTEX(fiq_virq_mutex); /* Default reacquire function * - we always relinquish FIQ control @@ -60,8 +65,11 @@ static unsigned long no_fiq_insn; */ static int fiq_def_op(void *ref, int relinquish) { - if (!relinquish) + if (!relinquish) { + unsigned offset = FIQ_OFFSET; + no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn)); + } return 0; } @@ -127,16 +135,33 @@ void release_fiq(struct fiq_handler *f) while (current_fiq->fiq_op(current_fiq->dev_id, 0)); } -static int fiq_start; +struct irq_data *lookup_fiq_irq_data(int fiq) +{ + struct irq_data *d; + + if (fiq_start != -1) + return irq_get_irq_data(fiq + fiq_start); + + rcu_read_lock(); + d = radix_tree_lookup(&fiq_virq_tree, fiq); + rcu_read_unlock(); + return d; +} void enable_fiq(int fiq) { - enable_irq(fiq + fiq_start); + struct irq_data *d = lookup_fiq_irq_data(fiq); + if (WARN_ON(!d)) + return; + enable_irq(d->irq); } void disable_fiq(int fiq) { - disable_irq(fiq + fiq_start); + struct irq_data *d = lookup_fiq_irq_data(fiq); + if (WARN_ON(!d)) + return; + disable_irq(d->irq); } EXPORT_SYMBOL(set_fiq_handler); @@ -144,12 +169,32 @@ EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(claim_fiq); EXPORT_SYMBOL(release_fiq); +EXPORT_SYMBOL(lookup_fiq_irq_data); EXPORT_SYMBOL(enable_fiq); EXPORT_SYMBOL(disable_fiq); +/* + * Add a mapping between a normal IRQ and a FIQ shadow. + */ +void fiq_add_mapping(int irq, int fiq_virq, unsigned int length) +{ + int i; + + /* fiq_add_mapping can't be mixed with init_FIQ */ + BUG_ON(fiq_start != -1); + + mutex_lock(&fiq_virq_mutex); + for (i = 0; i < length; i++) { + int err = radix_tree_insert(&fiq_virq_tree, irq + i, + irq_get_irq_data(fiq_virq + i)); + if (err) + pr_err("fiq: Cannot map %d to %d\n", irq + i, + fiq_virq + i); + } + mutex_unlock(&fiq_virq_mutex); +} + void __init init_FIQ(int start) { - unsigned offset = FIQ_OFFSET; - no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); fiq_start = start; } -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs 2014-06-05 9:53 ` [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs Daniel Thompson @ 2014-06-05 11:51 ` Russell King - ARM Linux 2014-06-05 13:08 ` Daniel Thompson 2014-06-12 8:37 ` Linus Walleij 2014-06-13 14:29 ` Rob Herring 2 siblings, 1 reply; 68+ messages in thread From: Russell King - ARM Linux @ 2014-06-05 11:51 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, Catalin Marinas, Linus Walleij, Jiri Slaby, Dirk Behme, Nicolas Pitre, Fabio Estevam, patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial, kgdb-bugreport, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman On Thu, Jun 05, 2014 at 10:53:06AM +0100, Daniel Thompson wrote: > static int fiq_def_op(void *ref, int relinquish) > { > - if (!relinquish) > + if (!relinquish) { > + unsigned offset = FIQ_OFFSET; > + no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); > set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn)); > + } ... > void __init init_FIQ(int start) > { > - unsigned offset = FIQ_OFFSET; > - no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); > fiq_start = start; > } This is wrong - when the default handler is "reinstalled", this change has the effect that we read the first instruction of the existing handler, and then write that same instruction back, rather than replacing the first instruction with the value that was there at boot. -- FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs 2014-06-05 11:51 ` Russell King - ARM Linux @ 2014-06-05 13:08 ` Daniel Thompson 0 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 13:08 UTC (permalink / raw) To: Russell King - ARM Linux Cc: Mark Rutland, kernel, Catalin Marinas, Linus Walleij, Jiri Slaby, Dirk Behme, Nicolas Pitre, Fabio Estevam, patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial, kgdb-bugreport, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman On 05/06/14 12:51, Russell King - ARM Linux wrote: > On Thu, Jun 05, 2014 at 10:53:06AM +0100, Daniel Thompson wrote: >> static int fiq_def_op(void *ref, int relinquish) >> { >> - if (!relinquish) >> + if (!relinquish) { >> + unsigned offset = FIQ_OFFSET; >> + no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); >> set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn)); >> + } > ... >> void __init init_FIQ(int start) >> { >> - unsigned offset = FIQ_OFFSET; >> - no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); >> fiq_start = start; >> } > > This is wrong - when the default handler is "reinstalled", this change has > the effect that we read the first instruction of the existing handler, and > then write that same instruction back, rather than replacing the first > instruction with the value that was there at boot. Thanks. I'll fix this. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs 2014-06-05 9:53 ` [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs Daniel Thompson 2014-06-05 11:51 ` Russell King - ARM Linux @ 2014-06-12 8:37 ` Linus Walleij 2014-06-12 9:54 ` Daniel Thompson 2014-06-13 14:29 ` Rob Herring 2 siblings, 1 reply; 68+ messages in thread From: Linus Walleij @ 2014-06-12 8:37 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, kgdb-bugreport, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Patch Tracking, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial@vger.kernel.org, Catalin Marinas, kernel-team, devicetree@vger.kernel.org, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner On Thu, Jun 5, 2014 at 11:53 AM, Daniel Thompson <daniel.thompson@linaro.org> wrote: > Currently enable_fiq/disable_fiq use a simple offset to convert an IRQ > virq into a FIQ virq. This is too inflexible for multi-platform kernels > and makes runtime error checking impossible. > > We solve this by introducing a flexible mapping that allows interrupt > controllers that support FIQ to register those mappings. This, in turn, > makes it much possible for drivers in DT kernels to gain access to > FIQ virqs. I always had a big problem with the term "virq" which I take to mean "virtual IRQ". The distinction is: - Hardware IRQ offsets/numbers - a number encoded in HW specs which we usually call hwirqs - Linux IRQ numbers - just some number Sometimes, just sometimes, the Linux IRQ number matches the HW numbers, and then I guess the IRQ is regarded "non-virtual". The only real effect being that the numbers shown in /proc/interrupts are the same in both columns... the leftmost column with the Linux IRQ number and the one right next to the IRQ controller name which is the hwirq local offset. But all Linux IRQ numbers are virtual by definition. It's just some number that the kernel use as a cookie to look up the irq_desc. And one day we may get rid of IRQ numbers altogether. I would prefer just to s/virq/irq/g on this patch or if that is disturbing something more to the point like s/virq/linux_irq/g. Maybe this is a pointless battle, but still... Yours, Linus Walleij ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs 2014-06-12 8:37 ` Linus Walleij @ 2014-06-12 9:54 ` Daniel Thompson 0 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-12 9:54 UTC (permalink / raw) To: Linus Walleij Cc: Mark Rutland, kernel, kgdb-bugreport, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Patch Tracking, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial@vger.kernel.org, Catalin Marinas, kernel-team, devicetree@vger.kernel.org, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner On 12/06/14 09:37, Linus Walleij wrote: > On Thu, Jun 5, 2014 at 11:53 AM, Daniel Thompson > <daniel.thompson@linaro.org> wrote: > >> Currently enable_fiq/disable_fiq use a simple offset to convert an IRQ >> virq into a FIQ virq. This is too inflexible for multi-platform kernels >> and makes runtime error checking impossible. >> >> We solve this by introducing a flexible mapping that allows interrupt >> controllers that support FIQ to register those mappings. This, in turn, >> makes it much possible for drivers in DT kernels to gain access to >> FIQ virqs. > > I always had a big problem with the term "virq" which I take to mean > "virtual IRQ". So do I... That said, I think of it as the virtual as in virtual memory rather the virtual contained within virtualization. > The distinction is: > > - Hardware IRQ offsets/numbers - a number encoded in HW > specs which we usually call hwirqs > > - Linux IRQ numbers - just some number > > Sometimes, just sometimes, the Linux IRQ number matches the > HW numbers, and then I guess the IRQ is regarded "non-virtual". > The only real effect being that the numbers shown in > /proc/interrupts are the same in both columns... the leftmost > column with the Linux IRQ number and the one right next to > the IRQ controller name which is the hwirq local offset. > > But all Linux IRQ numbers are virtual by definition. It's just some > number that the kernel use as a cookie to look up the irq_desc. > And one day we may get rid of IRQ numbers altogether. > > I would prefer just to s/virq/irq/g on this patch or if that is > disturbing something more to the point like s/virq/linux_irq/g. > > Maybe this is a pointless battle, but still... I chose the term not because I have a personal attachement but because that is how they are spelt in the C symbols within irqdomain.[ch] which my patch relies upon heavily. The english documentation and comments is (very nearly) strict about using "Linux IRQ" so I'll happily change all the English text. However... I don't fancy s/virq/irq/ since this risks confusion between Linux irq and ARM IRQ and I don't fancy s/virq/linux_irq/ because in the kernel today virq is ~750x more frequenctly used than 'linux_irq' (git grep and wc suggests its 1507 versus 2). How strongly do you feel about this? ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs 2014-06-05 9:53 ` [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs Daniel Thompson 2014-06-05 11:51 ` Russell King - ARM Linux 2014-06-12 8:37 ` Linus Walleij @ 2014-06-13 14:29 ` Rob Herring 2014-06-18 11:24 ` Daniel Thompson 2 siblings, 1 reply; 68+ messages in thread From: Rob Herring @ 2014-06-13 14:29 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Linaro Patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial@vger.kernel.org, Catalin Marinas, kernel-team, devicetree@vger.kernel.org, linaro-kernel@lists.linaro.org, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring On Thu, Jun 5, 2014 at 4:53 AM, Daniel Thompson <daniel.thompson@linaro.org> wrote: > Currently enable_fiq/disable_fiq use a simple offset to convert an IRQ > virq into a FIQ virq. This is too inflexible for multi-platform kernels > and makes runtime error checking impossible. > > We solve this by introducing a flexible mapping that allows interrupt > controllers that support FIQ to register those mappings. This, in turn, > makes it much possible for drivers in DT kernels to gain access to > FIQ virqs. I don't get why you need a separate linux irq numbers for FIQ. Isn't enabling FIQ simply a property of an irq like edge vs. level trigger? Also, given the constraints on FIQ, we can't really have more that 1 IRQ assigned to FIQ. Rob ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs 2014-06-13 14:29 ` Rob Herring @ 2014-06-18 11:24 ` Daniel Thompson 0 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-18 11:24 UTC (permalink / raw) To: Rob Herring Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Linaro Patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial@vger.kernel.org, Catalin Marinas, kernel-team, devicetree@vger.kernel.org, linaro-kernel@lists.linaro.org, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring On 13/06/14 15:29, Rob Herring wrote: > On Thu, Jun 5, 2014 at 4:53 AM, Daniel Thompson > <daniel.thompson@linaro.org> wrote: >> Currently enable_fiq/disable_fiq use a simple offset to convert an IRQ >> virq into a FIQ virq. This is too inflexible for multi-platform kernels >> and makes runtime error checking impossible. >> >> We solve this by introducing a flexible mapping that allows interrupt >> controllers that support FIQ to register those mappings. This, in turn, >> makes it much possible for drivers in DT kernels to gain access to >> FIQ virqs. > > I don't get why you need a separate linux irq numbers for FIQ. Isn't > enabling FIQ simply a property of an irq like edge vs. level trigger? > Also, given the constraints on FIQ, we can't really have more that 1 > IRQ assigned to FIQ. No particular reason. I mostly went that way because it mimics the effect of fiq_start on enable_fiq/disable_fiq whilst supporting multi-platform. I'm tempted to keep the radix tree in the FIQ infrastructure but rather than messing about with shadow virqs use it to lookup a fiq_chip structure. I think this would keep a clean separation between the ARM centric (and slightly weird) FIQ from the generic irq code. Daniel. ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC v3 2/9] arm: fiq: Allow EOI to be communicated to the intc 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-06-05 9:53 ` [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-05 9:53 ` [RFC v3 3/9] irqchip: gic: Provide support for interrupt grouping Daniel Thompson ` (7 subsequent siblings) 9 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel Modern ARM systems require an EOI to be sent to the interrupt controller on completion of both IRQ and FIQ. The FIQ code currently does not provide any API to perform this. This patch provides this API, implemented by hooking into main irq driver in a similar way to the existing enable_fiq()/disable_fiq(). All existing in-kernel callers of init_FIQ() and fiq_add_mapping() have been reviewed to check they meet the documented restriction. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Fabio Estevam <festevam@gmail.com> Cc: Nicolas Pitre <nico@linaro.org> --- arch/arm/include/asm/fiq.h | 2 ++ arch/arm/kernel/fiq.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h index 75d98c6..10d22eb 100644 --- a/arch/arm/include/asm/fiq.h +++ b/arch/arm/include/asm/fiq.h @@ -39,6 +39,8 @@ extern void set_fiq_handler(void *start, unsigned int length); extern struct irq_data *lookup_fiq_irq_data(int fiq); extern void enable_fiq(int fiq); extern void disable_fiq(int fiq); +extern void eoi_fiq_with_irq_data(struct irq_data *d); +extern void eoi_fiq(int fiq); extern void fiq_add_mapping(int irq, int fiq_virq, unsigned int length); /* helpers defined in fiqasm.S: */ diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 177939c..ed01162 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -164,6 +164,25 @@ void disable_fiq(int fiq) disable_irq(d->irq); } +/* This call ends a FIQ and does not perform radix tree lookups. Use this + * if the FIQ interrupt rate is expected to be extremely high. + */ +void eoi_fiq_with_irq_data(struct irq_data *irq_data) +{ + struct irq_chip *chip = irq_data_get_irq_chip(irq_data); + if (chip->irq_eoi) + chip->irq_eoi(irq_data); +} +EXPORT_SYMBOL(eoi_fiq_with_irq_data); + +void eoi_fiq(int fiq) +{ + struct irq_data *d = lookup_fiq_irq_data(fiq); + BUG_ON(!d); + eoi_fiq_with_irq_data(d); +} +EXPORT_SYMBOL(eoi_fiq); + EXPORT_SYMBOL(set_fiq_handler); EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ @@ -175,6 +194,9 @@ EXPORT_SYMBOL(disable_fiq); /* * Add a mapping between a normal IRQ and a FIQ shadow. + * + * By providing a mapping the interrupt controller is guaranteeing not + * to use spin locks from .irq_eoi */ void fiq_add_mapping(int irq, int fiq_virq, unsigned int length) { @@ -194,6 +216,12 @@ void fiq_add_mapping(int irq, int fiq_virq, unsigned int length) mutex_unlock(&fiq_virq_mutex); } +/* + * Set the offset between normal IRQs and their FIQ shadows. + * + * By providing an offset the interrupt controller is guaranteeing not + * to use spin locks from .irq_eoi + */ void __init init_FIQ(int start) { fiq_start = start; -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v3 3/9] irqchip: gic: Provide support for interrupt grouping 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-06-05 9:53 ` [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs Daniel Thompson 2014-06-05 9:53 ` [RFC v3 2/9] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-05 19:50 ` Nicolas Pitre 2014-06-05 9:53 ` [RFC v3 4/9] irqchip: gic: Introduce shadow irqs for FIQ Daniel Thompson ` (6 subsequent siblings) 9 siblings, 1 reply; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, Nicolas Pitre, kernel, kgdb-bugreport, Linus Walleij, Sricharan R, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz All GIC hardware except GICv1 without TrustZone support provides a means to group exceptions into group 0 (which can optionally be signally using use FIQ) and group 1. The kernel currently provides no means to exploit this. This patch alters the initialization of the GIC to place all interrupts into group 1, this is a foundational requirement to meaningfully use FIQ. Note that 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". This allows grouping to be used to allow hardware peripherals to send interrupts into the secure world. On systems without TrustZone support the kernel has the power to route interrupt sources to FIQ, potentially allowing a driver to exploit the NMI-like properties of FIQ. The registers involved are RAZ/WI when unimplemented or protected by security policy. This patch therefore applies grouping unconditionally. Tested on a qemu GICv2 model (self-written from GICv2 spec) and an STiH416 (ARM Cortex A9, GICv1, TZ). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Christoffer Dall <christoffer.dall@linaro.org> Cc: Sricharan R <r.sricharan@ti.com> Acked-by: Dirk Behme <dirk.behme@de.bosch.com> --- drivers/irqchip/irq-gic.c | 35 ++++++++++++++++++++++++++++++----- include/linux/irqchip/arm-gic.h | 3 +++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 57d165e..aa8efe4 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -408,13 +408,27 @@ static void __init gic_dist_init(struct gic_chip_data *gic) writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); /* + * Set all global interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers a read-as-zero/write-ignored. + */ + for (i = 32; i < gic_irqs; i += 32) + writel_relaxed(0xffffffff, base + GIC_DIST_IGROUP + i * 4 / 32); + + /* * Disable all interrupts. Leave the PPI and SGIs alone * as these enables are banked registers. */ for (i = 32; i < gic_irqs; i += 32) writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); - writel_relaxed(1, base + GIC_DIST_CTRL); + /* + * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only, + * bit 1 ignored) + */ + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | + GIC_DIST_CTRL_ENABLE_GRP1_BIT, base + GIC_DIST_CTRL); } static void gic_cpu_init(struct gic_chip_data *gic) @@ -452,8 +466,16 @@ static void gic_cpu_init(struct gic_chip_data *gic) for (i = 0; i < 32; i += 4) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4); + /* + * Set all PPI and SGI interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers are read-as-zero/write-ignored. + */ + writel_relaxed(0xffffffff, dist_base + GIC_DIST_IGROUP + 0); + writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); - writel_relaxed(1, base + GIC_CPU_CTRL); + writel_relaxed(0x1f, base + GIC_CPU_CTRL); } void gic_cpu_if_down(void) @@ -537,7 +559,9 @@ 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(1, dist_base + GIC_DIST_CTRL); + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | + GIC_DIST_CTRL_ENABLE_GRP1_BIT, + dist_base + GIC_DIST_CTRL); } static void gic_cpu_save(unsigned int gic_nr) @@ -594,7 +618,7 @@ static void gic_cpu_restore(unsigned int gic_nr) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); - writel_relaxed(1, cpu_base + GIC_CPU_CTRL); + writel_relaxed(0x1f, cpu_base + GIC_CPU_CTRL); } static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) @@ -670,7 +694,8 @@ 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); + writel_relaxed(map << 16 | irq | 0x8000, + gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); raw_spin_unlock_irqrestore(&irq_controller_lock, flags); } diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 7ed92d0..919502f 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -37,6 +37,9 @@ #define GIC_DIST_SGI_PENDING_CLEAR 0xf10 #define GIC_DIST_SGI_PENDING_SET 0xf20 +#define GIC_DIST_CTRL_ENABLE_GRP0_BIT (1 << 0) +#define GIC_DIST_CTRL_ENABLE_GRP1_BIT (1 << 1) + #define GICH_HCR 0x0 #define GICH_VTR 0x4 #define GICH_VMCR 0x8 -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [RFC v3 3/9] irqchip: gic: Provide support for interrupt grouping 2014-06-05 9:53 ` [RFC v3 3/9] irqchip: gic: Provide support for interrupt grouping Daniel Thompson @ 2014-06-05 19:50 ` Nicolas Pitre 0 siblings, 0 replies; 68+ messages in thread From: Nicolas Pitre @ 2014-06-05 19:50 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Sricharan R, Colin Cross, Jiri Slaby, Dirk Behme, Russell King, patches, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, Ian Campbell, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg On Thu, 5 Jun 2014, Daniel Thompson wrote: > diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c > index 57d165e..aa8efe4 100644 > --- a/drivers/irqchip/irq-gic.c > +++ b/drivers/irqchip/irq-gic.c > @@ -408,13 +408,27 @@ static void __init gic_dist_init(struct gic_chip_data *gic) > writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); > > /* > + * Set all global interrupts to be group 1. > + * > + * If grouping is not available (not implemented or prohibited by > + * security mode) these registers a read-as-zero/write-ignored. > + */ > + for (i = 32; i < gic_irqs; i += 32) > + writel_relaxed(0xffffffff, base + GIC_DIST_IGROUP + i * 4 / 32); > + > + /* > * Disable all interrupts. Leave the PPI and SGIs alone > * as these enables are banked registers. > */ > for (i = 32; i < gic_irqs; i += 32) > writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); > > - writel_relaxed(1, base + GIC_DIST_CTRL); > + /* > + * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only, > + * bit 1 ignored) > + */ > + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | > + GIC_DIST_CTRL_ENABLE_GRP1_BIT, base + GIC_DIST_CTRL); Could there be more meaningful defines than GIC_DIST_CTRL_ENABLE_GRP0_BIT and GIC_DIST_CTRL_ENABLE_GRP1_BIT for those bits? Otherwise the code would look just as clear and possibly cleaner by simply using 0x3. Nicolas ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC v3 4/9] irqchip: gic: Introduce shadow irqs for FIQ 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (2 preceding siblings ...) 2014-06-05 9:53 ` [RFC v3 3/9] irqchip: gic: Provide support for interrupt grouping Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-06 7:46 ` Peter De Schrijver 2014-06-05 9:53 ` [RFC v3 5/9] irqchip: vic: " Daniel Thompson ` (5 subsequent siblings) 9 siblings, 1 reply; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, Nicolas Pitre, kernel, kgdb-bugreport, Linus Walleij, Sricharan R, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz This patch registers two virqs for each interrupt source it supports. Using multiple virqs allows the GIC driver to automatically modify the group register, allowing the new virqs to be used as argument to enable_fiq(). This also allows FIQ resources to be described in the device tree's interrupt list using a special flag (currently 0x80). Both these aspects combine and allow a driver to deploy a FIQ handler without any machine specific knowledge; it can be used effectively on multi-arch kernels. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Christoffer Dall <christoffer.dall@linaro.org> Cc: Sricharan R <r.sricharan@ti.com> --- drivers/irqchip/irq-gic.c | 62 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index aa8efe4..9a4712d 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -42,12 +42,17 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqchip/arm-gic.h> +#ifdef CONFIG_FIQ +#include <asm/fiq.h> +#endif #include <asm/irq.h> #include <asm/exception.h> #include <asm/smp_plat.h> #include "irqchip.h" +#define GIC_INTSPEC_IRQ_IS_FIQ (1 << 7) + 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; + unsigned int fiq_shadow_offset; #ifdef CONFIG_GIC_NON_BANKED void __iomem *(*get_base)(union gic_base *); #endif @@ -143,11 +149,34 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d) return gic_data_cpu_base(gic_data); } +static inline bool gic_is_fiq(struct irq_data *d) +{ + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); + return d->hwirq > gic_data->gic_irqs; +} + static inline unsigned int gic_irq(struct irq_data *d) { + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); + if (gic_is_fiq(d)) + return d->hwirq - gic_data->fiq_shadow_offset; return d->hwirq; } +static void gic_set_group_irq(struct irq_data *d, int group) +{ + unsigned int reg = gic_irq(d) / 32 * 4; + u32 mask = 1 << (gic_irq(d) % 32); + u32 val; + + val = readl_relaxed(gic_dist_base(d) + GIC_DIST_IGROUP + reg); + if (group) + val |= mask; + else + val &= ~mask; + writel_relaxed(val, gic_dist_base(d) + GIC_DIST_IGROUP + reg); +} + /* * Routines to acknowledge, disable and enable interrupts */ @@ -159,6 +188,8 @@ static void gic_mask_irq(struct irq_data *d) writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); if (gic_arch_extn.irq_mask) gic_arch_extn.irq_mask(d); + if (gic_is_fiq(d)) + gic_set_group_irq(d, 1); raw_spin_unlock(&irq_controller_lock); } @@ -167,6 +198,8 @@ static void gic_unmask_irq(struct irq_data *d) u32 mask = 1 << (gic_irq(d) % 32); raw_spin_lock(&irq_controller_lock); + if (gic_is_fiq(d)) + gic_set_group_irq(d, 0); if (gic_arch_extn.irq_unmask) gic_arch_extn.irq_unmask(d); writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); @@ -940,7 +973,12 @@ static int gic_routable_irq_domain_xlate(struct irq_domain *d, unsigned long *out_hwirq, unsigned int *out_type) { + struct gic_chip_data *gic_data = d->host_data; *out_hwirq += 16; + + if (intspec[2] & GIC_INTSPEC_IRQ_IS_FIQ) + *out_hwirq += gic_data->fiq_shadow_offset; + return 0; } @@ -1026,10 +1064,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, gic->gic_irqs = gic_irqs; gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ + gic->fiq_shadow_offset = gic_irqs; if (of_property_read_u32(node, "arm,routable-irqs", &nr_routable_irqs)) { - irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, + irq_base = irq_alloc_descs(irq_start, 16, 2 * gic_irqs, numa_node_id()); if (IS_ERR_VALUE(irq_base)) { WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", @@ -1037,17 +1076,28 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, irq_base = irq_start; } - gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, - hwirq_base, &gic_irq_domain_ops, gic); + gic->domain = + irq_domain_add_legacy(node, 2 * gic_irqs, irq_base, + hwirq_base, &gic_irq_domain_ops, gic); } else { - gic->domain = irq_domain_add_linear(node, nr_routable_irqs, - &gic_irq_domain_ops, - gic); + gic->domain = irq_domain_add_linear(node, 2 * nr_routable_irqs, + &gic_irq_domain_ops, gic); } if (WARN_ON(!gic->domain)) return; +#ifdef CONFIG_FIQ + /* FIQ can only be supported on platforms without an extended irq_eoi + * method (otherwise we take a lock during irq_eoi handling). + */ + if (!gic_arch_extn.irq_eoi) + fiq_add_mapping( + irq_linear_revmap(gic->domain, hwirq_base), + irq_linear_revmap(gic->domain, hwirq_base + gic_irqs), + gic_irqs); +#endif + if (gic_nr == 0) { #ifdef CONFIG_SMP set_smp_cross_call(gic_raise_softirq); -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [RFC v3 4/9] irqchip: gic: Introduce shadow irqs for FIQ 2014-06-05 9:53 ` [RFC v3 4/9] irqchip: gic: Introduce shadow irqs for FIQ Daniel Thompson @ 2014-06-06 7:46 ` Peter De Schrijver 2014-06-06 9:23 ` Daniel Thompson 0 siblings, 1 reply; 68+ messages in thread From: Peter De Schrijver @ 2014-06-06 7:46 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, Nicolas Pitre, kernel@stlinux.com, kgdb-bugreport@lists.sourceforge.net, Linus Walleij, Sricharan R, Colin Cross, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches@linaro.org, Anton Vorontsov, David A. Long, linux-serial@vger.kernel.org, Catalin Marinas, kernel-team@android.com, devicetree@vger.kernel.org, linaro-kernel@lists.linaro.org, Jason Cooper <jas> On Thu, Jun 05, 2014 at 11:53:09AM +0200, Daniel Thompson wrote: > This patch registers two virqs for each interrupt source it supports. > Using multiple virqs allows the GIC driver to automatically modify the group > register, allowing the new virqs to be used as argument to enable_fiq(). > This also allows FIQ resources to be described in the device tree's > interrupt list using a special flag (currently 0x80). > > Both these aspects combine and allow a driver to deploy a FIQ handler > without any machine specific knowledge; it can be used effectively on > multi-arch kernels. > > Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Jason Cooper <jason@lakedaemon.net> > Cc: Nicolas Pitre <nicolas.pitre@linaro.org> > Cc: Christoffer Dall <christoffer.dall@linaro.org> > Cc: Sricharan R <r.sricharan@ti.com> > --- > drivers/irqchip/irq-gic.c | 62 ++++++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 56 insertions(+), 6 deletions(-) > > diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c > index aa8efe4..9a4712d 100644 > --- a/drivers/irqchip/irq-gic.c > +++ b/drivers/irqchip/irq-gic.c > @@ -42,12 +42,17 @@ > #include <linux/irqchip/chained_irq.h> > #include <linux/irqchip/arm-gic.h> > > +#ifdef CONFIG_FIQ > +#include <asm/fiq.h> > +#endif > #include <asm/irq.h> > #include <asm/exception.h> > #include <asm/smp_plat.h> > > #include "irqchip.h" > > +#define GIC_INTSPEC_IRQ_IS_FIQ (1 << 7) > + > 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; > + unsigned int fiq_shadow_offset; > #ifdef CONFIG_GIC_NON_BANKED > void __iomem *(*get_base)(union gic_base *); > #endif > @@ -143,11 +149,34 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d) > return gic_data_cpu_base(gic_data); > } > > +static inline bool gic_is_fiq(struct irq_data *d) > +{ > + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); > + return d->hwirq > gic_data->gic_irqs; > +} > + > static inline unsigned int gic_irq(struct irq_data *d) > { > + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); > + if (gic_is_fiq(d)) > + return d->hwirq - gic_data->fiq_shadow_offset; > return d->hwirq; > } > > +static void gic_set_group_irq(struct irq_data *d, int group) > +{ > + unsigned int reg = gic_irq(d) / 32 * 4; > + u32 mask = 1 << (gic_irq(d) % 32); > + u32 val; > + > + val = readl_relaxed(gic_dist_base(d) + GIC_DIST_IGROUP + reg); > + if (group) > + val |= mask; > + else > + val &= ~mask; > + writel_relaxed(val, gic_dist_base(d) + GIC_DIST_IGROUP + reg); > +} > + > /* > * Routines to acknowledge, disable and enable interrupts > */ > @@ -159,6 +188,8 @@ static void gic_mask_irq(struct irq_data *d) > writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); > if (gic_arch_extn.irq_mask) > gic_arch_extn.irq_mask(d); > + if (gic_is_fiq(d)) > + gic_set_group_irq(d, 1); > raw_spin_unlock(&irq_controller_lock); > } > > @@ -167,6 +198,8 @@ static void gic_unmask_irq(struct irq_data *d) > u32 mask = 1 << (gic_irq(d) % 32); > > raw_spin_lock(&irq_controller_lock); > + if (gic_is_fiq(d)) > + gic_set_group_irq(d, 0); > if (gic_arch_extn.irq_unmask) > gic_arch_extn.irq_unmask(d); > writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); > @@ -940,7 +973,12 @@ static int gic_routable_irq_domain_xlate(struct irq_domain *d, > unsigned long *out_hwirq, > unsigned int *out_type) > { > + struct gic_chip_data *gic_data = d->host_data; > *out_hwirq += 16; > + > + if (intspec[2] & GIC_INTSPEC_IRQ_IS_FIQ) > + *out_hwirq += gic_data->fiq_shadow_offset; > + > return 0; > } > > @@ -1026,10 +1064,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, > gic->gic_irqs = gic_irqs; > > gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ > + gic->fiq_shadow_offset = gic_irqs; > > if (of_property_read_u32(node, "arm,routable-irqs", > &nr_routable_irqs)) { > - irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, > + irq_base = irq_alloc_descs(irq_start, 16, 2 * gic_irqs, > numa_node_id()); > if (IS_ERR_VALUE(irq_base)) { > WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", > @@ -1037,17 +1076,28 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, > irq_base = irq_start; > } > > - gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, > - hwirq_base, &gic_irq_domain_ops, gic); > + gic->domain = > + irq_domain_add_legacy(node, 2 * gic_irqs, irq_base, > + hwirq_base, &gic_irq_domain_ops, gic); > } else { > - gic->domain = irq_domain_add_linear(node, nr_routable_irqs, > - &gic_irq_domain_ops, > - gic); > + gic->domain = irq_domain_add_linear(node, 2 * nr_routable_irqs, > + &gic_irq_domain_ops, gic); > } > > if (WARN_ON(!gic->domain)) > return; > > +#ifdef CONFIG_FIQ > + /* FIQ can only be supported on platforms without an extended irq_eoi > + * method (otherwise we take a lock during irq_eoi handling). > + */ > + if (!gic_arch_extn.irq_eoi) > + fiq_add_mapping( > + irq_linear_revmap(gic->domain, hwirq_base), > + irq_linear_revmap(gic->domain, hwirq_base + gic_irqs), > + gic_irqs); > +#endif This is rather unfortunate. On Tegra for example we don't need a lock for the irq_eoi because the eoi ack can be handled with a single write to the appropriate irq ack register. Cheers, Peter. ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [RFC v3 4/9] irqchip: gic: Introduce shadow irqs for FIQ 2014-06-06 7:46 ` Peter De Schrijver @ 2014-06-06 9:23 ` Daniel Thompson 0 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-06 9:23 UTC (permalink / raw) To: Peter De Schrijver Cc: Mark Rutland, Nicolas Pitre, kernel@stlinux.com, kgdb-bugreport@lists.sourceforge.net, Linus Walleij, Sricharan R, Colin Cross, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches@linaro.org, Anton Vorontsov, David A. Long, linux-serial@vger.kernel.org, Catalin Marinas, kernel-team@android.com, devicetree@vger.kernel.org, linaro-kernel@lists.linaro.org, Jason Cooper <jas> On 06/06/14 08:46, Peter De Schrijver wrote: >> @@ -1037,17 +1076,28 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, >> irq_base = irq_start; >> } >> >> - gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, >> - hwirq_base, &gic_irq_domain_ops, gic); >> + gic->domain = >> + irq_domain_add_legacy(node, 2 * gic_irqs, irq_base, >> + hwirq_base, &gic_irq_domain_ops, gic); >> } else { >> - gic->domain = irq_domain_add_linear(node, nr_routable_irqs, >> - &gic_irq_domain_ops, >> - gic); >> + gic->domain = irq_domain_add_linear(node, 2 * nr_routable_irqs, >> + &gic_irq_domain_ops, gic); >> } >> >> if (WARN_ON(!gic->domain)) >> return; >> >> +#ifdef CONFIG_FIQ >> + /* FIQ can only be supported on platforms without an extended irq_eoi >> + * method (otherwise we take a lock during irq_eoi handling). >> + */ >> + if (!gic_arch_extn.irq_eoi) >> + fiq_add_mapping( >> + irq_linear_revmap(gic->domain, hwirq_base), >> + irq_linear_revmap(gic->domain, hwirq_base + gic_irqs), >> + gic_irqs); >> +#endif > > This is rather unfortunate. On Tegra for example we don't need a lock for the > irq_eoi because the eoi ack can be handled with a single write to the > appropriate irq ack register. I believe that Tegra is the only platform that uses this hook so should be safe to remove the locks from gic_irq_eoi(). Certainly looking back at the code history and the mailing list discussions around this code[1] I cannot see any reasoning about the locks that I have missed. Any objections to just nuking the locks? Daniel. [1] http://thread.gmane.org/gmane.linux.ports.arm.kernel/107474 http://thread.gmane.org/gmane.linux.ports.arm.kernel/108361 http://thread.gmane.org/gmane.linux.ports.arm.kernel/109690 ^ permalink raw reply [flat|nested] 68+ messages in thread
* [RFC v3 5/9] irqchip: vic: Introduce shadow irqs for FIQ 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (3 preceding siblings ...) 2014-06-05 9:53 ` [RFC v3 4/9] irqchip: gic: Introduce shadow irqs for FIQ Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-05 9:53 ` [RFC v3 6/9] ARM: Move some macros from entry-armv to entry-header Daniel Thompson ` (4 subsequent siblings) 9 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Kukjin Kim, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, linux-samsung-soc, Ben Currently on the ARM Versatile machine both FIQ and IRQ signals share the same irq number. The effect of this is that enable_fiq() will enable an interrupt but will leave it routed to IRQ. This requires a driver utilizing FIQ to employ machine specific knowledge (i.e. that the machine has a VIC). By introducing shadow irqs to describe FIQs the VIC driver is able to update the routing automatically during enable_fiq()/disable_fiq(). Changes to the vic_init() API allow individual machines to choose where to fit the shadow irqs in the interrupt map and also to choose not to have shadows at all. This patch introduces shadows for mach-versatile whilst mach-ep93xx, mach-netx, mach-s3c64xx and plat-samsung retain unmodified interrupt maps. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ryan Mallon <rmallon@gmail.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Ben Dooks <ben-linux@fluff.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: linux-samsung-soc@vger.kernel.org --- arch/arm/mach-ep93xx/core.c | 6 +- arch/arm/mach-netx/generic.c | 3 +- arch/arm/mach-s3c64xx/common.c | 6 +- arch/arm/mach-versatile/core.c | 9 +-- arch/arm/mach-versatile/include/mach/irqs.h | 5 +- arch/arm/plat-samsung/s5p-irq.c | 3 +- drivers/irqchip/irq-vic.c | 102 +++++++++++++++++++++++----- include/linux/irqchip/arm-vic.h | 8 ++- 8 files changed, 113 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 0e571f1..aa26411 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -185,8 +185,10 @@ void __init ep93xx_timer_init(void) *************************************************************************/ void __init ep93xx_init_irq(void) { - vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); - vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); + vic_init(EP93XX_VIC1_BASE, 0, VIC_FIQ_START_NONE, + EP93XX_VIC1_VALID_IRQ_MASK, 0); + vic_init(EP93XX_VIC2_BASE, 32, VIC_FIQ_START_NONE, + EP93XX_VIC2_VALID_IRQ_MASK, 0); } diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index db25b0c..5398dcd 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -169,7 +169,8 @@ void __init netx_init_irq(void) { int irq; - vic_init(io_p2v(NETX_PA_VIC), NETX_IRQ_VIC_START, ~0, 0); + vic_init(io_p2v(NETX_PA_VIC), NETX_IRQ_VIC_START, VIC_FIQ_START_NONE, + ~0, 0); for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { irq_set_chip_and_handler(irq, &netx_hif_chip, diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c index 5c45aae..b98dd48 100644 --- a/arch/arm/mach-s3c64xx/common.c +++ b/arch/arm/mach-s3c64xx/common.c @@ -242,8 +242,10 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); /* initialise the pair of VICs */ - vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME); - vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME); + vic_init(VA_VIC0, IRQ_VIC0_BASE, VIC_FIQ_START_NONE, vic0_valid, + IRQ_VIC0_RESUME); + vic_init(VA_VIC1, IRQ_VIC1_BASE, VIC_FIQ_START_NONE, vic1_valid, + IRQ_VIC1_RESUME); } #define eint_offset(irq) ((irq) - IRQ_EINT(0)) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index f2c89fb..3444ca8 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -108,7 +108,8 @@ void __init versatile_init_irq(void) np = of_find_matching_node_by_address(NULL, vic_of_match, VERSATILE_VIC_BASE); - __vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, ~0, 0, np); + __vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, + np ? -1 : FIQ_VIC_START, ~0, 0, np); writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); @@ -614,9 +615,9 @@ static struct pl022_ssp_controller ssp0_plat_data = { * These devices are connected via the DMA APB bridge */ #define SCI_IRQ { IRQ_SCIINT } -#define UART0_IRQ { IRQ_UARTINT0 } -#define UART1_IRQ { IRQ_UARTINT1 } -#define UART2_IRQ { IRQ_UARTINT2 } +#define UART0_IRQ { IRQ_UARTINT0, FIQ_UARTINT0 } +#define UART1_IRQ { IRQ_UARTINT1, FIQ_UARTINT1 } +#define UART2_IRQ { IRQ_UARTINT2, FIQ_UARTINT2 } #define SSP_IRQ { IRQ_SSPINT } /* FPGA Primecells */ diff --git a/arch/arm/mach-versatile/include/mach/irqs.h b/arch/arm/mach-versatile/include/mach/irqs.h index 0fd771c..68171d9 100644 --- a/arch/arm/mach-versatile/include/mach/irqs.h +++ b/arch/arm/mach-versatile/include/mach/irqs.h @@ -131,4 +131,7 @@ #define IRQ_GPIO3_START (IRQ_GPIO2_END + 1) #define IRQ_GPIO3_END (IRQ_GPIO3_START + 31) -#define NR_IRQS (IRQ_GPIO3_END + 1) +#define FIQ_VIC_START (IRQ_GPIO3_END + 1) +#define FIQ_VIC_END (FIQ_VIC_START + (IRQ_VIC_END - IRQ_VIC_START)) + +#define NR_IRQS (FIQ_VIC_END + 1) diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c index ddfaca9..ddb1138 100644 --- a/arch/arm/plat-samsung/s5p-irq.c +++ b/arch/arm/plat-samsung/s5p-irq.c @@ -26,6 +26,7 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic) /* initialize the VICs */ for (irq = 0; irq < num_vic; irq++) - vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); + vic_init(VA_VIC(irq), VIC_BASE(irq), VIC_FIQ_START_NONE, + vic[irq], 0); #endif } diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index 7d35287..748c5af 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c @@ -36,6 +36,9 @@ #include <asm/exception.h> #include <asm/irq.h> +#ifdef CONFIG_FIQ +#include <asm/fiq.h> +#endif #include "irqchip.h" @@ -56,6 +59,8 @@ #define VIC_PL192_VECT_ADDR 0xF00 +#define VIC_FIQ_SHADOW_OFFSET 32 + /** * struct vic_device - VIC PM device * @parent_irq: The parent IRQ number of the VIC if cascaded, or 0. @@ -81,8 +86,11 @@ struct vic_device { u32 soft_int; u32 protect; struct irq_domain *domain; + struct irq_domain *fiq_domain; }; +static DEFINE_RAW_SPINLOCK(irq_controller_lock); + /* we cannot allocate memory when VICs are initially registered */ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; @@ -197,6 +205,9 @@ static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq, { struct vic_device *v = d->host_data; + if (hwirq > VIC_FIQ_SHADOW_OFFSET) + hwirq -= VIC_FIQ_SHADOW_OFFSET; + /* Skip invalid IRQs, only register handlers for the real ones */ if (!(v->valid_sources & (1 << hwirq))) return -EPERM; @@ -261,6 +272,15 @@ static struct irq_domain_ops vic_irqdomain_ops = { .xlate = irq_domain_xlate_onetwocell, }; +#ifdef CONFIG_FIQ +static void vic_map_fiq(int irq, int fiq, unsigned int length) +{ + fiq_add_mapping(irq, fiq, length); +} +#else +static inline void vic_map_fiq(int irq, int fiq, unsigned int length) {} +#endif + /** * vic_register() - Register a VIC. * @base: The base address of the VIC. @@ -277,7 +297,7 @@ static struct irq_domain_ops vic_irqdomain_ops = { * This also configures the IRQ domain for the VIC. */ static void __init vic_register(void __iomem *base, unsigned int parent_irq, - unsigned int irq, + unsigned int irq, int fiq, u32 valid_sources, u32 resume_sources, struct device_node *node) { @@ -307,6 +327,22 @@ static void __init vic_register(void __iomem *base, unsigned int parent_irq, for (i = 0; i < fls(valid_sources); i++) if (valid_sources & (1 << i)) irq_create_mapping(v->domain, i); + + /* create FIQ shadow mapping for each IRQ */ + if (fiq >= 0) { + v->fiq_domain = irq_domain_add_legacy( + node, fls(valid_sources), fiq, + VIC_FIQ_SHADOW_OFFSET, &vic_irqdomain_ops, v); + /* create an IRQ mapping for each valid IRQ */ + for (i = 0; i < fls(valid_sources); i++) + if (valid_sources & (1 << i)) { + int fiq_virq = irq_create_mapping( + v->fiq_domain, i + VIC_FIQ_SHADOW_OFFSET); + vic_map_fiq(irq_find_mapping(v->domain, i), + fiq_virq, 1); + } + } + /* If no base IRQ was passed, figure out our allocated base */ if (irq) v->irq = irq; @@ -314,10 +350,36 @@ static void __init vic_register(void __iomem *base, unsigned int parent_irq, v->irq = irq_find_mapping(v->domain, 0); } +static inline bool vic_is_fiq(struct irq_data *d) +{ + return d->hwirq >= VIC_FIQ_SHADOW_OFFSET; +} + +static inline unsigned int vic_irq(struct irq_data *d) +{ + return d->hwirq & (VIC_FIQ_SHADOW_OFFSET-1); +} + +static void vic_set_fiq(struct irq_data *d, bool enable) +{ + void __iomem *base = irq_data_get_irq_chip_data(d); + unsigned int irq = vic_irq(d); + u32 val; + + raw_spin_lock(&irq_controller_lock); + val = readl(base + VIC_INT_SELECT); + if (enable) + val |= 1 << irq; + else + val &= ~(1 << irq); + writel(val, base + VIC_INT_SELECT); + raw_spin_unlock(&irq_controller_lock); +} + static void vic_ack_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->hwirq; + unsigned int irq = vic_irq(d); writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); /* moreover, clear the soft-triggered, in case it was the reason */ writel(1 << irq, base + VIC_INT_SOFT_CLEAR); @@ -326,17 +388,22 @@ static void vic_ack_irq(struct irq_data *d) static void vic_mask_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->hwirq; + unsigned int irq = vic_irq(d); + if (vic_is_fiq(d)) + vic_set_fiq(d, false); writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); } static void vic_unmask_irq(struct irq_data *d) { void __iomem *base = irq_data_get_irq_chip_data(d); - unsigned int irq = d->hwirq; + unsigned int irq = vic_irq(d); + if (vic_is_fiq(d)) + vic_set_fiq(d, true); writel(1 << irq, base + VIC_INT_ENABLE); } + #if defined(CONFIG_PM) static struct vic_device *vic_from_irq(unsigned int irq) { @@ -355,7 +422,7 @@ static struct vic_device *vic_from_irq(unsigned int irq) static int vic_set_wake(struct irq_data *d, unsigned int on) { struct vic_device *v = vic_from_irq(d->irq); - unsigned int off = d->hwirq; + unsigned int off = vic_irq(d); u32 bit = 1 << off; if (!v) @@ -413,7 +480,8 @@ static void __init vic_clear_interrupts(void __iomem *base) * and 020 within the page. We call this "second block". */ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, - u32 vic_sources, struct device_node *node) + int fiq_start, u32 vic_sources, + struct device_node *node) { unsigned int i; int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; @@ -439,12 +507,12 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, writel(32, base + VIC_PL190_DEF_VECT_ADDR); } - vic_register(base, 0, irq_start, vic_sources, 0, node); + vic_register(base, 0, irq_start, fiq_start, vic_sources, 0, node); } void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, - u32 vic_sources, u32 resume_sources, - struct device_node *node) + int fiq_start, u32 vic_sources, u32 resume_sources, + struct device_node *node) { unsigned int i; u32 cellid = 0; @@ -462,7 +530,7 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, switch(vendor) { case AMBA_VENDOR_ST: - vic_init_st(base, irq_start, vic_sources, node); + vic_init_st(base, irq_start, fiq_start, vic_sources, node); return; default: printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n"); @@ -479,7 +547,8 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, vic_init2(base); - vic_register(base, parent_irq, irq_start, vic_sources, resume_sources, node); + vic_register(base, parent_irq, irq_start, fiq_start, vic_sources, + resume_sources, node); } /** @@ -490,9 +559,9 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, * @resume_sources: bitmask of interrupt sources to allow for resume */ void __init vic_init(void __iomem *base, unsigned int irq_start, - u32 vic_sources, u32 resume_sources) + int fiq_start, u32 vic_sources, u32 resume_sources) { - __vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL); + __vic_init(base, 0, irq_start, -1, vic_sources, resume_sources, NULL); } /** @@ -511,7 +580,7 @@ int __init vic_init_cascaded(void __iomem *base, unsigned int parent_irq, struct vic_device *v; v = &vic_devices[vic_id]; - __vic_init(base, parent_irq, 0, vic_sources, resume_sources, NULL); + __vic_init(base, parent_irq, 0, -1, vic_sources, resume_sources, NULL); /* Return out acquired base */ return v->irq; } @@ -535,9 +604,10 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent) of_property_read_u32(node, "valid-wakeup-mask", &wakeup_mask); /* - * Passing 0 as first IRQ makes the simple domain allocate descriptors + * Passing 0 as first IRQ (and first FIQ) makes the domain allocate + * descriptors. */ - __vic_init(regs, 0, 0, interrupt_mask, wakeup_mask, node); + __vic_init(regs, 0, 0, -1, interrupt_mask, wakeup_mask, node); return 0; } diff --git a/include/linux/irqchip/arm-vic.h b/include/linux/irqchip/arm-vic.h index ba46c79..fae480d 100644 --- a/include/linux/irqchip/arm-vic.h +++ b/include/linux/irqchip/arm-vic.h @@ -26,12 +26,16 @@ #define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */ #define VIC_INT_ENABLE_CLEAR 0x14 +#define VIC_FIQ_START_NONE -1 + struct device_node; struct pt_regs; void __vic_init(void __iomem *base, int parent_irq, int irq_start, - u32 vic_sources, u32 resume_sources, struct device_node *node); -void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); + int fiq_start, u32 vic_sources, u32 resume_sources, + struct device_node *node); +void vic_init(void __iomem *base, unsigned int irq_start, int fiq_start, + u32 vic_sources, u32 resume_sources); int vic_init_cascaded(void __iomem *base, unsigned int parent_irq, u32 vic_sources, u32 resume_sources); -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v3 6/9] ARM: Move some macros from entry-armv to entry-header 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (4 preceding siblings ...) 2014-06-05 9:53 ` [RFC v3 5/9] irqchip: vic: " Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-05 9:53 ` [RFC v3 7/9] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson ` (3 subsequent siblings) 9 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman From: Anton Vorontsov <anton.vorontsov@linaro.org> Just move the macros into header file as we would want to use them for KGDB FIQ entry code. The following macros were moved: - svc_entry - usr_entry - kuser_cmpxchg_check - vector_stub To make kuser_cmpxchg_check actually work across different files, we also have to make kuser_cmpxchg64_fixup global. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Nicolas Pitre <nico@linaro.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> --- arch/arm/kernel/entry-armv.S | 151 +------------------------------------ arch/arm/kernel/entry-header.S | 164 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 150 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 1879e8d..ed95b95 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -140,53 +140,6 @@ ENDPROC(__und_invalid) * SVC mode handlers */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) -#define SPFIX(code...) code -#else -#define SPFIX(code...) -#endif - - .macro svc_entry, stack_hole=0 - UNWIND(.fnstart ) - UNWIND(.save {r0 - pc} ) - sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) -#ifdef CONFIG_THUMB2_KERNEL - SPFIX( str r0, [sp] ) @ temporarily saved - SPFIX( mov r0, sp ) - SPFIX( tst r0, #4 ) @ test original stack alignment - SPFIX( ldr r0, [sp] ) @ restored -#else - SPFIX( tst sp, #4 ) -#endif - SPFIX( subeq sp, sp, #4 ) - stmia sp, {r1 - r12} - - ldmia r0, {r3 - r5} - add r7, sp, #S_SP - 4 @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) - SPFIX( addeq r2, r2, #4 ) - str r3, [sp, #-4]! @ save the "real" r0 copied - @ from the exception stack - - mov r3, lr - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r2 - sp_svc - @ r3 - lr_svc - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - stmia r7, {r2 - r6} - -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif - .endm - .align 5 __dabt_svc: svc_entry @@ -306,73 +259,8 @@ ENDPROC(__pabt_svc) /* * User mode handlers - * - * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - - .macro usr_entry - UNWIND(.fnstart ) - UNWIND(.cantunwind ) @ don't unwind the user space - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - r12} ) - THUMB( stmia sp, {r0 - r12} ) - - ldmia r0, {r3 - r5} - add r0, sp, #S_PC @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - - str r3, [sp] @ save the "real" r0 copied - @ from the exception stack - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - @ Also, separately save sp_usr and lr_usr - @ - stmia r0, {r4 - r6} - ARM( stmdb r0, {sp, lr}^ ) - THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) - - @ - @ Enable the alignment trap while in kernel mode - @ - alignment_trap r0 - - @ - @ Clear FP to mark the first stack frame - @ - zero_fp - -#ifdef CONFIG_IRQSOFF_TRACER - bl trace_hardirqs_off -#endif - ct_user_exit save = 0 - .endm - - .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ - !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ Make sure our user space atomic helper is restarted - @ if it was interrupted in a critical region. Here we - @ perform a quick test inline since it should be false - @ 99.9999% of the time. The rest is done out of line. - cmp r4, #TASK_SIZE - blhs kuser_cmpxchg64_fixup -#endif -#endif - .endm - .align 5 __dabt_usr: usr_entry @@ -819,6 +707,7 @@ __kuser_cmpxchg64: @ 0xffff0f60 ldmfd sp!, {r4, r5, r6, pc} .text + .global kuser_cmpxchg64_fixup kuser_cmpxchg64_fixup: @ Called from kuser_cmpxchg_fixup. @ r4 = address of interrupted insn (must be preserved). @@ -960,44 +849,6 @@ __kuser_helper_end: * SP points to a minimal amount of processor-private memory, the address * of which is copied into r0 for the mode specific abort handler. */ - .macro vector_stub, name, mode, correction=0 - .align 5 - -vector_\name: - .if \correction - sub lr, lr, #\correction - .endif - - @ - @ Save r0, lr_<exception> (parent PC) and spsr_<exception> - @ (parent CPSR) - @ - stmia sp, {r0, lr} @ save r0, lr - mrs lr, spsr - str lr, [sp, #8] @ save spsr - - @ - @ Prepare for SVC32 mode. IRQs remain disabled. - @ - mrs r0, cpsr - eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) - msr spsr_cxsf, r0 - - @ - @ the branch table must immediately follow this code - @ - and lr, lr, #0x0f - THUMB( adr r0, 1f ) - THUMB( ldr lr, [r0, lr, lsl #2] ) - mov r0, sp - ARM( ldr lr, [pc, lr, lsl #2] ) - movs pc, lr @ branch to handler in SVC mode -ENDPROC(vector_\name) - - .align 2 - @ handler addresses follow this label -1: - .endm .section .stubs, "ax", %progbits __stubs_start: diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index efb208d..5d794d6 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -356,3 +356,167 @@ scno .req r7 @ syscall number tbl .req r8 @ syscall table pointer why .req r8 @ Linux syscall (!= 0) tsk .req r9 @ current thread_info + +/* + * SVC mode handler macros + */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) +#define SPFIX(code...) code +#else +#define SPFIX(code...) +#endif + + .macro svc_entry, stack_hole=0 + UNWIND(.fnstart ) + UNWIND(.save {r0 - pc} ) + sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) +#ifdef CONFIG_THUMB2_KERNEL + SPFIX( str r0, [sp] ) @ temporarily saved + SPFIX( mov r0, sp ) + SPFIX( tst r0, #4 ) @ test original stack alignment + SPFIX( ldr r0, [sp] ) @ restored +#else + SPFIX( tst sp, #4 ) +#endif + SPFIX( subeq sp, sp, #4 ) + stmia sp, {r1 - r12} + + ldmia r0, {r3 - r5} + add r7, sp, #S_SP - 4 @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) + SPFIX( addeq r2, r2, #4 ) + str r3, [sp, #-4]! @ save the "real" r0 copied + @ from the exception stack + + mov r3, lr + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r2 - sp_svc + @ r3 - lr_svc + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + stmia r7, {r2 - r6} + +#ifdef CONFIG_TRACE_IRQFLAGS + bl trace_hardirqs_off +#endif + .endm + +/* + * User mode handler macros + * + * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE + */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) +#error "sizeof(struct pt_regs) must be a multiple of 8" +#endif + + .macro usr_entry + UNWIND(.fnstart ) + UNWIND(.cantunwind ) @ don't unwind the user space + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) + + ldmia r0, {r3 - r5} + add r0, sp, #S_PC @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + + str r3, [sp] @ save the "real" r0 copied + @ from the exception stack + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + @ Also, separately save sp_usr and lr_usr + @ + stmia r0, {r4 - r6} + ARM( stmdb r0, {sp, lr}^ ) + THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) + + @ + @ Enable the alignment trap while in kernel mode + @ + alignment_trap r0 + + @ + @ Clear FP to mark the first stack frame + @ + zero_fp + +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + ct_user_exit save = 0 + .endm + + .macro kuser_cmpxchg_check +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r4, #TASK_SIZE + blhs kuser_cmpxchg64_fixup +#endif +#endif + .endm + +/* + * Vector stubs macro. + */ + .macro vector_stub, name, mode, correction=0 + .align 5 + +vector_\name: + .if \correction + sub lr, lr, #\correction + .endif + + @ + @ Save r0, lr_<exception> (parent PC) and spsr_<exception> + @ (parent CPSR) + @ + stmia sp, {r0, lr} @ save r0, lr + mrs lr, spsr + str lr, [sp, #8] @ save spsr + + @ + @ Prepare for SVC32 mode. IRQs remain disabled. + @ + mrs r0, cpsr + eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) + msr spsr_cxsf, r0 + + @ + @ the branch table must immediately follow this code + @ + and lr, lr, #0x0f + THUMB( adr r0, 1f ) + THUMB( ldr lr, [r0, lr, lsl #2] ) + mov r0, sp + ARM( ldr lr, [pc, lr, lsl #2] ) + movs pc, lr @ branch to handler in SVC mode +ENDPROC(vector_\name) + + .align 2 + @ handler addresses follow this label +1: + .endm + + -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v3 7/9] ARM: Add KGDB/KDB FIQ debugger generic code 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (5 preceding siblings ...) 2014-06-05 9:53 ` [RFC v3 6/9] ARM: Move some macros from entry-armv to entry-header Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-05 9:53 ` [RFC v3 8/9] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson ` (2 subsequent siblings) 9 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, Ben Dooks, David A. Long, linux-serial, Catalin Marinas, kernel-team, Dave Martin, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner From: Anton Vorontsov <anton.vorontsov@linaro.org> The FIQ debugger may be used to debug situations when the kernel stuck in uninterruptable sections, e.g. the kernel infinitely loops or deadlocked in an interrupt or with interrupts disabled. By default KGDB FIQ is disabled in runtime, but can be enabled with kgdb_fiq.enable=1 kernel command line option. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Ben Dooks <ben.dooks@codethink.co.uk> Cc: Dave Martin <Dave.Martin@arm.com> --- arch/arm/Kconfig | 2 + arch/arm/Kconfig.debug | 18 ++++++ arch/arm/include/asm/kgdb.h | 7 +++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/kgdb_fiq.c | 124 +++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++++++++++++++ 6 files changed, 239 insertions(+) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db3c541..419fd0a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -307,6 +307,7 @@ choice config ARCH_MULTIPLATFORM bool "Allow multiple platforms to be selected" depends on MMU + select ARCH_MIGHT_HAVE_KGDB_FIQ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_HAS_SG_CHAIN select ARM_PATCH_PHYS_VIRT @@ -356,6 +357,7 @@ config ARCH_REALVIEW config ARCH_VERSATILE bool "ARM Ltd. Versatile family" + select ARCH_MIGHT_HAVE_KGDB_FIQ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_AMBA select ARM_TIMER_SP804 diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 6a2bcfd..1f1bec1 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -2,6 +2,24 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config ARCH_MIGHT_HAVE_KGDB_FIQ + bool + +config KGDB_FIQ + bool "KGDB FIQ support" + depends on KGDB_KDB && ARCH_MIGHT_HAVE_KGDB_FIQ && !THUMB2_KERNEL + select FIQ + help + The FIQ debugger may be used to debug situations when the + kernel stuck in uninterruptable sections, e.g. the kernel + infinitely loops or deadlocked in an interrupt or with + interrupts disabled. + + By default KGDB FIQ is disabled at runtime, but can be + enabled with kgdb_fiq.enable=1 kernel command line option. + + If unsure, say N. + config ARM_PTDUMP bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 0a9d5dd..5de21f01 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h @@ -11,7 +11,9 @@ #define __ARM_KGDB_H__ #include <linux/ptrace.h> +#include <linux/linkage.h> #include <asm/opcodes.h> +#include <asm/exception.h> /* * GDB assumes that we're a user process being debugged, so @@ -48,6 +50,11 @@ static inline void arch_kgdb_breakpoint(void) extern void kgdb_handle_bus_error(void); extern int kgdb_fault_expected; +extern char kgdb_fiq_handler; +extern char kgdb_fiq_handler_end; +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs); +extern int kgdb_register_fiq(unsigned int fiq); + #endif /* !__ASSEMBLY__ */ /* diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 040619c..251f651 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -67,6 +67,7 @@ endif obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o +obj-$(CONFIG_KGDB_FIQ) += kgdb_fiq_entry.o kgdb_fiq.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_HAVE_TCM) += tcm.o obj-$(CONFIG_OF) += devtree.o diff --git a/arch/arm/kernel/kgdb_fiq.c b/arch/arm/kernel/kgdb_fiq.c new file mode 100644 index 0000000..45f2a79 --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq.c @@ -0,0 +1,124 @@ +/* + * KGDB FIQ + * + * Copyright 2010 Google, Inc. + * Arve Hjønnevåg <arve@android.com> + * Colin Cross <ccross@android.com> + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov <anton.vorontsov@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <linux/hardirq.h> +#include <linux/atomic.h> +#include <linux/kdb.h> +#include <linux/kgdb.h> +#include <asm/fiq.h> +#include <asm/exception.h> + +static int kgdb_fiq_enabled; +module_param_named(enable, kgdb_fiq_enabled, int, 0600); +MODULE_PARM_DESC(enable, "set to 1 to enable FIQ KGDB"); + +static unsigned int kgdb_fiq; + +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs) +{ + if (kgdb_nmi_poll_knock()) { + nmi_enter(); + kgdb_handle_exception(1, 0, 0, regs); + nmi_exit(); + } + + eoi_fiq(kgdb_fiq); +} + +static struct fiq_handler kgdb_fiq_desc = { + .name = "kgdb", +}; + +static long kgdb_fiq_setup_stack(void *info) +{ + struct pt_regs regs; + + regs.ARM_sp = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER) + + THREAD_START_SP; + WARN_ON(!regs.ARM_sp); + + set_fiq_regs(®s); + return 0; +} + +/** + * kgdb_fiq_enable_nmi - Manage NMI-triggered entry to KGDB + * @on: Flag to either enable or disable an NMI + * + * This function manages NMIs that usually cause KGDB to enter. That is, not + * all NMIs should be enabled or disabled, but only those that issue + * kgdb_handle_exception(). + * + * The call counts disable requests, and thus allows to nest disables. But + * trying to enable already enabled NMI is an error. + */ +static void kgdb_fiq_enable_nmi(bool on) +{ + static atomic_t cnt; + int ret; + + ret = atomic_add_return(on ? 1 : -1, &cnt); + if (ret > 1 && on) { + /* + * There should be only one instance that calls this function + * in "enable, disable" order. All other users must call + * disable first, then enable. If not, something is wrong. + */ + WARN_ON(1); + return; + } + + if (ret > 0) + enable_fiq(kgdb_fiq); + else + disable_fiq(kgdb_fiq); +} + +int kgdb_register_fiq(unsigned int fiq) +{ + int err; + int cpu; + + if (!kgdb_fiq_enabled) + return -ENODEV; + + if (!lookup_fiq_irq_data(fiq)) { + pr_warn( + "%s: Cannot register %u (no FIQ with this number)\n", + __func__, fiq); + return -ENODEV; + } + + kgdb_fiq = fiq; + + err = claim_fiq(&kgdb_fiq_desc); + if (err) { + pr_warn("%s: unable to claim fiq", __func__); + return err; + } + + for_each_possible_cpu(cpu) + work_on_cpu(cpu, kgdb_fiq_setup_stack, NULL); + + set_fiq_handler(&kgdb_fiq_handler, + &kgdb_fiq_handler_end - &kgdb_fiq_handler); + + arch_kgdb_ops.enable_nmi = kgdb_fiq_enable_nmi; + return 0; +} diff --git a/arch/arm/kernel/kgdb_fiq_entry.S b/arch/arm/kernel/kgdb_fiq_entry.S new file mode 100644 index 0000000..d6becca --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq_entry.S @@ -0,0 +1,87 @@ +/* + * KGDB FIQ entry + * + * Copyright 1996,1997,1998 Russell King. + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov <anton.vorontsov@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/memory.h> +#include <asm/unwind.h> +#include "entry-header.S" + + .text + +@ This is needed for usr_entry/alignment_trap +.LCcralign: + .long cr_alignment +.LCdohandle: + .long kgdb_fiq_do_handle + + .macro fiq_handler + ldr r1, =.LCdohandle + mov r0, sp + adr lr, BSYM(9997f) + ldr pc, [r1] +9997: + .endm + + .align 5 +__fiq_svc: + svc_entry + fiq_handler + mov r0, sp + ldmib r0, {r1 - r14} + msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT + add r8, r0, #S_PC + ldr r9, [r0, #S_PSR] + msr spsr_cxsf, r9 + ldr r0, [r0, #S_R0] + ldmia r8, {pc}^ + + UNWIND(.fnend ) +ENDPROC(__fiq_svc) + .ltorg + + .align 5 +__fiq_usr: + usr_entry + kuser_cmpxchg_check + fiq_handler + get_thread_info tsk + mov why, #0 + b ret_to_user_from_irq + UNWIND(.fnend ) +ENDPROC(__fiq_usr) + .ltorg + + .global kgdb_fiq_handler +kgdb_fiq_handler: + + vector_stub fiq, FIQ_MODE, 4 + + .long __fiq_usr @ 0 (USR_26 / USR_32) + .long __fiq_svc @ 1 (FIQ_26 / FIQ_32) + .long __fiq_svc @ 2 (IRQ_26 / IRQ_32) + .long __fiq_svc @ 3 (SVC_26 / SVC_32) + .long __fiq_svc @ 4 + .long __fiq_svc @ 5 + .long __fiq_svc @ 6 + .long __fiq_svc @ 7 + .long __fiq_svc @ 8 + .long __fiq_svc @ 9 + .long __fiq_svc @ a + .long __fiq_svc @ b + .long __fiq_svc @ c + .long __fiq_svc @ d + .long __fiq_svc @ e + .long __fiq_svc @ f + + .global kgdb_fiq_handler_end +kgdb_fiq_handler_end: -- 1.9.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v3 8/9] serial: amba-pl011: Pass on FIQ information to KGDB. 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (6 preceding siblings ...) 2014-06-05 9:53 ` [RFC v3 7/9] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-05 9:53 ` [RFC v3 9/9] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson 9 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman If the AMBA bus has provided the pl011 with a FIQ resource (i.e. a second IRQ) then speculatively register it with KGDB when the polling driver is initialized. By providing this information to KGDB the serial driver offers "permission" for KGDB to route the UART interrupt signal from the drivers own handler to KGDBs FIQ handler (which will eventually use the UART's polled I/O callbacks to interact with the user). This permission also implies the amba-pl011 driver has already unmasked RX interrupts (otherwise the FIQ handler will never trigger). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/amba-pl011.c | 99 ++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index dacf0a0..778fd38 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -58,6 +58,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/sizes.h> #include <linux/io.h> +#include <linux/kgdb.h> #define UART_NR 14 @@ -1416,8 +1417,63 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&uap->port.lock, flags); } +static int pl011_hwinit(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + int retval; + + /* Optionaly enable pins to be muxed in and configured */ + pinctrl_pm_select_default_state(port->dev); + + /* + * Try to enable the clock producer. + */ + retval = clk_prepare_enable(uap->clk); + if (retval) + goto out; + + uap->port.uartclk = clk_get_rate(uap->clk); + + /* Clear pending error and receive interrupts */ + writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | + UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); + + /* + * Save interrupts enable mask, and enable RX interrupts in case if + * the interrupt is used for NMI entry. + */ + uap->im = readw(uap->port.membase + UART011_IMSC); + writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); + + if (dev_get_platdata(uap->port.dev)) { + struct amba_pl011_data *plat; + + plat = dev_get_platdata(uap->port.dev); + if (plat->init) + plat->init(); + } + return 0; + out: + return retval; +} + #ifdef CONFIG_CONSOLE_POLL +static int pl011_poll_init(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + int retval; + + retval = pl011_hwinit(port); + +#ifdef CONFIG_KGDB_FIQ + if (retval == 0) + kgdb_register_fiq(uap->port.irq); +#endif + + return retval; +} + static void pl011_quiesce_irqs(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1471,46 +1527,6 @@ static void pl011_put_poll_char(struct uart_port *port, #endif /* CONFIG_CONSOLE_POLL */ -static int pl011_hwinit(struct uart_port *port) -{ - struct uart_amba_port *uap = (struct uart_amba_port *)port; - int retval; - - /* Optionaly enable pins to be muxed in and configured */ - pinctrl_pm_select_default_state(port->dev); - - /* - * Try to enable the clock producer. - */ - retval = clk_prepare_enable(uap->clk); - if (retval) - goto out; - - uap->port.uartclk = clk_get_rate(uap->clk); - - /* Clear pending error and receive interrupts */ - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | - UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); - - /* - * Save interrupts enable mask, and enable RX interrupts in case if - * the interrupt is used for NMI entry. - */ - uap->im = readw(uap->port.membase + UART011_IMSC); - writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); - - if (dev_get_platdata(uap->port.dev)) { - struct amba_pl011_data *plat; - - plat = dev_get_platdata(uap->port.dev); - if (plat->init) - plat->init(); - } - return 0; - out: - return retval; -} - static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) { writew(lcr_h, uap->port.membase + uap->lcrh_rx); @@ -1890,7 +1906,7 @@ static struct uart_ops amba_pl011_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif @@ -2169,6 +2185,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uart_unregister_driver(&amba_reg); pl011_dma_remove(uap); } + out: return ret; } -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [RFC v3 9/9] serial: asc: Add support for KGDB's FIQ/NMI mode 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (7 preceding siblings ...) 2014-06-05 9:53 ` [RFC v3 8/9] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson @ 2014-06-05 9:53 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson 9 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-05 9:53 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Patrice Chotard, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel If the platform bus has provided the st-asc with a FIQ resource (i.e. a second IRQ) then speculatively register it with KGDB when the polling driver is initialized. By providing this information to KGDB the serial driver offers "permission" for KGDB to route the UART interrupt signal from the drivers own handler to KGDBs FIQ handler (which will eventually use the UART's polled I/O callbacks to interact with the user). This permission also implies the st-asc driver has already unmasked RX interrupts (otherwise the FIQ handler will never trigger). This unmask is copied from similar code in amba-pl011.c . Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> Cc: Maxime Coquelin <maxime.coquelin@st.com> Cc: Patrice Chotard <patrice.chotard@st.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: kernel@stlinux.com Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/st-asc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index c7f61ac..4f376d8 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -30,6 +30,7 @@ #include <linux/of_platform.h> #include <linux/serial_core.h> #include <linux/clk.h> +#include <linux/kgdb.h> #define DRIVER_NAME "st-asc" #define ASC_SERIAL_NAME "ttyAS" @@ -613,6 +614,25 @@ asc_verify_port(struct uart_port *port, struct serial_struct *ser) } #ifdef CONFIG_CONSOLE_POLL + +#ifdef CONFIG_KGDB_FIQ +/* + * Prepare the UART to be used from kgdb's NMI support. + */ +static int asc_poll_init(struct uart_port *port) +{ + struct asc_port *ascport = container_of(port, struct asc_port, port); + + /* register the FIQ with kgdb */ + kgdb_register_fiq(ascport->port.irq); + + /* enable RX interrupts in case the interrupt is used for NMI entry. */ + asc_enable_rx_interrupts(port); + + return 0; +} +#endif /* CONFIG_KGDB_FIQ */ + /* * Console polling routines for writing and reading from the uart while * in an interrupt or debug context (i.e. kgdb). @@ -656,6 +676,9 @@ static struct uart_ops asc_uart_ops = { .verify_port = asc_verify_port, .pm = asc_pm, #ifdef CONFIG_CONSOLE_POLL +#ifdef CONFIG_KGDB_FIQ + .poll_init = asc_poll_init, +#endif /* CONFIG_KGDB_FIQ */ .poll_get_char = asc_get_poll_char, .poll_put_char = asc_put_poll_char, #endif /* CONFIG_CONSOLE_POLL */ -- 1.9.0 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (8 preceding siblings ...) 2014-06-05 9:53 ` [RFC v3 9/9] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 01/13] arm: fiq: Add callbacks to manage FIQ routings Daniel Thompson ` (12 more replies) 9 siblings, 13 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman This patchset makes it possible to use the kgdb NMI infrastructure on ARM platforms by providing a mutli-platform compatible means for drivers to manage FIQ routings. First a quick summary of how the already mainlined kgdb NMI infrastructure (mostly found in drivers/tty/serial/kgdb_nmi.c) works. The kgdb infrastructure will re-route the kgdb console UART's interrupt signal from IRQ to FIQ. Naturally the UART will no longer function normally and will instead be managed by kgdb using the polled I/O functions. Any character delivered to the UART causes the kgdb handler function to be called. Note that, within this patchset a serial driver explicitly consents (or not) to the abuse outlined above by calling the appropriate registration during the .poll_init() callback. In so doing it also commits to honour the stringent runtime requirements imposed on FIQ handlers within its polled I/O handlers. Major remaining TODO item is to modify the code to halt the other CPUs; at present this code sends IPIs (which use a normal IRQ) and busy waits for the other CPUs to halt. This means the benefits of invoking the debugger via NMI are only partially realized on SMP systems. However there are no cross dependencies so the code is "good to go" without this feature implemented. Changes since v3: * Corrected the FIQ uninstall code (Russell King). * Removed named constants for EnableGrp0 and EnableGrp1 (Nicolas Pitre). * Remove spin locks from gic_eoi_irq (Peter De Schrijver). * Massively simplified things by avoiding allocation of shadow IRQ (Rob Herring) * Correctly set the priority of FIQ interrupts by making the top bit follow ARM recommendations. Fixes robustness problem in the debugger itself. * Auto-detect whether the platform can support FIQ and act accordingly. This permits proper dead code elimination when CONFIG_FIQ is not set. * Ported to and tested on iMX6 (Wandboard quad). Included a patch from Dirk Behme that is required to get this device working properly with kgdb. * Avoid using writel() (which takes spin locks) in polled I/O callbacks of supported serial drivers. Changes since v2: * Use flexible mappings to link a normal virq to a FIQ virq. This replaces the device tree proposals from the previous RFC (review of Russell King and Rob Herring). * Reviewed all use of spin locks within .irq_eoi callbacks (and fixed the issue identified). Added comments to the FIQ registration functions making clear the requirements imposed on interrupt controller that call the FIQ API (thanks Russell King). * Fixed a few whitespace issues (review of Srinivas Kandagatla) * ARM64/defconfig build tests (no problems found) Changes since v1: * Fully fledged multi-platform support. * Tested for correct FIQ operation on STiH416/B2020 (Cortex A9), qemu/versatile and qemu/vexpress-a15 (with self-written mods to the GIC model to support FIQ). * Regression tested (and resulting bugs fixed) on qemu/versatile+DT and qemu/integreatorcp. Anton Vorontsov (2): ARM: Move some macros from entry-armv to entry-header ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson (10): arm: fiq: Add callbacks to manage FIQ routings arm: fiq: Allow EOI to be communicated to the intc irqchip: gic: Provide support for interrupt grouping irqchip: gic: Add support for FIQ management irqchip: gic: Remove spin locks from eoi_irq irqchip: vic: Add support for FIQ management serial: amba-pl011: Pass FIQ information to KGDB. serial: asc: Add support for KGDB's FIQ/NMI mode serial: asc: Adopt readl_/writel_relaxed() serial: imx: Add support for KGDB's FIQ/NMI mode Dirk Behme (1): serial: imx: clean up imx_poll_get_char() arch/arm/Kconfig | 2 + arch/arm/Kconfig.debug | 18 +++++ arch/arm/include/asm/fiq.h | 13 ++++ arch/arm/include/asm/kgdb.h | 7 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/entry-armv.S | 151 +---------------------------------- arch/arm/kernel/entry-header.S | 164 +++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/fiq.c | 112 +++++++++++++++++++++++++- arch/arm/kernel/kgdb_fiq.c | 124 +++++++++++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++++++++ arch/arm/mach-versatile/core.c | 2 +- drivers/irqchip/irq-gic.c | 155 +++++++++++++++++++++++++++++++++--- drivers/irqchip/irq-vic.c | 92 +++++++++++++++++----- drivers/tty/serial/amba-pl011.c | 99 +++++++++++++---------- drivers/tty/serial/imx.c | 88 ++++++++++++--------- drivers/tty/serial/st-asc.c | 34 +++++++- include/linux/irqchip/arm-vic.h | 6 +- 17 files changed, 892 insertions(+), 263 deletions(-) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S -- 1.9.3 ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH v4 01/13] arm: fiq: Add callbacks to manage FIQ routings 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 02/13] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson ` (11 subsequent siblings) 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel Currently enable_fiq/disable_fiq use a simple offset to convert an IRQ virq into a FIQ virq. This is too inflexible for multi-platform kernels and makes runtime error checking impossible. We solve this by introducing a flexible mapping that allows interrupt controllers that support FIQ to register those mappings. This, in turn, makes it much possible for drivers in DT kernels to install FIQ handlers without knowing anything about the interrupt controller. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Fabio Estevam <festevam@gmail.com> Cc: Nicolas Pitre <nico@linaro.org> --- arch/arm/include/asm/fiq.h | 7 +++ arch/arm/kernel/fiq.c | 103 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h index d493d0b..a7806ef 100644 --- a/arch/arm/include/asm/fiq.h +++ b/arch/arm/include/asm/fiq.h @@ -18,6 +18,11 @@ #include <asm/ptrace.h> +struct fiq_chip { + void (*fiq_enable)(struct irq_data *data); + void (*fiq_disable)(struct irq_data *data); +}; + struct fiq_handler { struct fiq_handler *next; /* Name @@ -38,6 +43,8 @@ extern void release_fiq(struct fiq_handler *f); extern void set_fiq_handler(void *start, unsigned int length); extern void enable_fiq(int fiq); extern void disable_fiq(int fiq); +extern bool has_fiq(int fiq); +extern void fiq_register_mapping(int irq, struct fiq_chip *chip); /* helpers defined in fiqasm.S: */ extern void __set_fiq_regs(unsigned long const *regs); diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 918875d..567f8fd 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -40,6 +40,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/seq_file.h> +#include <linux/irq.h> +#include <linux/radix-tree.h> +#include <linux/slab.h> #include <asm/cacheflush.h> #include <asm/cp15.h> @@ -52,7 +55,15 @@ (unsigned)&vector_fiq_offset; \ }) +struct fiq_data { + struct fiq_chip *fiq_chip; + struct irq_data *irq_data; +}; + static unsigned long no_fiq_insn; +static int fiq_start = -1; +static RADIX_TREE(fiq_data_tree, GFP_KERNEL); +static DEFINE_MUTEX(fiq_data_mutex); /* Default reacquire function * - we always relinquish FIQ control @@ -127,18 +138,65 @@ void release_fiq(struct fiq_handler *f) while (current_fiq->fiq_op(current_fiq->dev_id, 0)); } -static int fiq_start; +static struct fiq_data *lookup_fiq_data(int fiq) +{ + struct fiq_data *data; + + rcu_read_lock(); + data = radix_tree_lookup(&fiq_data_tree, fiq); + rcu_read_unlock(); + + return data; +} void enable_fiq(int fiq) { + struct fiq_data *data = lookup_fiq_data(fiq); + + if (data) { + if (data->fiq_chip->fiq_enable) + data->fiq_chip->fiq_enable(data->irq_data); + enable_irq(fiq); + return; + } + + if (WARN_ON(fiq_start == -1)) + return; + enable_irq(fiq + fiq_start); } void disable_fiq(int fiq) { + struct fiq_data *data = lookup_fiq_data(fiq); + + if (data) { + if (data->fiq_chip->fiq_disable) + data->fiq_chip->fiq_disable(data->irq_data); + disable_irq(fiq); + return; + } + + if (WARN_ON(fiq_start == -1)) + return; + disable_irq(fiq + fiq_start); } +bool has_fiq(int fiq) +{ + struct fiq_data *data = lookup_fiq_data(fiq); + + if (data) + return true; + + if (fiq_start == -1) + return false; + + return fiq > fiq_start; +} +EXPORT_SYMBOL(has_fiq); + EXPORT_SYMBOL(set_fiq_handler); EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ @@ -147,9 +205,50 @@ EXPORT_SYMBOL(release_fiq); EXPORT_SYMBOL(enable_fiq); EXPORT_SYMBOL(disable_fiq); +/* + * Add a mapping from a Linux irq to the fiq data. + */ +void fiq_register_mapping(int irq, struct fiq_chip *chip) +{ + struct fiq_data *fiq_data = NULL; + int res; + + /* fiq_register_mapping can't be mixed with init_FIQ */ + BUG_ON(fiq_start != -1); + + fiq_data = kmalloc(sizeof(*fiq_data), GFP_KERNEL); + if (!fiq_data) + goto err; + + fiq_data->fiq_chip = chip; + fiq_data->irq_data = irq_get_irq_data(irq); + BUG_ON(!fiq_data->irq_data); + + mutex_lock(&fiq_data_mutex); + res = radix_tree_insert(&fiq_data_tree, irq, fiq_data); + mutex_unlock(&fiq_data_mutex); + if (res) + goto err; + + return; + +err: + kfree(fiq_data); + pr_err("fiq: Cannot register mapping %d\n", irq); +} + +/* + * Set the offset between normal IRQs and their FIQ shadows. + */ void __init init_FIQ(int start) { + fiq_start = start; +} + +static int __init init_default_fiq_handler(void) +{ unsigned offset = FIQ_OFFSET; no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); - fiq_start = start; + return 0; } +pure_initcall(init_default_fiq_handler); -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 02/13] arm: fiq: Allow EOI to be communicated to the intc 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 01/13] arm: fiq: Add callbacks to manage FIQ routings Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 03/13] irqchip: gic: Provide support for interrupt grouping Daniel Thompson ` (10 subsequent siblings) 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Fabio Estevam, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel Modern ARM systems require an EOI to be sent to the interrupt controller on completion of both IRQ and FIQ. The FIQ code currently does not provide any API to perform this. This patch provides this API, implemented by adding a callback to the fiq_chip structure. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Fabio Estevam <festevam@gmail.com> Cc: Nicolas Pitre <nico@linaro.org> --- arch/arm/include/asm/fiq.h | 6 ++++++ arch/arm/kernel/fiq.c | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h index a7806ef..e5d9458 100644 --- a/arch/arm/include/asm/fiq.h +++ b/arch/arm/include/asm/fiq.h @@ -21,6 +21,11 @@ struct fiq_chip { void (*fiq_enable)(struct irq_data *data); void (*fiq_disable)(struct irq_data *data); + + /* .fiq_eoi() will be called from the FIQ handler. For this + * reason it must not use spin locks (or any other locks). + */ + void (*fiq_eoi)(struct irq_data *data); }; struct fiq_handler { @@ -43,6 +48,7 @@ extern void release_fiq(struct fiq_handler *f); extern void set_fiq_handler(void *start, unsigned int length); extern void enable_fiq(int fiq); extern void disable_fiq(int fiq); +extern void eoi_fiq(int fiq); extern bool has_fiq(int fiq); extern void fiq_register_mapping(int irq, struct fiq_chip *chip); diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 567f8fd..edde332 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -183,6 +183,15 @@ void disable_fiq(int fiq) disable_irq(fiq + fiq_start); } +void eoi_fiq(int fiq) +{ + struct fiq_data *data = lookup_fiq_data(fiq); + + if (data && data->fiq_chip->fiq_eoi) + data->fiq_chip->fiq_eoi(data->irq_data); +} +EXPORT_SYMBOL(eoi_fiq); + bool has_fiq(int fiq) { struct fiq_data *data = lookup_fiq_data(fiq); -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 03/13] irqchip: gic: Provide support for interrupt grouping 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 01/13] arm: fiq: Add callbacks to manage FIQ routings Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 02/13] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 04/13] irqchip: gic: Add support for FIQ management Daniel Thompson ` (9 subsequent siblings) 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, Nicolas Pitre, kernel, kgdb-bugreport, Linus Walleij, Sricharan R, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz All GIC hardware except GICv1-without-TrustZone support provides a means to group exceptions into group 0 (which can optionally be signally using use FIQ) and group 1. The kernel currently provides no means to exploit this. This patch alters the initialization of the GIC to place all interrupts into group 1 which is the foundational requirement to meaningfully use FIQ. Note that 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" (this feature allows grouping to be used to allow hardware peripherals to send interrupts into the secure world). The GIC driver will automatically detect this and disable its attempts to group interrupts. On systems without TrustZone support the kernel has the power to route interrupt sources to FIQ, potentially allowing a driver to exploit the NMI-like properties of FIQ. Tested on Freescale i.MX6 (quad A9), STiH416 (dual A9) and a self-written qemu GICv2 model. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Christoffer Dall <christoffer.dall@linaro.org> Cc: Sricharan R <r.sricharan@ti.com> Acked-by: Dirk Behme <dirk.behme@de.bosch.com> --- drivers/irqchip/irq-gic.c | 99 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 7e11c9d..bbffca3 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -42,6 +42,9 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqchip/arm-gic.h> +#ifdef CONFIG_FIQ +#include <asm/fiq.h> +#endif #include <asm/irq.h> #include <asm/exception.h> #include <asm/smp_plat.h> @@ -68,6 +71,9 @@ struct gic_chip_data { #ifdef CONFIG_GIC_NON_BANKED void __iomem *(*get_base)(union gic_base *); #endif +#ifdef CONFIG_FIQ + bool fiq_enable; +#endif }; static DEFINE_RAW_SPINLOCK(irq_controller_lock); @@ -131,6 +137,16 @@ static inline void gic_set_base_accessor(struct gic_chip_data *data, #define gic_set_base_accessor(d, f) #endif +#ifdef CONFIG_FIQ +static inline bool gic_data_fiq_enable(struct gic_chip_data *data) +{ + return data->fiq_enable; +} +#else +static inline bool gic_data_fiq_enable( + struct gic_chip_data *data) { return false; } +#endif + static inline void __iomem *gic_dist_base(struct irq_data *d) { struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); @@ -349,6 +365,42 @@ static struct irq_chip gic_chip = { .irq_set_wake = gic_set_wake, }; +#ifdef CONFIG_FIQ +static void __init gic_init_fiq(struct gic_chip_data *gic, + irq_hw_number_t first_irq, + unsigned int num_irqs) +{ + void __iomem *dist_base = gic_data_dist_base(gic_data); + unsigned int i; + + /* + * FIQ can only be supported on platforms without an extended irq_eoi + * method (otherwise we take a lock during eoi handling). + */ + if (gic_arch_extn.irq_eoi) + return; + + /* + * If grouping is not available (not implemented or prohibited by + * security mode) these registers a read-as-zero/write-ignored. + * However as a precaution we restore the reset default regardless of + * the result of the test. + */ + writel_relaxed(1, dist_base + GIC_DIST_IGROUP + 0); + gic->fiq_enable = readl_relaxed(dist_base + GIC_DIST_IGROUP + 0); + writel_relaxed(0, dist_base + GIC_DIST_IGROUP + 0); + pr_debug("gic: FIQ support %s\n", + gic->fiq_enable ? "enabled" : "disabled"); + + if (!gic->fiq_enable) + return; +} +#else /* CONFIG_FIQ */ +static inline void gic_init_fiq(struct gic_chip_data *gic, + irq_hw_number_t first_irq, + unsigned int num_irqs) {} +#endif /* CONFIG_FIQ */ + void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) { if (gic_nr >= MAX_GIC_NR) @@ -408,13 +460,28 @@ static void __init gic_dist_init(struct gic_chip_data *gic) writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); /* + * Optionally set all global interrupts to be group 1. + */ + if (gic_data_fiq_enable(gic)) + for (i = 32; i < gic_irqs; i += 32) + writel_relaxed(0xffffffff, + base + GIC_DIST_IGROUP + i * 4 / 32); + + /* * Disable all interrupts. Leave the PPI and SGIs alone * as these enables are banked registers. */ for (i = 32; i < gic_irqs; i += 32) writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); - writel_relaxed(1, base + GIC_DIST_CTRL); + /* + * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only, + * bit 1 ignored) + */ + if (gic_data_fiq_enable(gic)) + writel_relaxed(3, base + GIC_DIST_CTRL); + else + writel_relaxed(1, base + GIC_DIST_CTRL); } static void gic_cpu_init(struct gic_chip_data *gic) @@ -452,8 +519,20 @@ static void gic_cpu_init(struct gic_chip_data *gic) for (i = 0; i < 32; i += 4) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4); + /* + * Set all PPI and SGI interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers are read-as-zero/write-ignored. + */ + if (gic_data_fiq_enable(gic)) + writel_relaxed(0xffffffff, dist_base + GIC_DIST_IGROUP + 0); + writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); - writel_relaxed(1, base + GIC_CPU_CTRL); + if (gic_data_fiq_enable(gic)) + writel_relaxed(0x1f, base + GIC_CPU_CTRL); + else + writel_relaxed(1, base + GIC_CPU_CTRL); } void gic_cpu_if_down(void) @@ -537,7 +616,10 @@ 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(1, dist_base + GIC_DIST_CTRL); + if (gic_data_fiq_enable(&gic_data[gic_nr])) + writel_relaxed(3, dist_base + GIC_DIST_CTRL); + else + writel_relaxed(1, dist_base + GIC_DIST_CTRL); } static void gic_cpu_save(unsigned int gic_nr) @@ -594,7 +676,7 @@ static void gic_cpu_restore(unsigned int gic_nr) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); - writel_relaxed(1, cpu_base + GIC_CPU_CTRL); + writel_relaxed(0x1f, cpu_base + GIC_CPU_CTRL); } static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) @@ -656,6 +738,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { int cpu; unsigned long flags, map = 0; + unsigned long softint; raw_spin_lock_irqsave(&irq_controller_lock, flags); @@ -670,7 +753,11 @@ 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); + softint = map << 16 | irq; + if (gic_data_fiq_enable(&gic_data[0])) + softint |= 0x8000; + writel_relaxed(softint, + gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); raw_spin_unlock_irqrestore(&irq_controller_lock, flags); } @@ -1014,6 +1101,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, hwirq_base, &gic_irq_domain_ops, gic); + + gic_init_fiq(gic, irq_base, gic_irqs); } else { gic->domain = irq_domain_add_linear(node, nr_routable_irqs, &gic_irq_domain_ops, -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 04/13] irqchip: gic: Add support for FIQ management 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (2 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 03/13] irqchip: gic: Provide support for interrupt grouping Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 05/13] irqchip: gic: Remove spin locks from eoi_irq Daniel Thompson ` (8 subsequent siblings) 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, Nicolas Pitre, kernel, kgdb-bugreport, Linus Walleij, Sricharan R, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz This patch introduces callbacks to route interrupts to or away from the FIQ signal and registers these callbacks with the FIQ infrastructure (if the device can supports it). Both these aspects combine and allow a driver to deploy a FIQ handler without any machine specific knowledge; it can be used effectively on multi-platform kernels. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Christoffer Dall <christoffer.dall@linaro.org> Cc: Sricharan R <r.sricharan@ti.com> --- drivers/irqchip/irq-gic.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index bbffca3..0300c08 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -366,6 +366,58 @@ static struct irq_chip gic_chip = { }; #ifdef CONFIG_FIQ +/* + * 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. + */ +static void gic_set_group_irq(struct irq_data *d, int group) +{ + unsigned int grp_reg = gic_irq(d) / 32 * 4; + u32 grp_mask = 1 << (gic_irq(d) % 32); + u32 grp_val; + + unsigned int pri_reg = (gic_irq(d) / 4) * 4; + u32 pri_mask = 1 << (7 + ((gic_irq(d) % 4) * 8)); + u32 pri_val; + + raw_spin_lock(&irq_controller_lock); + + grp_val = readl_relaxed(gic_dist_base(d) + GIC_DIST_IGROUP + grp_reg); + pri_val = readl_relaxed(gic_dist_base(d) + 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, gic_dist_base(d) + GIC_DIST_IGROUP + grp_reg); + writel_relaxed(pri_val, gic_dist_base(d) + GIC_DIST_PRI + pri_reg); + + raw_spin_unlock(&irq_controller_lock); +} + +static void gic_enable_fiq(struct irq_data *d) +{ + gic_set_group_irq(d, 0); +} + +static void gic_disable_fiq(struct irq_data *d) +{ + gic_set_group_irq(d, 1); +} + +static struct fiq_chip gic_fiq = { + .fiq_enable = gic_enable_fiq, + .fiq_disable = gic_disable_fiq, + .fiq_eoi = gic_eoi_irq, +}; + static void __init gic_init_fiq(struct gic_chip_data *gic, irq_hw_number_t first_irq, unsigned int num_irqs) @@ -394,6 +446,12 @@ static void __init gic_init_fiq(struct gic_chip_data *gic, if (!gic->fiq_enable) return; + + /* + * FIQ is supported on this device! Register our chip data. + */ + for (i = 0; i < num_irqs; i++) + fiq_register_mapping(first_irq + i, &gic_fiq); } #else /* CONFIG_FIQ */ static inline void gic_init_fiq(struct gic_chip_data *gic, -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 05/13] irqchip: gic: Remove spin locks from eoi_irq 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (3 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 04/13] irqchip: gic: Add support for FIQ management Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 06/13] irqchip: vic: Add support for FIQ management Daniel Thompson ` (7 subsequent siblings) 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel This patch is motivated by the comment it removes from gic_init_fiq, namely that the spin locks in eoi_irq preclude certain platforms from supporting FIQ. Currently there is only one upstream platform (tegra) that actually hooks gic_arch_extn.irq_eoi and it does not require these spin locks. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Peter De Schrijver <pdeschrijver@nvidia.com> --- drivers/irqchip/irq-gic.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 0300c08..1cbff1d 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -191,11 +191,8 @@ static void gic_unmask_irq(struct irq_data *d) static void gic_eoi_irq(struct irq_data *d) { - if (gic_arch_extn.irq_eoi) { - raw_spin_lock(&irq_controller_lock); + if (gic_arch_extn.irq_eoi) gic_arch_extn.irq_eoi(d); - raw_spin_unlock(&irq_controller_lock); - } writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); } @@ -426,13 +423,6 @@ static void __init gic_init_fiq(struct gic_chip_data *gic, unsigned int i; /* - * FIQ can only be supported on platforms without an extended irq_eoi - * method (otherwise we take a lock during eoi handling). - */ - if (gic_arch_extn.irq_eoi) - return; - - /* * If grouping is not available (not implemented or prohibited by * security mode) these registers a read-as-zero/write-ignored. * However as a precaution we restore the reset default regardless of -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 06/13] irqchip: vic: Add support for FIQ management 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (4 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 05/13] irqchip: gic: Remove spin locks from eoi_irq Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 07/13] ARM: Move some macros from entry-armv to entry-header Daniel Thompson ` (6 subsequent siblings) 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Kukjin Kim, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Jason Cooper, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, linux-samsung-soc, Ben This patch introduces callbacks to route interrupts to or away from the FIQ signal. It also causes these callbacks to be registered with the FIQ infrastructure. This patch enable FIQ support for mach-versatile whilst mach-ep93xx, mach-netx, mach-s3c64xx and plat-samsung are unmodified (and can therefore continue to use init_FIQ() as before). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ryan Mallon <rmallon@gmail.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: Ben Dooks <ben-linux@fluff.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Cc: linux-samsung-soc@vger.kernel.org --- arch/arm/mach-versatile/core.c | 2 +- drivers/irqchip/irq-vic.c | 92 ++++++++++++++++++++++++++++++++--------- include/linux/irqchip/arm-vic.h | 6 ++- 3 files changed, 78 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index be83ba2..1abf360 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -108,7 +108,7 @@ void __init versatile_init_irq(void) np = of_find_matching_node_by_address(NULL, vic_of_match, VERSATILE_VIC_BASE); - __vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, ~0, 0, np); + __vic_init(VA_VIC_BASE, 0, IRQ_VIC_START, ~0, 0, np ? false : true, np); writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index 7d35287..22aa126 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c @@ -36,6 +36,9 @@ #include <asm/exception.h> #include <asm/irq.h> +#ifdef CONFIG_FIQ +#include <asm/fiq.h> +#endif #include "irqchip.h" @@ -261,11 +264,53 @@ static struct irq_domain_ops vic_irqdomain_ops = { .xlate = irq_domain_xlate_onetwocell, }; +#ifdef CONFIG_FIQ +static DEFINE_RAW_SPINLOCK(irq_controller_lock); + +static void vic_set_fiq(struct irq_data *d, bool enable) +{ + void __iomem *base = irq_data_get_irq_chip_data(d); + unsigned int irq = d->hwirq; + u32 val; + + raw_spin_lock(&irq_controller_lock); + val = readl(base + VIC_INT_SELECT); + if (enable) + val |= 1 << irq; + else + val &= ~(1 << irq); + writel(val, base + VIC_INT_SELECT); + raw_spin_unlock(&irq_controller_lock); +} + +static void vic_enable_fiq(struct irq_data *d) +{ + vic_set_fiq(d, true); +} + +static void vic_disable_fiq(struct irq_data *d) +{ + vic_set_fiq(d, false); +} + +struct fiq_chip vic_fiq = { + .fiq_enable = vic_enable_fiq, + .fiq_disable = vic_disable_fiq, +}; + +static void vic_register_fiq(int irq) +{ + fiq_register_mapping(irq, &vic_fiq); +} +#else /* CONFIG_FIQ */ +static inline void vic_register_fiq(int irq) {} +#endif /* CONFIG_FIQ */ + /** * vic_register() - Register a VIC. * @base: The base address of the VIC. * @parent_irq: The parent IRQ if cascaded, else 0. - * @irq: The base IRQ for the VIC. + * @irq_start: The base IRQ for the VIC. * @valid_sources: bitmask of valid interrupts * @resume_sources: bitmask of interrupts allowed for resume sources. * @node: The device tree node associated with the VIC. @@ -277,12 +322,13 @@ static struct irq_domain_ops vic_irqdomain_ops = { * This also configures the IRQ domain for the VIC. */ static void __init vic_register(void __iomem *base, unsigned int parent_irq, - unsigned int irq, + unsigned int irq_start, u32 valid_sources, u32 resume_sources, - struct device_node *node) + bool map_fiqs, struct device_node *node) { struct vic_device *v; int i; + unsigned int irq; if (vic_id >= ARRAY_SIZE(vic_devices)) { printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); @@ -301,15 +347,19 @@ static void __init vic_register(void __iomem *base, unsigned int parent_irq, irq_set_chained_handler(parent_irq, vic_handle_irq_cascaded); } - v->domain = irq_domain_add_simple(node, fls(valid_sources), irq, + v->domain = irq_domain_add_simple(node, fls(valid_sources), irq_start, &vic_irqdomain_ops, v); /* create an IRQ mapping for each valid IRQ */ - for (i = 0; i < fls(valid_sources); i++) - if (valid_sources & (1 << i)) - irq_create_mapping(v->domain, i); + for (i = 0; i < fls(valid_sources); i++) { + if (valid_sources & (1 << i)) { + irq = irq_create_mapping(v->domain, i); + vic_register_fiq(irq); + } + } + /* If no base IRQ was passed, figure out our allocated base */ - if (irq) - v->irq = irq; + if (irq_start) + v->irq = irq_start; else v->irq = irq_find_mapping(v->domain, 0); } @@ -413,7 +463,8 @@ static void __init vic_clear_interrupts(void __iomem *base) * and 020 within the page. We call this "second block". */ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, - u32 vic_sources, struct device_node *node) + u32 vic_sources, bool map_fiqs, + struct device_node *node) { unsigned int i; int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; @@ -439,12 +490,12 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, writel(32, base + VIC_PL190_DEF_VECT_ADDR); } - vic_register(base, 0, irq_start, vic_sources, 0, node); + vic_register(base, 0, irq_start, vic_sources, 0, map_fiqs, node); } void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, - u32 vic_sources, u32 resume_sources, - struct device_node *node) + u32 vic_sources, u32 resume_sources, + bool map_fiqs, struct device_node *node) { unsigned int i; u32 cellid = 0; @@ -462,7 +513,7 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, switch(vendor) { case AMBA_VENDOR_ST: - vic_init_st(base, irq_start, vic_sources, node); + vic_init_st(base, irq_start, vic_sources, map_fiqs, node); return; default: printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n"); @@ -479,7 +530,8 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, vic_init2(base); - vic_register(base, parent_irq, irq_start, vic_sources, resume_sources, node); + vic_register(base, parent_irq, irq_start, vic_sources, resume_sources, + map_fiqs, node); } /** @@ -492,7 +544,8 @@ void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, void __init vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources) { - __vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL); + __vic_init(base, 0, irq_start, vic_sources, resume_sources, + false, NULL); } /** @@ -511,7 +564,8 @@ int __init vic_init_cascaded(void __iomem *base, unsigned int parent_irq, struct vic_device *v; v = &vic_devices[vic_id]; - __vic_init(base, parent_irq, 0, vic_sources, resume_sources, NULL); + __vic_init(base, parent_irq, 0, vic_sources, resume_sources, false, + NULL); /* Return out acquired base */ return v->irq; } @@ -535,9 +589,9 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent) of_property_read_u32(node, "valid-wakeup-mask", &wakeup_mask); /* - * Passing 0 as first IRQ makes the simple domain allocate descriptors + * Passing 0 as first IRQ makes the domain allocate descriptors. */ - __vic_init(regs, 0, 0, interrupt_mask, wakeup_mask, node); + __vic_init(regs, 0, 0, interrupt_mask, wakeup_mask, true, node); return 0; } diff --git a/include/linux/irqchip/arm-vic.h b/include/linux/irqchip/arm-vic.h index ba46c79..30ab39f 100644 --- a/include/linux/irqchip/arm-vic.h +++ b/include/linux/irqchip/arm-vic.h @@ -30,8 +30,10 @@ struct device_node; struct pt_regs; void __vic_init(void __iomem *base, int parent_irq, int irq_start, - u32 vic_sources, u32 resume_sources, struct device_node *node); -void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); + u32 vic_sources, u32 resume_sources, + bool map_fiqs, struct device_node *node); +void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, + u32 resume_sources); int vic_init_cascaded(void __iomem *base, unsigned int parent_irq, u32 vic_sources, u32 resume_sources); -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 07/13] ARM: Move some macros from entry-armv to entry-header 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (5 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 06/13] irqchip: vic: Add support for FIQ management Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 08/13] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson ` (5 subsequent siblings) 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman From: Anton Vorontsov <anton.vorontsov@linaro.org> Just move the macros into header file as we would want to use them for KGDB FIQ entry code. The following macros were moved: - svc_entry - usr_entry - kuser_cmpxchg_check - vector_stub To make kuser_cmpxchg_check actually work across different files, we also have to make kuser_cmpxchg64_fixup global. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Nicolas Pitre <nico@linaro.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> --- arch/arm/kernel/entry-armv.S | 151 +----------------- arch/arm/kernel/entry-header.S | 350 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 351 insertions(+), 150 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 52a949a..4172cd6 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -140,53 +140,6 @@ ENDPROC(__und_invalid) * SVC mode handlers */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) -#define SPFIX(code...) code -#else -#define SPFIX(code...) -#endif - - .macro svc_entry, stack_hole=0 - UNWIND(.fnstart ) - UNWIND(.save {r0 - pc} ) - sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) -#ifdef CONFIG_THUMB2_KERNEL - SPFIX( str r0, [sp] ) @ temporarily saved - SPFIX( mov r0, sp ) - SPFIX( tst r0, #4 ) @ test original stack alignment - SPFIX( ldr r0, [sp] ) @ restored -#else - SPFIX( tst sp, #4 ) -#endif - SPFIX( subeq sp, sp, #4 ) - stmia sp, {r1 - r12} - - ldmia r0, {r3 - r5} - add r7, sp, #S_SP - 4 @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) - SPFIX( addeq r2, r2, #4 ) - str r3, [sp, #-4]! @ save the "real" r0 copied - @ from the exception stack - - mov r3, lr - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r2 - sp_svc - @ r3 - lr_svc - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - stmia r7, {r2 - r6} - -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif - .endm - .align 5 __dabt_svc: svc_entry @@ -306,73 +259,8 @@ ENDPROC(__pabt_svc) /* * User mode handlers - * - * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE */ -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - - .macro usr_entry - UNWIND(.fnstart ) - UNWIND(.cantunwind ) @ don't unwind the user space - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - r12} ) - THUMB( stmia sp, {r0 - r12} ) - - ldmia r0, {r3 - r5} - add r0, sp, #S_PC @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - - str r3, [sp] @ save the "real" r0 copied - @ from the exception stack - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - @ Also, separately save sp_usr and lr_usr - @ - stmia r0, {r4 - r6} - ARM( stmdb r0, {sp, lr}^ ) - THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) - - @ - @ Enable the alignment trap while in kernel mode - @ - alignment_trap r0, .LCcralign - - @ - @ Clear FP to mark the first stack frame - @ - zero_fp - -#ifdef CONFIG_IRQSOFF_TRACER - bl trace_hardirqs_off -#endif - ct_user_exit save = 0 - .endm - - .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ - !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ Make sure our user space atomic helper is restarted - @ if it was interrupted in a critical region. Here we - @ perform a quick test inline since it should be false - @ 99.9999% of the time. The rest is done out of line. - cmp r4, #TASK_SIZE - blhs kuser_cmpxchg64_fixup -#endif -#endif - .endm - .align 5 __dabt_usr: usr_entry @@ -823,6 +711,7 @@ __kuser_cmpxchg64: @ 0xffff0f60 ldmfd sp!, {r4, r5, r6, pc} .text + .global kuser_cmpxchg64_fixup kuser_cmpxchg64_fixup: @ Called from kuser_cmpxchg_fixup. @ r4 = address of interrupted insn (must be preserved). @@ -964,44 +853,6 @@ __kuser_helper_end: * SP points to a minimal amount of processor-private memory, the address * of which is copied into r0 for the mode specific abort handler. */ - .macro vector_stub, name, mode, correction=0 - .align 5 - -vector_\name: - .if \correction - sub lr, lr, #\correction - .endif - - @ - @ Save r0, lr_<exception> (parent PC) and spsr_<exception> - @ (parent CPSR) - @ - stmia sp, {r0, lr} @ save r0, lr - mrs lr, spsr - str lr, [sp, #8] @ save spsr - - @ - @ Prepare for SVC32 mode. IRQs remain disabled. - @ - mrs r0, cpsr - eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) - msr spsr_cxsf, r0 - - @ - @ the branch table must immediately follow this code - @ - and lr, lr, #0x0f - THUMB( adr r0, 1f ) - THUMB( ldr lr, [r0, lr, lsl #2] ) - mov r0, sp - ARM( ldr lr, [pc, lr, lsl #2] ) - movs pc, lr @ branch to handler in SVC mode -ENDPROC(vector_\name) - - .align 2 - @ handler addresses follow this label -1: - .endm .section .stubs, "ax", %progbits __stubs_start: diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 5d702f8..572f4b4 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -356,3 +356,353 @@ scno .req r7 @ syscall number tbl .req r8 @ syscall table pointer why .req r8 @ Linux syscall (!= 0) tsk .req r9 @ current thread_info + +/* + * SVC mode handler macros + */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) +#define SPFIX(code...) code +#else +#define SPFIX(code...) +#endif + + .macro svc_entry, stack_hole=0 + UNWIND(.fnstart ) + UNWIND(.save {r0 - pc} ) + sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) +#ifdef CONFIG_THUMB2_KERNEL + SPFIX( str r0, [sp] ) @ temporarily saved + SPFIX( mov r0, sp ) + SPFIX( tst r0, #4 ) @ test original stack alignment + SPFIX( ldr r0, [sp] ) @ restored +#else + SPFIX( tst sp, #4 ) +#endif + SPFIX( subeq sp, sp, #4 ) + stmia sp, {r1 - r12} + + ldmia r0, {r3 - r5} + add r7, sp, #S_SP - 4 @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) + SPFIX( addeq r2, r2, #4 ) + str r3, [sp, #-4]! @ save the "real" r0 copied + @ from the exception stack + + mov r3, lr + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r2 - sp_svc + @ r3 - lr_svc + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + stmia r7, {r2 - r6} + +#ifdef CONFIG_TRACE_IRQFLAGS + bl trace_hardirqs_off +#endif + .endm + +/* + * User mode handler macros + * + * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE + */ + +#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) +#error "sizeof(struct pt_regs) must be a multiple of 8" +#endif + + .macro usr_entry + UNWIND(.fnstart ) + UNWIND(.cantunwind ) @ don't unwind the user space + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) + + ldmia r0, {r3 - r5} + add r0, sp, #S_PC @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + + str r3, [sp] @ save the "real" r0 copied + @ from the exception stack + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + @ Also, separately save sp_usr and lr_usr + @ + stmia r0, {r4 - r6} + ARM( stmdb r0, {sp, lr}^ ) + THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) + + @ + @ Enable the alignment trap while in kernel mode + @ + alignment_trap r0, .LCcralign + + @ + @ Clear FP to mark the first stack frame + @ + zero_fp + +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + ct_user_exit save = 0 + .endm + + .macro kuser_cmpxchg_check +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r4, #TASK_SIZE + blhs kuser_cmpxchg64_fixup +#endif +#endif + .endm + +#error "sizeof(struct pt_regs) must be a multiple of 8" +#endif + + .macro usr_entry + UNWIND(.fnstart ) + UNWIND(.cantunwind ) @ don't unwind the user space + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) + + ldmia r0, {r3 - r5} + add r0, sp, #S_PC @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + + str r3, [sp] @ save the "real" r0 copied + @ from the exception stack + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + @ Also, separately save sp_usr and lr_usr + @ + stmia r0, {r4 - r6} + ARM( stmdb r0, {sp, lr}^ ) + THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) + + @ + @ Enable the alignment trap while in kernel mode + @ + alignment_trap r0, .LCcralign + + @ + @ Clear FP to mark the first stack frame + @ + zero_fp + +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + ct_user_exit save = 0 + .endm + + .macro kuser_cmpxchg_check +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r4, #TASK_SIZE + blhs kuser_cmpxchg64_fixup +#endif +#endif + .endm + +#error "sizeof(struct pt_regs) must be a multiple of 8" +#endif + + .macro usr_entry + UNWIND(.fnstart ) + UNWIND(.cantunwind ) @ don't unwind the user space + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) + + ldmia r0, {r3 - r5} + add r0, sp, #S_PC @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + + str r3, [sp] @ save the "real" r0 copied + @ from the exception stack + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + @ Also, separately save sp_usr and lr_usr + @ + stmia r0, {r4 - r6} + ARM( stmdb r0, {sp, lr}^ ) + THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) + + @ + @ Enable the alignment trap while in kernel mode + @ + alignment_trap r0, .LCcralign + + @ + @ Clear FP to mark the first stack frame + @ + zero_fp + +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + ct_user_exit save = 0 + .endm + + .macro kuser_cmpxchg_check +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r4, #TASK_SIZE + blhs kuser_cmpxchg64_fixup +#endif +#endif + .endm + +#error "sizeof(struct pt_regs) must be a multiple of 8" +#endif + + .macro usr_entry + UNWIND(.fnstart ) + UNWIND(.cantunwind ) @ don't unwind the user space + sub sp, sp, #S_FRAME_SIZE + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) + + ldmia r0, {r3 - r5} + add r0, sp, #S_PC @ here for interlock avoidance + mov r6, #-1 @ "" "" "" "" + + str r3, [sp] @ save the "real" r0 copied + @ from the exception stack + + @ + @ We are now ready to fill in the remaining blanks on the stack: + @ + @ r4 - lr_<exception>, already fixed up for correct return/restart + @ r5 - spsr_<exception> + @ r6 - orig_r0 (see pt_regs definition in ptrace.h) + @ + @ Also, separately save sp_usr and lr_usr + @ + stmia r0, {r4 - r6} + ARM( stmdb r0, {sp, lr}^ ) + THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) + + @ + @ Enable the alignment trap while in kernel mode + @ + alignment_trap r0 + + @ + @ Clear FP to mark the first stack frame + @ + zero_fp + +#ifdef CONFIG_IRQSOFF_TRACER + bl trace_hardirqs_off +#endif + ct_user_exit save = 0 + .endm + + .macro kuser_cmpxchg_check +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r4, #TASK_SIZE + blhs kuser_cmpxchg64_fixup +#endif +#endif + .endm + +/* + * Vector stubs macro. + */ + .macro vector_stub, name, mode, correction=0 + .align 5 + +vector_\name: + .if \correction + sub lr, lr, #\correction + .endif + + @ + @ Save r0, lr_<exception> (parent PC) and spsr_<exception> + @ (parent CPSR) + @ + stmia sp, {r0, lr} @ save r0, lr + mrs lr, spsr + str lr, [sp, #8] @ save spsr + + @ + @ Prepare for SVC32 mode. IRQs remain disabled. + @ + mrs r0, cpsr + eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) + msr spsr_cxsf, r0 + + @ + @ the branch table must immediately follow this code + @ + and lr, lr, #0x0f + THUMB( adr r0, 1f ) + THUMB( ldr lr, [r0, lr, lsl #2] ) + mov r0, sp + ARM( ldr lr, [pc, lr, lsl #2] ) + movs pc, lr @ branch to handler in SVC mode +ENDPROC(vector_\name) + + .align 2 + @ handler addresses follow this label +1: + .endm + + -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 08/13] ARM: Add KGDB/KDB FIQ debugger generic code 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (6 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 07/13] ARM: Move some macros from entry-armv to entry-header Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 09/13] serial: amba-pl011: Pass FIQ information to KGDB Daniel Thompson ` (4 subsequent siblings) 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, Ben Dooks, David A. Long, linux-serial, Catalin Marinas, kernel-team, Dave Martin, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner From: Anton Vorontsov <anton.vorontsov@linaro.org> The FIQ debugger may be used to debug situations when the kernel stuck in uninterruptable sections, e.g. the kernel infinitely loops or deadlocked in an interrupt or with interrupts disabled. By default KGDB FIQ is disabled in runtime, but can be enabled with kgdb_fiq.enable=1 kernel command line option. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Ben Dooks <ben.dooks@codethink.co.uk> Cc: Dave Martin <Dave.Martin@arm.com> --- arch/arm/Kconfig | 2 + arch/arm/Kconfig.debug | 18 ++++ arch/arm/include/asm/kgdb.h | 7 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/entry-header.S | 186 --------------------------------------- arch/arm/kernel/kgdb_fiq.c | 124 ++++++++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 ++++++++++++++++++ 7 files changed, 239 insertions(+), 186 deletions(-) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 87b63fd..32795c2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -304,6 +304,7 @@ choice config ARCH_MULTIPLATFORM bool "Allow multiple platforms to be selected" depends on MMU + select ARCH_MIGHT_HAVE_KGDB_FIQ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_HAS_SG_CHAIN select ARM_PATCH_PHYS_VIRT @@ -354,6 +355,7 @@ config ARCH_REALVIEW config ARCH_VERSATILE bool "ARM Ltd. Versatile family" + select ARCH_MIGHT_HAVE_KGDB_FIQ select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_AMBA select ARM_TIMER_SP804 diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 26536f7..c7342b6 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -2,6 +2,24 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config ARCH_MIGHT_HAVE_KGDB_FIQ + bool + +config KGDB_FIQ + bool "KGDB FIQ support" + depends on KGDB_KDB && ARCH_MIGHT_HAVE_KGDB_FIQ && !THUMB2_KERNEL + select FIQ + help + The FIQ debugger may be used to debug situations when the + kernel stuck in uninterruptable sections, e.g. the kernel + infinitely loops or deadlocked in an interrupt or with + interrupts disabled. + + By default KGDB FIQ is disabled at runtime, but can be + enabled with kgdb_fiq.enable=1 kernel command line option. + + If unsure, say N. + config ARM_PTDUMP bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 0a9d5dd..5de21f01 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h @@ -11,7 +11,9 @@ #define __ARM_KGDB_H__ #include <linux/ptrace.h> +#include <linux/linkage.h> #include <asm/opcodes.h> +#include <asm/exception.h> /* * GDB assumes that we're a user process being debugged, so @@ -48,6 +50,11 @@ static inline void arch_kgdb_breakpoint(void) extern void kgdb_handle_bus_error(void); extern int kgdb_fault_expected; +extern char kgdb_fiq_handler; +extern char kgdb_fiq_handler_end; +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs); +extern int kgdb_register_fiq(unsigned int fiq); + #endif /* !__ASSEMBLY__ */ /* diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 38ddd9f..30ee8f3 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -68,6 +68,7 @@ endif obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o +obj-$(CONFIG_KGDB_FIQ) += kgdb_fiq_entry.o kgdb_fiq.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_HAVE_TCM) += tcm.o obj-$(CONFIG_OF) += devtree.o diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 572f4b4..eb2c426 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -477,192 +477,6 @@ tsk .req r9 @ current thread_info #endif .endm -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - - .macro usr_entry - UNWIND(.fnstart ) - UNWIND(.cantunwind ) @ don't unwind the user space - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - r12} ) - THUMB( stmia sp, {r0 - r12} ) - - ldmia r0, {r3 - r5} - add r0, sp, #S_PC @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - - str r3, [sp] @ save the "real" r0 copied - @ from the exception stack - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - @ Also, separately save sp_usr and lr_usr - @ - stmia r0, {r4 - r6} - ARM( stmdb r0, {sp, lr}^ ) - THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) - - @ - @ Enable the alignment trap while in kernel mode - @ - alignment_trap r0, .LCcralign - - @ - @ Clear FP to mark the first stack frame - @ - zero_fp - -#ifdef CONFIG_IRQSOFF_TRACER - bl trace_hardirqs_off -#endif - ct_user_exit save = 0 - .endm - - .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ - !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ Make sure our user space atomic helper is restarted - @ if it was interrupted in a critical region. Here we - @ perform a quick test inline since it should be false - @ 99.9999% of the time. The rest is done out of line. - cmp r4, #TASK_SIZE - blhs kuser_cmpxchg64_fixup -#endif -#endif - .endm - -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - - .macro usr_entry - UNWIND(.fnstart ) - UNWIND(.cantunwind ) @ don't unwind the user space - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - r12} ) - THUMB( stmia sp, {r0 - r12} ) - - ldmia r0, {r3 - r5} - add r0, sp, #S_PC @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - - str r3, [sp] @ save the "real" r0 copied - @ from the exception stack - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - @ Also, separately save sp_usr and lr_usr - @ - stmia r0, {r4 - r6} - ARM( stmdb r0, {sp, lr}^ ) - THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) - - @ - @ Enable the alignment trap while in kernel mode - @ - alignment_trap r0, .LCcralign - - @ - @ Clear FP to mark the first stack frame - @ - zero_fp - -#ifdef CONFIG_IRQSOFF_TRACER - bl trace_hardirqs_off -#endif - ct_user_exit save = 0 - .endm - - .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ - !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ Make sure our user space atomic helper is restarted - @ if it was interrupted in a critical region. Here we - @ perform a quick test inline since it should be false - @ 99.9999% of the time. The rest is done out of line. - cmp r4, #TASK_SIZE - blhs kuser_cmpxchg64_fixup -#endif -#endif - .endm - -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - - .macro usr_entry - UNWIND(.fnstart ) - UNWIND(.cantunwind ) @ don't unwind the user space - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - r12} ) - THUMB( stmia sp, {r0 - r12} ) - - ldmia r0, {r3 - r5} - add r0, sp, #S_PC @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - - str r3, [sp] @ save the "real" r0 copied - @ from the exception stack - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - @ Also, separately save sp_usr and lr_usr - @ - stmia r0, {r4 - r6} - ARM( stmdb r0, {sp, lr}^ ) - THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) - - @ - @ Enable the alignment trap while in kernel mode - @ - alignment_trap r0 - - @ - @ Clear FP to mark the first stack frame - @ - zero_fp - -#ifdef CONFIG_IRQSOFF_TRACER - bl trace_hardirqs_off -#endif - ct_user_exit save = 0 - .endm - - .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ - !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ Make sure our user space atomic helper is restarted - @ if it was interrupted in a critical region. Here we - @ perform a quick test inline since it should be false - @ 99.9999% of the time. The rest is done out of line. - cmp r4, #TASK_SIZE - blhs kuser_cmpxchg64_fixup -#endif -#endif - .endm - /* * Vector stubs macro. */ diff --git a/arch/arm/kernel/kgdb_fiq.c b/arch/arm/kernel/kgdb_fiq.c new file mode 100644 index 0000000..dbf4873 --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq.c @@ -0,0 +1,124 @@ +/* + * KGDB FIQ + * + * Copyright 2010 Google, Inc. + * Arve Hjønnevåg <arve@android.com> + * Colin Cross <ccross@android.com> + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov <anton.vorontsov@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <linux/hardirq.h> +#include <linux/atomic.h> +#include <linux/kdb.h> +#include <linux/kgdb.h> +#include <asm/fiq.h> +#include <asm/exception.h> + +static int kgdb_fiq_enabled; +module_param_named(enable, kgdb_fiq_enabled, int, 0600); +MODULE_PARM_DESC(enable, "set to 1 to enable FIQ KGDB"); + +static unsigned int kgdb_fiq; + +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs) +{ + if (kgdb_nmi_poll_knock()) { + nmi_enter(); + kgdb_handle_exception(1, 0, 0, regs); + nmi_exit(); + } + + eoi_fiq(kgdb_fiq); +} + +static struct fiq_handler kgdb_fiq_desc = { + .name = "kgdb", +}; + +static long kgdb_fiq_setup_stack(void *info) +{ + struct pt_regs regs; + + regs.ARM_sp = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER) + + THREAD_START_SP; + WARN_ON(!regs.ARM_sp); + + set_fiq_regs(®s); + return 0; +} + +/** + * kgdb_fiq_enable_nmi - Manage NMI-triggered entry to KGDB + * @on: Flag to either enable or disable an NMI + * + * This function manages NMIs that usually cause KGDB to enter. That is, not + * all NMIs should be enabled or disabled, but only those that issue + * kgdb_handle_exception(). + * + * The call counts disable requests, and thus allows to nest disables. But + * trying to enable already enabled NMI is an error. + */ +static void kgdb_fiq_enable_nmi(bool on) +{ + static atomic_t cnt; + int ret; + + ret = atomic_add_return(on ? 1 : -1, &cnt); + if (ret > 1 && on) { + /* + * There should be only one instance that calls this function + * in "enable, disable" order. All other users must call + * disable first, then enable. If not, something is wrong. + */ + WARN_ON(1); + return; + } + + if (ret > 0) + enable_fiq(kgdb_fiq); + else + disable_fiq(kgdb_fiq); +} + +int kgdb_register_fiq(unsigned int fiq) +{ + int err; + int cpu; + + if (!kgdb_fiq_enabled) + return -ENODEV; + + if (!has_fiq(fiq)) { + pr_warn( + "%s: Cannot register %u (no FIQ with this number)\n", + __func__, fiq); + return -ENODEV; + } + + kgdb_fiq = fiq; + + err = claim_fiq(&kgdb_fiq_desc); + if (err) { + pr_warn("%s: unable to claim fiq", __func__); + return err; + } + + for_each_possible_cpu(cpu) + work_on_cpu(cpu, kgdb_fiq_setup_stack, NULL); + + set_fiq_handler(&kgdb_fiq_handler, + &kgdb_fiq_handler_end - &kgdb_fiq_handler); + + arch_kgdb_ops.enable_nmi = kgdb_fiq_enable_nmi; + return 0; +} diff --git a/arch/arm/kernel/kgdb_fiq_entry.S b/arch/arm/kernel/kgdb_fiq_entry.S new file mode 100644 index 0000000..d6becca --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq_entry.S @@ -0,0 +1,87 @@ +/* + * KGDB FIQ entry + * + * Copyright 1996,1997,1998 Russell King. + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov <anton.vorontsov@linaro.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/memory.h> +#include <asm/unwind.h> +#include "entry-header.S" + + .text + +@ This is needed for usr_entry/alignment_trap +.LCcralign: + .long cr_alignment +.LCdohandle: + .long kgdb_fiq_do_handle + + .macro fiq_handler + ldr r1, =.LCdohandle + mov r0, sp + adr lr, BSYM(9997f) + ldr pc, [r1] +9997: + .endm + + .align 5 +__fiq_svc: + svc_entry + fiq_handler + mov r0, sp + ldmib r0, {r1 - r14} + msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT + add r8, r0, #S_PC + ldr r9, [r0, #S_PSR] + msr spsr_cxsf, r9 + ldr r0, [r0, #S_R0] + ldmia r8, {pc}^ + + UNWIND(.fnend ) +ENDPROC(__fiq_svc) + .ltorg + + .align 5 +__fiq_usr: + usr_entry + kuser_cmpxchg_check + fiq_handler + get_thread_info tsk + mov why, #0 + b ret_to_user_from_irq + UNWIND(.fnend ) +ENDPROC(__fiq_usr) + .ltorg + + .global kgdb_fiq_handler +kgdb_fiq_handler: + + vector_stub fiq, FIQ_MODE, 4 + + .long __fiq_usr @ 0 (USR_26 / USR_32) + .long __fiq_svc @ 1 (FIQ_26 / FIQ_32) + .long __fiq_svc @ 2 (IRQ_26 / IRQ_32) + .long __fiq_svc @ 3 (SVC_26 / SVC_32) + .long __fiq_svc @ 4 + .long __fiq_svc @ 5 + .long __fiq_svc @ 6 + .long __fiq_svc @ 7 + .long __fiq_svc @ 8 + .long __fiq_svc @ 9 + .long __fiq_svc @ a + .long __fiq_svc @ b + .long __fiq_svc @ c + .long __fiq_svc @ d + .long __fiq_svc @ e + .long __fiq_svc @ f + + .global kgdb_fiq_handler_end +kgdb_fiq_handler_end: -- 1.9.3 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 09/13] serial: amba-pl011: Pass FIQ information to KGDB. 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (7 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 08/13] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-20 0:36 ` Greg Kroah-Hartman 2014-06-19 10:38 ` [PATCH v4 10/13] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson ` (3 subsequent siblings) 12 siblings, 1 reply; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman If the AMBA bus has provided the pl011 with a FIQ resource (i.e. a second IRQ) then speculatively register it with KGDB when the polling driver is initialized. By providing this information to KGDB the serial driver offers "permission" for KGDB to route the UART interrupt signal from the drivers own handler to KGDBs FIQ handler (which will eventually use the UART's polled I/O callbacks to interact with the user). This permission also implies the amba-pl011 driver has already unmasked RX interrupts (otherwise the FIQ handler will never trigger). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/amba-pl011.c | 99 ++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 908a6e3..00ba4b6 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -58,6 +58,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/sizes.h> #include <linux/io.h> +#include <linux/kgdb.h> #define UART_NR 14 @@ -1416,8 +1417,63 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&uap->port.lock, flags); } +static int pl011_hwinit(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + int retval; + + /* Optionaly enable pins to be muxed in and configured */ + pinctrl_pm_select_default_state(port->dev); + + /* + * Try to enable the clock producer. + */ + retval = clk_prepare_enable(uap->clk); + if (retval) + goto out; + + uap->port.uartclk = clk_get_rate(uap->clk); + + /* Clear pending error and receive interrupts */ + writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | + UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); + + /* + * Save interrupts enable mask, and enable RX interrupts in case if + * the interrupt is used for NMI entry. + */ + uap->im = readw(uap->port.membase + UART011_IMSC); + writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); + + if (dev_get_platdata(uap->port.dev)) { + struct amba_pl011_data *plat; + + plat = dev_get_platdata(uap->port.dev); + if (plat->init) + plat->init(); + } + return 0; + out: + return retval; +} + #ifdef CONFIG_CONSOLE_POLL +static int pl011_poll_init(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + int retval; + + retval = pl011_hwinit(port); + +#ifdef CONFIG_KGDB_FIQ + if (retval == 0) + kgdb_register_fiq(uap->port.irq); +#endif + + return retval; +} + static void pl011_quiesce_irqs(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -1471,46 +1527,6 @@ static void pl011_put_poll_char(struct uart_port *port, #endif /* CONFIG_CONSOLE_POLL */ -static int pl011_hwinit(struct uart_port *port) -{ - struct uart_amba_port *uap = (struct uart_amba_port *)port; - int retval; - - /* Optionaly enable pins to be muxed in and configured */ - pinctrl_pm_select_default_state(port->dev); - - /* - * Try to enable the clock producer. - */ - retval = clk_prepare_enable(uap->clk); - if (retval) - goto out; - - uap->port.uartclk = clk_get_rate(uap->clk); - - /* Clear pending error and receive interrupts */ - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | - UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); - - /* - * Save interrupts enable mask, and enable RX interrupts in case if - * the interrupt is used for NMI entry. - */ - uap->im = readw(uap->port.membase + UART011_IMSC); - writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); - - if (dev_get_platdata(uap->port.dev)) { - struct amba_pl011_data *plat; - - plat = dev_get_platdata(uap->port.dev); - if (plat->init) - plat->init(); - } - return 0; - out: - return retval; -} - static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) { writew(lcr_h, uap->port.membase + uap->lcrh_rx); @@ -1890,7 +1906,7 @@ static struct uart_ops amba_pl011_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif @@ -2198,6 +2214,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uart_unregister_driver(&amba_reg); pl011_dma_remove(uap); } + out: return ret; } -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH v4 09/13] serial: amba-pl011: Pass FIQ information to KGDB. 2014-06-19 10:38 ` [PATCH v4 09/13] serial: amba-pl011: Pass FIQ information to KGDB Daniel Thompson @ 2014-06-20 0:36 ` Greg Kroah-Hartman 0 siblings, 0 replies; 68+ messages in thread From: Greg Kroah-Hartman @ 2014-06-20 0:36 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, linux-kernel, Colin On Thu, Jun 19, 2014 at 11:38:19AM +0100, Daniel Thompson wrote: > If the AMBA bus has provided the pl011 with a FIQ resource (i.e. a > second IRQ) then speculatively register it with KGDB when the polling > driver is initialized. > > By providing this information to KGDB the serial driver offers > "permission" for KGDB to route the UART interrupt signal from the > drivers own handler to KGDBs FIQ handler (which will eventually use the > UART's polled I/O callbacks to interact with the user). This permission > also implies the amba-pl011 driver has already unmasked RX interrupts > (otherwise the FIQ handler will never trigger). > > Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> > Cc: Russell King <linux@arm.linux.org.uk> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > Cc: Jiri Slaby <jslaby@suse.cz> > Cc: linux-serial@vger.kernel.org > --- Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH v4 10/13] serial: asc: Add support for KGDB's FIQ/NMI mode 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (8 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 09/13] serial: amba-pl011: Pass FIQ information to KGDB Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-20 0:36 ` Greg Kroah-Hartman 2014-06-19 10:38 ` [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() Daniel Thompson ` (2 subsequent siblings) 12 siblings, 1 reply; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Patrice Chotard, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel Add a .poll_init() function that enables UART RX and registers the UART's irq with KGDB. By providing this information to KGDB the serial driver offers "permission" for KGDB to route the UART interrupt signal from the drivers own handler to KGDBs FIQ handler (which will eventually use the UART's polled I/O callbacks to interact with the user). Note that the RX is not only enabled but also unmasked. This is required because otherwise the FIQ handler could never trigger. This unmask is copied from similar code in amba-pl011.c . Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> Cc: Maxime Coquelin <maxime.coquelin@st.com> Cc: Patrice Chotard <patrice.chotard@st.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: kernel@stlinux.com Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/st-asc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index c7f61ac..4f376d8 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -30,6 +30,7 @@ #include <linux/of_platform.h> #include <linux/serial_core.h> #include <linux/clk.h> +#include <linux/kgdb.h> #define DRIVER_NAME "st-asc" #define ASC_SERIAL_NAME "ttyAS" @@ -613,6 +614,25 @@ asc_verify_port(struct uart_port *port, struct serial_struct *ser) } #ifdef CONFIG_CONSOLE_POLL + +#ifdef CONFIG_KGDB_FIQ +/* + * Prepare the UART to be used from kgdb's NMI support. + */ +static int asc_poll_init(struct uart_port *port) +{ + struct asc_port *ascport = container_of(port, struct asc_port, port); + + /* register the FIQ with kgdb */ + kgdb_register_fiq(ascport->port.irq); + + /* enable RX interrupts in case the interrupt is used for NMI entry. */ + asc_enable_rx_interrupts(port); + + return 0; +} +#endif /* CONFIG_KGDB_FIQ */ + /* * Console polling routines for writing and reading from the uart while * in an interrupt or debug context (i.e. kgdb). @@ -656,6 +676,9 @@ static struct uart_ops asc_uart_ops = { .verify_port = asc_verify_port, .pm = asc_pm, #ifdef CONFIG_CONSOLE_POLL +#ifdef CONFIG_KGDB_FIQ + .poll_init = asc_poll_init, +#endif /* CONFIG_KGDB_FIQ */ .poll_get_char = asc_get_poll_char, .poll_put_char = asc_put_poll_char, #endif /* CONFIG_CONSOLE_POLL */ -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH v4 10/13] serial: asc: Add support for KGDB's FIQ/NMI mode 2014-06-19 10:38 ` [PATCH v4 10/13] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson @ 2014-06-20 0:36 ` Greg Kroah-Hartman 0 siblings, 0 replies; 68+ messages in thread From: Greg Kroah-Hartman @ 2014-06-20 0:36 UTC (permalink / raw) To: Daniel Thompson Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Patrice Chotard, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches, Anton Vorontsov, Kumar Gala, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Jason Wessel, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel On Thu, Jun 19, 2014 at 11:38:20AM +0100, Daniel Thompson wrote: > Add a .poll_init() function that enables UART RX and registers the > UART's irq with KGDB. By providing this information to KGDB the serial > driver offers "permission" for KGDB to route the UART interrupt signal > from the drivers own handler to KGDBs FIQ handler (which will eventually > use the UART's polled I/O callbacks to interact with the user). > > Note that the RX is not only enabled but also unmasked. This is required > because otherwise the FIQ handler could never trigger. This unmask is > copied from similar code in amba-pl011.c . > > Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> > Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> > Cc: Maxime Coquelin <maxime.coquelin@st.com> > Cc: Patrice Chotard <patrice.chotard@st.com> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > Cc: Jiri Slaby <jslaby@suse.cz> > Cc: kernel@stlinux.com > Cc: linux-serial@vger.kernel.org > --- Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (9 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 10/13] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 11:29 ` Srinivas Kandagatla 2014-06-19 10:38 ` [PATCH v4 12/13] serial: imx: clean up imx_poll_get_char() Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 13/13] serial: imx: Add support for KGDB's FIQ/NMI mode Daniel Thompson 12 siblings, 1 reply; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Patrice Chotard, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel The architectures supported by this driver have expensive implementations of writel(), reliant on spin locks and explicit L2 cache management. These architectures provide a cheaper writel_relaxed() which is much better suited to peripherals that do not perform DMA. The situation with readl()/readl_relaxed()is similar although less acute. This driver does not use DMA and will be more power efficient and more robust (due to absense of spin locks during console I/O) if it uses the relaxed variants. This driver is cross compilable for testing purposes and remains compilable on all architectures by falling back to writel() when writel_relaxed() does not exist. We also include explicit compiler barriers. There are redundant on ARM and SH but important on x86 because it defines "relaxed" differently. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> Cc: Maxime Coquelin <maxime.coquelin@st.com> Cc: Patrice Chotard <patrice.chotard@st.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: kernel@stlinux.com Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/st-asc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index 4f376d8..58aa1c6 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -152,12 +152,21 @@ static inline struct asc_port *to_asc_port(struct uart_port *port) static inline u32 asc_in(struct uart_port *port, u32 offset) { - return readl(port->membase + offset); + u32 r; + + r = readl_relaxed(port->membase + offset); + barrier(); + return r; } static inline void asc_out(struct uart_port *port, u32 offset, u32 value) { +#ifdef writel_relaxed + writel_relaxed(value, port->membase + offset); + barrier(); +#else writel(value, port->membase + offset); +#endif } /* -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* Re: [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() 2014-06-19 10:38 ` [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() Daniel Thompson @ 2014-06-19 11:29 ` Srinivas Kandagatla 2014-06-19 11:46 ` Daniel Thompson 0 siblings, 1 reply; 68+ messages in thread From: Srinivas Kandagatla @ 2014-06-19 11:29 UTC (permalink / raw) To: Daniel Thompson, Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, linux-kernel, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Colin Cross, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Maxime Coquelin, Greg Hi Dan, On 19/06/14 11:38, Daniel Thompson wrote: > The architectures supported by this driver have expensive > implementations of writel(), reliant on spin locks and explicit L2 cache > management. These architectures provide a cheaper writel_relaxed() which > is much better suited to peripherals that do not perform DMA. The > situation with readl()/readl_relaxed()is similar although less acute. > > This driver does not use DMA and will be more power efficient and more > robust (due to absense of spin locks during console I/O) if it uses the > relaxed variants. > > This driver is cross compilable for testing purposes and remains > compilable on all architectures by falling back to writel() when > writel_relaxed() does not exist. We also include explicit compiler > barriers. There are redundant on ARM and SH but important on > x86 because it defines "relaxed" differently. > Why are we concern about x86 for this driver? As per my understanding this IP is only seen on ARM and SH based CPUs so why cant we just use relaxed versions, why ifdefs? I think, this would involve fixing the kconfig and make it depend on SH and ARM based platforms only. On the other hand, This patch looks more generic and applicable to most of the drivers. Am not sure which way is the right one. --srini > Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> > Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> > Cc: Maxime Coquelin <maxime.coquelin@st.com> > Cc: Patrice Chotard <patrice.chotard@st.com> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> > Cc: Jiri Slaby <jslaby@suse.cz> > Cc: kernel@stlinux.com > Cc: linux-serial@vger.kernel.org > --- > drivers/tty/serial/st-asc.c | 11 ++++++++++- > 1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c > index 4f376d8..58aa1c6 100644 > --- a/drivers/tty/serial/st-asc.c > +++ b/drivers/tty/serial/st-asc.c > @@ -152,12 +152,21 @@ static inline struct asc_port *to_asc_port(struct uart_port *port) > > static inline u32 asc_in(struct uart_port *port, u32 offset) > { > - return readl(port->membase + offset); > + u32 r; > + > + r = readl_relaxed(port->membase + offset); > + barrier(); > + return r; > } > > static inline void asc_out(struct uart_port *port, u32 offset, u32 value) > { > +#ifdef writel_relaxed > + writel_relaxed(value, port->membase + offset); > + barrier(); > +#else > writel(value, port->membase + offset); > +#endif > } > > /* > ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() 2014-06-19 11:29 ` Srinivas Kandagatla @ 2014-06-19 11:46 ` Daniel Thompson 2014-06-19 11:58 ` Maxime Coquelin 2014-06-19 12:01 ` Srinivas Kandagatla 0 siblings, 2 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 11:46 UTC (permalink / raw) To: Srinivas Kandagatla, Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, linux-kernel, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Colin Cross, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Maxime Coquelin, Greg On 19/06/14 12:29, Srinivas Kandagatla wrote: > Hi Dan, > > On 19/06/14 11:38, Daniel Thompson wrote: >> The architectures supported by this driver have expensive >> implementations of writel(), reliant on spin locks and explicit L2 cache >> management. These architectures provide a cheaper writel_relaxed() which >> is much better suited to peripherals that do not perform DMA. The >> situation with readl()/readl_relaxed()is similar although less acute. >> >> This driver does not use DMA and will be more power efficient and more >> robust (due to absense of spin locks during console I/O) if it uses the >> relaxed variants. >> >> This driver is cross compilable for testing purposes and remains >> compilable on all architectures by falling back to writel() when >> writel_relaxed() does not exist. We also include explicit compiler >> barriers. There are redundant on ARM and SH but important on >> x86 because it defines "relaxed" differently. >> > Why are we concern about x86 for this driver? > As per my understanding this IP is only seen on ARM and SH based CPUs so > why cant we just use relaxed versions, why ifdefs? > I think, this would involve fixing the kconfig and make it depend on SH > and ARM based platforms only. You mean just drop the COMPILE_TEST? In generally I like as much code as possible to compile on x86. Its worthwhile protection against the excessive/accidental ARMisms which could easily impact less common architectures (such as SH). > On the other hand, This patch looks more generic and applicable to most > of the drivers. Am not sure which way is the right one. I'm particularly keen on doing the right thing where readl_relaxed() is concerned because this function has a compiler barrier on ARM but not on x86. Since having asc_in/asc_out made it easy to portably make these changes I decided is was better to be redundantly exemplary than conceal secret portability issues. Don't feel that strongly though. Can easily change it if you're unconvinced. > > > --srini > >> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> >> Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> >> Cc: Maxime Coquelin <maxime.coquelin@st.com> >> Cc: Patrice Chotard <patrice.chotard@st.com> >> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> >> Cc: Jiri Slaby <jslaby@suse.cz> >> Cc: kernel@stlinux.com >> Cc: linux-serial@vger.kernel.org >> --- >> drivers/tty/serial/st-asc.c | 11 ++++++++++- >> 1 file changed, 10 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c >> index 4f376d8..58aa1c6 100644 >> --- a/drivers/tty/serial/st-asc.c >> +++ b/drivers/tty/serial/st-asc.c >> @@ -152,12 +152,21 @@ static inline struct asc_port >> *to_asc_port(struct uart_port *port) >> >> static inline u32 asc_in(struct uart_port *port, u32 offset) >> { >> - return readl(port->membase + offset); >> + u32 r; >> + >> + r = readl_relaxed(port->membase + offset); >> + barrier(); >> + return r; >> } >> >> static inline void asc_out(struct uart_port *port, u32 offset, u32 >> value) >> { >> +#ifdef writel_relaxed >> + writel_relaxed(value, port->membase + offset); >> + barrier(); >> +#else >> writel(value, port->membase + offset); >> +#endif >> } >> >> /* >> ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() 2014-06-19 11:46 ` Daniel Thompson @ 2014-06-19 11:58 ` Maxime Coquelin 2014-06-19 12:01 ` Srinivas Kandagatla 1 sibling, 0 replies; 68+ messages in thread From: Maxime Coquelin @ 2014-06-19 11:58 UTC (permalink / raw) To: Daniel Thompson, Srinivas Kandagatla, Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, linux-kernel, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Colin Cross, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman Hi Daniel, On 06/19/2014 01:46 PM, Daniel Thompson wrote: > On 19/06/14 12:29, Srinivas Kandagatla wrote: >> Hi Dan, >> >> On 19/06/14 11:38, Daniel Thompson wrote: >>> The architectures supported by this driver have expensive >>> implementations of writel(), reliant on spin locks and explicit >>> L2 cache management. These architectures provide a cheaper >>> writel_relaxed() which is much better suited to peripherals >>> that do not perform DMA. The situation with >>> readl()/readl_relaxed()is similar although less acute. >>> >>> This driver does not use DMA and will be more power efficient >>> and more robust (due to absense of spin locks during console >>> I/O) if it uses the relaxed variants. >>> >>> This driver is cross compilable for testing purposes and >>> remains compilable on all architectures by falling back to >>> writel() when writel_relaxed() does not exist. We also include >>> explicit compiler barriers. There are redundant on ARM and SH >>> but important on x86 because it defines "relaxed" differently. >>> >> Why are we concern about x86 for this driver? As per my >> understanding this IP is only seen on ARM and SH based CPUs so >> why cant we just use relaxed versions, why ifdefs? I think, this >> would involve fixing the kconfig and make it depend on SH and ARM >> based platforms only. > > You mean just drop the COMPILE_TEST? > > In generally I like as much code as possible to compile on x86. > Its worthwhile protection against the excessive/accidental ARMisms > which could easily impact less common architectures (such as SH). Personally, dropping COMPILE_TEST is what I would prefer. Thanks, Maxime > > >> On the other hand, This patch looks more generic and applicable >> to most of the drivers. Am not sure which way is the right one. > > I'm particularly keen on doing the right thing where > readl_relaxed() is concerned because this function has a compiler > barrier on ARM but not on x86. > > Since having asc_in/asc_out made it easy to portably make these > changes I decided is was better to be redundantly exemplary than > conceal secret portability issues. > > Don't feel that strongly though. Can easily change it if you're > unconvinced. > > > >> >> >> --srini >> >>> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: >>> Srinivas Kandagatla <srinivas.kandagatla@gmail.com> Cc: Maxime >>> Coquelin <maxime.coquelin@st.com> Cc: Patrice Chotard >>> <patrice.chotard@st.com> Cc: Greg Kroah-Hartman >>> <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> >>> Cc: kernel@stlinux.com Cc: linux-serial@vger.kernel.org --- >>> drivers/tty/serial/st-asc.c | 11 ++++++++++- 1 file changed, 10 >>> insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/tty/serial/st-asc.c >>> b/drivers/tty/serial/st-asc.c index 4f376d8..58aa1c6 100644 --- >>> a/drivers/tty/serial/st-asc.c +++ >>> b/drivers/tty/serial/st-asc.c @@ -152,12 +152,21 @@ static >>> inline struct asc_port *to_asc_port(struct uart_port *port) >>> >>> static inline u32 asc_in(struct uart_port *port, u32 offset) { >>> - return readl(port->membase + offset); + u32 r; + + r >>> = readl_relaxed(port->membase + offset); + barrier(); + >>> return r; } >>> >>> static inline void asc_out(struct uart_port *port, u32 offset, >>> u32 value) { +#ifdef writel_relaxed + writel_relaxed(value, >>> port->membase + offset); + barrier(); +#else writel(value, >>> port->membase + offset); +#endif } >>> >>> /* >>> > ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() 2014-06-19 11:46 ` Daniel Thompson 2014-06-19 11:58 ` Maxime Coquelin @ 2014-06-19 12:01 ` Srinivas Kandagatla 2014-06-19 13:12 ` Daniel Thompson 1 sibling, 1 reply; 68+ messages in thread From: Srinivas Kandagatla @ 2014-06-19 12:01 UTC (permalink / raw) To: Daniel Thompson, Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, linux-kernel, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Colin Cross, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Maxime Coquelin, Greg On 19/06/14 12:46, Daniel Thompson wrote: > On 19/06/14 12:29, Srinivas Kandagatla wrote: >> Hi Dan, >> >> On 19/06/14 11:38, Daniel Thompson wrote: >>> The architectures supported by this driver have expensive >>> implementations of writel(), reliant on spin locks and explicit L2 cache >>> management. These architectures provide a cheaper writel_relaxed() which >>> is much better suited to peripherals that do not perform DMA. The >>> situation with readl()/readl_relaxed()is similar although less acute. >>> >>> This driver does not use DMA and will be more power efficient and more >>> robust (due to absense of spin locks during console I/O) if it uses the >>> relaxed variants. >>> >>> This driver is cross compilable for testing purposes and remains >>> compilable on all architectures by falling back to writel() when >>> writel_relaxed() does not exist. We also include explicit compiler >>> barriers. There are redundant on ARM and SH but important on >>> x86 because it defines "relaxed" differently. >>> >> Why are we concern about x86 for this driver? >> As per my understanding this IP is only seen on ARM and SH based CPUs so >> why cant we just use relaxed versions, why ifdefs? >> I think, this would involve fixing the kconfig and make it depend on SH >> and ARM based platforms only. > > You mean just drop the COMPILE_TEST? > > In generally I like as much code as possible to compile on x86. Its > worthwhile protection against the excessive/accidental ARMisms which > could easily impact less common architectures (such as SH). That's fair. Does this mean that we are going do similar changes to other ST drivers too? > TBH, there is no SH based SOCs in mainline which uses this driver. I don't think ST would add SH only SOCs to mainline in near future. > >> On the other hand, This patch looks more generic and applicable to most >> of the drivers. Am not sure which way is the right one. > > I'm particularly keen on doing the right thing where readl_relaxed() is > concerned because this function has a compiler barrier on ARM but not on > x86. > My only concern is code duplication all across ST drivers. > Since having asc_in/asc_out made it easy to portably make these changes > I decided is was better to be redundantly exemplary than conceal secret > portability issues. Your change would fit in nicely with as asc_in/out are wrappers and fix st-asc but this would be just for asc driver. What about other drivers which fall in same category? So I think we should just drop COMPILE_TEST and possibly make it specific to ARM and SH or ARM only. --srini > > Don't feel that strongly though. Can easily change it if you're unconvinced. > > > >> >> >> --srini >> >>> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> >>> Cc: Srinivas Kandagatla <srinivas.kandagatla@gmail.com> >>> Cc: Maxime Coquelin <maxime.coquelin@st.com> >>> Cc: Patrice Chotard <patrice.chotard@st.com> >>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> >>> Cc: Jiri Slaby <jslaby@suse.cz> >>> Cc: kernel@stlinux.com >>> Cc: linux-serial@vger.kernel.org >>> --- >>> drivers/tty/serial/st-asc.c | 11 ++++++++++- >>> 1 file changed, 10 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c >>> index 4f376d8..58aa1c6 100644 >>> --- a/drivers/tty/serial/st-asc.c >>> +++ b/drivers/tty/serial/st-asc.c >>> @@ -152,12 +152,21 @@ static inline struct asc_port >>> *to_asc_port(struct uart_port *port) >>> >>> static inline u32 asc_in(struct uart_port *port, u32 offset) >>> { >>> - return readl(port->membase + offset); >>> + u32 r; >>> + >>> + r = readl_relaxed(port->membase + offset); >>> + barrier(); >>> + return r; >>> } >>> >>> static inline void asc_out(struct uart_port *port, u32 offset, u32 >>> value) >>> { >>> +#ifdef writel_relaxed >>> + writel_relaxed(value, port->membase + offset); >>> + barrier(); >>> +#else >>> writel(value, port->membase + offset); >>> +#endif >>> } >>> >>> /* >>> > ^ permalink raw reply [flat|nested] 68+ messages in thread
* Re: [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() 2014-06-19 12:01 ` Srinivas Kandagatla @ 2014-06-19 13:12 ` Daniel Thompson 0 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 13:12 UTC (permalink / raw) To: Srinivas Kandagatla, Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, linux-kernel, Jiri Slaby, Dirk Behme, Russell King, Nicolas Pitre, patches, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, Ian Campbell, Colin Cross, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Maxime Coquelin, Greg On 19/06/14 13:01, Srinivas Kandagatla wrote: >>> Why are we concern about x86 for this driver? >>> As per my understanding this IP is only seen on ARM and SH based CPUs so >>> why cant we just use relaxed versions, why ifdefs? >>> I think, this would involve fixing the kconfig and make it depend on SH >>> and ARM based platforms only. >> >> You mean just drop the COMPILE_TEST? >> >> In generally I like as much code as possible to compile on x86. Its >> worthwhile protection against the excessive/accidental ARMisms which >> could easily impact less common architectures (such as SH). > > That's fair. Does this mean that we are going do similar changes to > other ST drivers too? I didn't give any thought at all to other ST drivers. I don't see why a *general* preference (of mine or anyone else) would override what is right for any particular driver. I don't think "both manage ST peripherals" means drivers have much in common. >>> On the other hand, This patch looks more generic and applicable to most >>> of the drivers. Am not sure which way is the right one. >> >> I'm particularly keen on doing the right thing where readl_relaxed() is >> concerned because this function has a compiler barrier on ARM but not on >> x86. >> > My only concern is code duplication all across ST drivers. I really struggle to understand this. Why would anyone copy code out of the asc driver into the network driver (or any other ST driver)? >> Since having asc_in/asc_out made it easy to portably make these changes >> I decided is was better to be redundantly exemplary than conceal secret >> portability issues. > Your change would fit in nicely with as asc_in/out are wrappers and fix > st-asc but this would be just for asc driver. > What about other drivers which fall in same category? > > So I think we should just drop COMPILE_TEST and possibly make it > specific to ARM and SH or ARM only. I'm slightly uneasy about this primarily because all the rationale above describes a concern about drivers other than the one I seek to change. They ought to be outside the scope of this change. Nevertheless, since I said I don't feel that strongly about it, as you wish... I'll change this in v5. ^ permalink raw reply [flat|nested] 68+ messages in thread
* [PATCH v4 12/13] serial: imx: clean up imx_poll_get_char() 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (10 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 13/13] serial: imx: Add support for KGDB's FIQ/NMI mode Daniel Thompson 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman From: Dirk Behme <dirk.behme@de.bosch.com> Looking at the get_poll_char() function of the 8250.c serial driver, we learn: * poll_get_char() doesn't have to save/disable/restore the interrupt registers. No interrupt handling is needed in this function at all. Remove it. * Don't block in case there is no data available. So instead blocking in the do {} while loop, just return with NO_POLL_CHAR, immediately . Additionally, while the i.MX6 register URXD[7-0] contain the RX_DATA, the upper bits of this register (URXD[15-10]) might contain some control flags. To ensure that these are not returned with the data read, just mask out URXD[7-0]. These changes fix the 'hang' working with kdb: $ echo ttymxc3 > /sys/module/kgdboc/parameters/kgdboc $ echo g >/proc/sysrq-trigger [0]kdb> help ... <hang> Signed-off-by: Dirk Behme <dirk.behme@de.bosch.com> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/imx.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e2f9387..25ed1d2 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -80,6 +80,7 @@ #define URXD_FRMERR (1<<12) #define URXD_BRK (1<<11) #define URXD_PRERR (1<<10) +#define URXD_RX_DATA (0xFF<<0) #define UCR1_ADEN (1<<15) /* Auto detect interrupt */ #define UCR1_ADBR (1<<14) /* Auto detect baud rate */ #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ @@ -1503,32 +1504,10 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser) #if defined(CONFIG_CONSOLE_POLL) static int imx_poll_get_char(struct uart_port *port) { - struct imx_port_ucrs old_ucr; - unsigned int status; - unsigned char c; - - /* save control registers */ - imx_port_ucrs_save(port, &old_ucr); - - /* disable interrupts */ - writel(UCR1_UARTEN, port->membase + UCR1); - writel(old_ucr.ucr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI), - port->membase + UCR2); - writel(old_ucr.ucr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), - port->membase + UCR3); - - /* poll */ - do { - status = readl(port->membase + USR2); - } while (~status & USR2_RDR); - - /* read */ - c = readl(port->membase + URXD0); - - /* restore control registers */ - imx_port_ucrs_restore(port, &old_ucr); + if (!(readl(port->membase + USR2) & USR2_RDR)) + return NO_POLL_CHAR; - return c; + return readl(port->membase + URXD0) & URXD_RX_DATA; } static void imx_poll_put_char(struct uart_port *port, unsigned char c) -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
* [PATCH v4 13/13] serial: imx: Add support for KGDB's FIQ/NMI mode 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson ` (11 preceding siblings ...) 2014-06-19 10:38 ` [PATCH v4 12/13] serial: imx: clean up imx_poll_get_char() Daniel Thompson @ 2014-06-19 10:38 ` Daniel Thompson 12 siblings, 0 replies; 68+ messages in thread From: Daniel Thompson @ 2014-06-19 10:38 UTC (permalink / raw) To: Jason Wessel Cc: Mark Rutland, kernel, kgdb-bugreport, Linus Walleij, Jiri Slaby, Daniel Thompson, Dirk Behme, Russell King, Nicolas Pitre, Ian Campbell, Anton Vorontsov, David A. Long, linux-serial, Catalin Marinas, kernel-team, devicetree, linaro-kernel, Pawel Moll, patches, Kumar Gala, Rob Herring, John Stultz, Thomas Gleixner, linux-arm-kernel, Greg Kroah-Hartman This patch makes it possible to use the imx uart with KGDB's FIQ/NMI mode. Main changes are: .poll_init() will, if KGDB+FIQ are enabled, perform deeper hardware initialization to ensure the serial port is always active (required otherwise FIQ is not triggered by UART activity). This has an impact on power usage so it is conservatively enabled. imx_put_poll_char() has been simplified to remove the code to disable interrupts. The present code can corrupt register state when re-entered from FIQ handler. Both imx_put_poll_char() and imx_get_poll_char() adopt _relaxed() MMIO functions (which are safe for polled I/O and needed to avoid taking spin locks). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Cc: linux-serial@vger.kernel.org --- drivers/tty/serial/imx.c | 71 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 25ed1d2..a2baf7e 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -49,6 +49,7 @@ #include <linux/of_device.h> #include <linux/io.h> #include <linux/dma-mapping.h> +#include <linux/kgdb.h> #include <asm/irq.h> #include <linux/platform_data/serial-imx.h> @@ -1502,44 +1503,73 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser) } #if defined(CONFIG_CONSOLE_POLL) + +#if defined(CONFIG_KGDB_FIQ) +/* + * Prepare the UART to be used from kgdb's NMI support. + */ +static int imx_poll_init(struct uart_port *port) +{ + struct imx_port *sport = (struct imx_port *)port; + unsigned long flags; + unsigned long temp; + int retval; + + retval = clk_prepare_enable(sport->clk_ipg); + if (retval) + return retval; + retval = clk_prepare_enable(sport->clk_per); + if (retval) + clk_disable_unprepare(sport->clk_ipg); + + imx_setup_ufcr(sport, 0); + + spin_lock_irqsave(&sport->port.lock, flags); + + temp = readl(sport->port.membase + UCR1); + if (is_imx1_uart(sport)) + temp |= IMX1_UCR1_UARTCLKEN; + temp |= UCR1_UARTEN | UCR1_RRDYEN; + temp &= ~(UCR1_TXMPTYEN | UCR1_RTSDEN); + writel(temp, sport->port.membase + UCR1); + + temp = readl(sport->port.membase + UCR2); + temp |= UCR2_RXEN; + writel(temp, sport->port.membase + UCR2); + + spin_unlock_irqrestore(&sport->port.lock, flags); + + /* register the FIQ with kgdb */ + kgdb_register_fiq(sport->port.irq); + + return 0; +} +#endif /* CONFIG_KGDB_FIQ */ + static int imx_poll_get_char(struct uart_port *port) { - if (!(readl(port->membase + USR2) & USR2_RDR)) + if (!(readl_relaxed(port->membase + USR2) & USR2_RDR)) return NO_POLL_CHAR; - return readl(port->membase + URXD0) & URXD_RX_DATA; + return readl_relaxed(port->membase + URXD0) & URXD_RX_DATA; } static void imx_poll_put_char(struct uart_port *port, unsigned char c) { - struct imx_port_ucrs old_ucr; unsigned int status; - /* save control registers */ - imx_port_ucrs_save(port, &old_ucr); - - /* disable interrupts */ - writel(UCR1_UARTEN, port->membase + UCR1); - writel(old_ucr.ucr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI), - port->membase + UCR2); - writel(old_ucr.ucr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), - port->membase + UCR3); - /* drain */ do { - status = readl(port->membase + USR1); + status = readl_relaxed(port->membase + USR1); } while (~status & USR1_TRDY); /* write */ - writel(c, port->membase + URTX0); + writel_relaxed(c, port->membase + URTX0); /* flush */ do { - status = readl(port->membase + USR2); + status = readl_relaxed(port->membase + USR2); } while (~status & USR2_TXDC); - - /* restore control registers */ - imx_port_ucrs_restore(port, &old_ucr); } #endif @@ -1560,6 +1590,9 @@ static struct uart_ops imx_pops = { .config_port = imx_config_port, .verify_port = imx_verify_port, #if defined(CONFIG_CONSOLE_POLL) +#if defined(CONFIG_KGDB_FIQ) + .poll_init = imx_poll_init, +#endif .poll_get_char = imx_poll_get_char, .poll_put_char = imx_poll_put_char, #endif -- 1.9.3 ^ permalink raw reply related [flat|nested] 68+ messages in thread
end of thread, other threads:[~2014-06-20 0:36 UTC | newest] Thread overview: 68+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-05-14 15:58 [RFC 0/8] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-05-14 15:58 ` [RFC 1/8] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson 2014-05-14 15:58 ` [RFC 2/8] irqchip: gic: Provide support for interrupt grouping Daniel Thompson 2014-05-14 15:58 ` [RFC 3/8] ARM: Move some macros from entry-armv to entry-header Daniel Thompson 2014-05-14 15:58 ` [RFC 4/8] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson 2014-05-14 15:58 ` [RFC 5/8] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson 2014-05-14 15:58 ` [RFC 6/8] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson 2014-05-14 15:58 ` [RFC 7/8] ARM: VIC: Add vic_set_fiq function to select if an interrupt should generate an IRQ or FIQ Daniel Thompson 2014-05-14 15:58 ` [RFC 8/8] arm: fiq: Hack FIQ routing backdoors into GIC and VIC Daniel Thompson 2014-05-23 13:57 ` [RFC v2 00/10] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-05-23 13:57 ` [RFC v2 01/10] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson 2014-05-23 14:59 ` Srinivas Kandagatla 2014-05-23 15:00 ` Russell King - ARM Linux 2014-05-28 15:47 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 02/10] irqchip: gic: Provide support for interrupt grouping Daniel Thompson 2014-05-23 13:57 ` [RFC v2 03/10] irqchip: gic: Introduce shadow irqs for FIQ Daniel Thompson 2014-05-23 13:57 ` [RFC v2 04/10] ARM: vexpress: Extend UART with FIQ support Daniel Thompson 2014-05-23 15:04 ` Russell King - ARM Linux 2014-05-29 10:31 ` Daniel Thompson 2014-05-29 13:44 ` Rob Herring 2014-06-03 12:41 ` Daniel Thompson 2014-05-23 13:57 ` [RFC v2 05/10] ARM: STi: STiH41x: " Daniel Thompson 2014-05-23 13:57 ` [RFC v2 06/10] irqchip: vic: Introduce shadow irqs for FIQ Daniel Thompson 2014-05-23 13:57 ` [RFC v2 07/10] ARM: Move some macros from entry-armv to entry-header Daniel Thompson 2014-05-23 13:57 ` [RFC v2 08/10] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson 2014-05-23 13:57 ` [RFC v2 09/10] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson 2014-05-23 13:57 ` [RFC v2 10/10] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson 2014-05-23 14:50 ` Srinivas Kandagatla 2014-06-05 9:53 ` [RFC v3 0/9] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-06-05 9:53 ` [RFC v3 1/9] arm: fiq: arbitrary mappings from IRQ to FIQ virqs Daniel Thompson 2014-06-05 11:51 ` Russell King - ARM Linux 2014-06-05 13:08 ` Daniel Thompson 2014-06-12 8:37 ` Linus Walleij 2014-06-12 9:54 ` Daniel Thompson 2014-06-13 14:29 ` Rob Herring 2014-06-18 11:24 ` Daniel Thompson 2014-06-05 9:53 ` [RFC v3 2/9] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson 2014-06-05 9:53 ` [RFC v3 3/9] irqchip: gic: Provide support for interrupt grouping Daniel Thompson 2014-06-05 19:50 ` Nicolas Pitre 2014-06-05 9:53 ` [RFC v3 4/9] irqchip: gic: Introduce shadow irqs for FIQ Daniel Thompson 2014-06-06 7:46 ` Peter De Schrijver 2014-06-06 9:23 ` Daniel Thompson 2014-06-05 9:53 ` [RFC v3 5/9] irqchip: vic: " Daniel Thompson 2014-06-05 9:53 ` [RFC v3 6/9] ARM: Move some macros from entry-armv to entry-header Daniel Thompson 2014-06-05 9:53 ` [RFC v3 7/9] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson 2014-06-05 9:53 ` [RFC v3 8/9] serial: amba-pl011: Pass on FIQ information to KGDB Daniel Thompson 2014-06-05 9:53 ` [RFC v3 9/9] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 00/13] kgdb: NMI/FIQ support for ARM Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 01/13] arm: fiq: Add callbacks to manage FIQ routings Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 02/13] arm: fiq: Allow EOI to be communicated to the intc Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 03/13] irqchip: gic: Provide support for interrupt grouping Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 04/13] irqchip: gic: Add support for FIQ management Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 05/13] irqchip: gic: Remove spin locks from eoi_irq Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 06/13] irqchip: vic: Add support for FIQ management Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 07/13] ARM: Move some macros from entry-armv to entry-header Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 08/13] ARM: Add KGDB/KDB FIQ debugger generic code Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 09/13] serial: amba-pl011: Pass FIQ information to KGDB Daniel Thompson 2014-06-20 0:36 ` Greg Kroah-Hartman 2014-06-19 10:38 ` [PATCH v4 10/13] serial: asc: Add support for KGDB's FIQ/NMI mode Daniel Thompson 2014-06-20 0:36 ` Greg Kroah-Hartman 2014-06-19 10:38 ` [PATCH v4 11/13] serial: asc: Adopt readl_/writel_relaxed() Daniel Thompson 2014-06-19 11:29 ` Srinivas Kandagatla 2014-06-19 11:46 ` Daniel Thompson 2014-06-19 11:58 ` Maxime Coquelin 2014-06-19 12:01 ` Srinivas Kandagatla 2014-06-19 13:12 ` Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 12/13] serial: imx: clean up imx_poll_get_char() Daniel Thompson 2014-06-19 10:38 ` [PATCH v4 13/13] serial: imx: Add support for KGDB's FIQ/NMI mode Daniel Thompson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).