diff options
author | Helge Deller <deller@gmx.de> | 2013-05-07 22:25:42 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2013-05-07 22:30:35 +0200 |
commit | 200c880420a2c02a0899120ce52d801fad705b90 (patch) | |
tree | c7f206861dbe5707fe319122bee0eabb67da7b9f /arch/parisc/kernel/irq.c | |
parent | parisc: add kernel stack overflow check (diff) | |
download | linux-200c880420a2c02a0899120ce52d801fad705b90.tar.xz linux-200c880420a2c02a0899120ce52d801fad705b90.zip |
parisc: implement irq stacks
Default kernel stack size on parisc is 16k. During tests we found that the
kernel stack can easily grow beyond 13k, which leaves 3k left for irq
processing.
This patch adds the possibility to activate an additional stack of 16k per CPU
which is being used during irq processing. This implementation does not yet
uses this irq stack for the irq bh handler.
The assembler code for call_on_stack was heavily cleaned up by John
David Anglin.
CC: John David Anglin <dave.anglin@bell.net>
Signed-off-by: Helge Deller <deller@gmx.de>
Diffstat (limited to 'arch/parisc/kernel/irq.c')
-rw-r--r-- | arch/parisc/kernel/irq.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 61e51ac85659..810f9cf89e48 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -358,6 +358,29 @@ static inline void stack_overflow_check(struct pt_regs *regs) #endif } +#ifdef CONFIG_IRQSTACKS +DEFINE_PER_CPU(union irq_stack_union, irq_stack_union); + +static void execute_on_irq_stack(void *func, unsigned long param1) +{ + unsigned long *irq_stack_start; + unsigned long irq_stack; + int cpu = smp_processor_id(); + + irq_stack_start = &per_cpu(irq_stack_union, cpu).stack[0]; + irq_stack = (unsigned long) irq_stack_start; + irq_stack = ALIGN(irq_stack, 16); /* align for stack frame usage */ + + BUG_ON(*irq_stack_start); /* report bug if we were called recursive. */ + *irq_stack_start = 1; + + /* This is where we switch to the IRQ stack. */ + call_on_stack(param1, func, irq_stack); + + *irq_stack_start = 0; +} +#endif /* CONFIG_IRQSTACKS */ + /* ONLY called from entry.S:intr_extint() */ void do_cpu_irq_mask(struct pt_regs *regs) { @@ -393,7 +416,12 @@ void do_cpu_irq_mask(struct pt_regs *regs) } #endif stack_overflow_check(regs); + +#ifdef CONFIG_IRQSTACKS + execute_on_irq_stack(&generic_handle_irq, irq); +#else generic_handle_irq(irq); +#endif /* CONFIG_IRQSTACKS */ out: irq_exit(); |