Thread (8 messages) 8 messages, 5 authors, 2020-10-15
STALE2076d

[PATCH 2/3] arm: introduce IRQ stacks

From: Maninder Singh <hidden>
Date: 2020-10-08 07:17:57
Also in: lkml
Subsystem: arm port, the rest · Maintainers: Russell King, Linus Torvalds

Possibly related (same subject, not in this thread)

This patch adds code for switching to IRQ stack.
IRQ stack and Kernel SVC stack have below design.

IRQ STACK:-
                    ------------ IRQ stack top
                    |          |
                    ------------
                    .          .
                    .          .
                    .          .
                    ------------
                    |    sp    | <- irq_stack_base + 0x8
                    ------------
                    |    fp    | <- irq_stack_base + 0x4
                    ------------
                    |tinfo_ptr | /* pointer to thread info */
irq_stack_ptr -->   ------------ IRQ stack base

Kernel SVC stack:-
                    ------------  Kernel stack top
                    |          |
                    ------------
                    .          .
                    .          .
                    .          .
                    ------------
                    |          |
                    |          |
                    ------------
                    |tinfo_ptr |  /* pointer to thread info */
                    ------------ Kernel stack base

Co-developed-by: Vaneet Narang <redacted>
Signed-off-by: Vaneet Narang <redacted>
Signed-off-by: Maninder Singh <redacted>
---
 arch/arm/include/asm/assembler.h |  8 ++++++++
 arch/arm/include/asm/irq.h       |  6 ++++++
 arch/arm/kernel/entry-armv.S     | 41 +++++++++++++++++++++++++++++++++++++++-
 arch/arm/kernel/irq.c            | 24 +++++++++++++++++++++++
 4 files changed, 78 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 8512bdc..82ee6ee 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -212,6 +212,14 @@
 #endif
 	.endm
 
+	.macro	this_cpu_ptr, sym, reg, tmp
+	ldr	\reg, =\sym
+#if defined(CONFIG_SMP) && !defined(CONFIG_CPU_V6)
+	mrc	p15, 0, \tmp, cr13, c0, 4
+	add	\reg, \reg, \tmp
+#endif
+	.endm
+
 /*
  * Increment/decrement the preempt count.
  */
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 46d4114..f3299ab 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -22,10 +22,16 @@
 #define NO_IRQ	((unsigned int)(-1))
 #endif
 
+#define IRQ_STACK_SIZE	THREAD_SIZE
+
 #ifndef __ASSEMBLY__
 struct irqaction;
 struct pt_regs;
 
+#ifdef CONFIG_IRQ_STACK
+DECLARE_PER_CPU(unsigned long *, irq_stack_ptr);
+#endif
+
 extern void asm_do_IRQ(unsigned int, struct pt_regs *);
 void handle_IRQ(unsigned int, struct pt_regs *);
 void init_IRQ(void);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 55a47df..13a5889 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -32,6 +32,43 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#ifdef CONFIG_IRQ_STACK
+#include <asm/irq.h>
+#endif
+
+	.macro  irq_stack_entry
+#ifdef CONFIG_IRQ_STACK
+	mov	r6, sp	/* preserve sp */
+
+	this_cpu_ptr irq_stack_ptr, r7, r8
+	ldr	r7, [r7]
+	mov	r8, r7
+
+	/*
+	 * Compare sp with base of IRQ stack.
+	 * if the top ~(#THREAD_SIZE_ORDER + PAGE_SHIFT) bits match,
+	 * we are on a irq stack.
+	 */
+	eor	r8, r8, sp
+	lsrs	r8, #THREAD_SIZE_ORDER + PAGE_SHIFT
+	beq	9998f
+
+	/*
+	 * store thread info pointer on IRQ stack and
+	 * switch to the irq stack.
+	 */
+	get_thread_info r8
+	stm	r7, {r8, fp, sp}
+	add	sp, r7, #IRQ_STACK_SIZE
+9998:
+#endif
+        .endm
+
+	.macro	irq_stack_exit
+#ifdef CONFIG_IRQ_STACK
+	mov	sp, r6	/* restore sp */
+#endif
+       .endm
 
 /*
  * Interrupt handling.
@@ -41,11 +78,13 @@
 	ldr	r1, =handle_arch_irq
 	mov	r0, sp
 	badr	lr, 9997f
+	irq_stack_entry
 	ldr	pc, [r1]
+9997:
+	irq_stack_exit
 #else
 	arch_irq_handler_default
 #endif
-9997:
 	.endm
 
 	.macro	pabt_helper
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 698b6f6..79872e5 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -43,6 +43,15 @@
 
 unsigned long irq_err_count;
 
+#ifdef CONFIG_IRQ_STACK
+DEFINE_PER_CPU(unsigned long *, irq_stack_ptr);
+
+/*
+ * irq_stack must be IRQ_STACK_SIZE(THREAD_SIZE) aligned,
+ */
+DEFINE_PER_CPU(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack) __aligned(IRQ_STACK_SIZE);
+#endif
+
 int arch_show_interrupts(struct seq_file *p, int prec)
 {
 #ifdef CONFIG_FIQ
@@ -55,6 +64,20 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 	return 0;
 }
 
+#ifdef CONFIG_IRQ_STACK
+static void init_irq_stacks(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		per_cpu(irq_stack_ptr, cpu) = per_cpu(irq_stack, cpu);
+}
+#else
+static inline void init_irq_stacks(void)
+{
+}
+#endif
+
 /*
  * handle_IRQ handles all hardware IRQ's.  Decoded IRQs should
  * not come via this function.  Instead, they should provide their
@@ -79,6 +102,7 @@ void __init init_IRQ(void)
 {
 	int ret;
 
+	init_irq_stacks();
 	if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq)
 		irqchip_init();
 	else
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help