1708644f19
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>
70 lines
1.8 KiB
Diff
70 lines
1.8 KiB
Diff
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
|