diff options
author | Felix Fietkau <nbd@nbd.name> | 2017-01-11 10:57:49 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2017-01-15 18:25:54 +0100 |
commit | 1708644f1915eb7587a904d81da0ef0b559d1567 (patch) | |
tree | 15fd746c87d428ef513ee95fc69ded44fbf7e2ea /target/linux/generic/patches-4.4/062-01-MIPS-Introduce-irq_stack.patch | |
parent | b02636fcb4b16d437442f817a60a30e9b7ce4ed2 (diff) | |
download | upstream-1708644f1915eb7587a904d81da0ef0b559d1567.tar.gz upstream-1708644f1915eb7587a904d81da0ef0b559d1567.tar.bz2 upstream-1708644f1915eb7587a904d81da0ef0b559d1567.zip |
kernel: backport MIPS changes introducing a separate IRQ stack
Prevents crashes when IRQs arrive when the current kernel stack context
already contains deeply nested function calls, e.g. when stacking lots
of network devices on top of each other
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'target/linux/generic/patches-4.4/062-01-MIPS-Introduce-irq_stack.patch')
-rw-r--r-- | target/linux/generic/patches-4.4/062-01-MIPS-Introduce-irq_stack.patch | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/target/linux/generic/patches-4.4/062-01-MIPS-Introduce-irq_stack.patch b/target/linux/generic/patches-4.4/062-01-MIPS-Introduce-irq_stack.patch new file mode 100644 index 0000000000..2a929aa7e1 --- /dev/null +++ b/target/linux/generic/patches-4.4/062-01-MIPS-Introduce-irq_stack.patch @@ -0,0 +1,70 @@ +From: Matt Redfearn <matt.redfearn@imgtec.com> +Date: Mon, 19 Dec 2016 14:20:56 +0000 +Subject: [PATCH] MIPS: Introduce irq_stack + +Allocate a per-cpu irq stack for use within interrupt handlers. + +Also add a utility function on_irq_stack to determine if a given stack +pointer is within the irq stack for that cpu. + +Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com> +--- + +--- a/arch/mips/include/asm/irq.h ++++ b/arch/mips/include/asm/irq.h +@@ -17,6 +17,18 @@ + + #include <irq.h> + ++#define IRQ_STACK_SIZE THREAD_SIZE ++ ++extern void *irq_stack[NR_CPUS]; ++ ++static inline bool on_irq_stack(int cpu, unsigned long sp) ++{ ++ unsigned long low = (unsigned long)irq_stack[cpu]; ++ unsigned long high = low + IRQ_STACK_SIZE; ++ ++ return (low <= sp && sp <= high); ++} ++ + #ifdef CONFIG_I8259 + static inline int irq_canonicalize(int irq) + { +--- a/arch/mips/kernel/asm-offsets.c ++++ b/arch/mips/kernel/asm-offsets.c +@@ -101,6 +101,7 @@ void output_thread_info_defines(void) + OFFSET(TI_REGS, thread_info, regs); + DEFINE(_THREAD_SIZE, THREAD_SIZE); + DEFINE(_THREAD_MASK, THREAD_MASK); ++ DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); + BLANK(); + } + +--- a/arch/mips/kernel/irq.c ++++ b/arch/mips/kernel/irq.c +@@ -25,6 +25,8 @@ + #include <linux/atomic.h> + #include <asm/uaccess.h> + ++void *irq_stack[NR_CPUS]; ++ + /* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves. +@@ -55,6 +57,15 @@ void __init init_IRQ(void) + irq_set_noprobe(i); + + arch_init_irq(); ++ ++ for_each_possible_cpu(i) { ++ int irq_pages = IRQ_STACK_SIZE / PAGE_SIZE; ++ void *s = (void *)__get_free_pages(GFP_KERNEL, irq_pages); ++ ++ irq_stack[i] = s; ++ pr_debug("CPU%d IRQ stack at 0x%p - 0x%p\n", i, ++ irq_stack[i], irq_stack[i] + IRQ_STACK_SIZE); ++ } + } + + #ifdef CONFIG_DEBUG_STACKOVERFLOW |