parisc: implement irq stacks
Helge Deller
maintainerPATCH 1/1 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 <[email protected]>
Signed-off-by Helge Deller <[email protected]>
arch/parisc/Kconfig +8 -0
@@ -243,6 +243,14 @@ config SMP If you don't know what to do here, say N. +config IRQSTACKS + bool "Use separate kernel stacks when processing interrupts" + default n + help + If you say Y here the kernel will use separate kernel stacks + for handling hard and soft interrupts. This can help avoid + overflowing the process kernel stacks. + config HOTPLUG_CPU bool default y if SMP
arch/parisc/include/asm/processor.h +17 -2
@@ -20,8 +20,6 @@#endif /* __ASSEMBLY__ */ -#define KERNEL_STACK_SIZE (4*PAGE_SIZE) -/* * Default implementation of macro that returns current * instruction pointer ("program counter").
@@ -61,6 +59,23 @@#ifndef __ASSEMBLY__/* +* IRQ STACK - used for irq handler +*/ +#ifdef __KERNEL__ + +#define IRQ_STACK_SIZE (4096 << 2)/* 16k irq stack size */ + +union irq_stack_union { +unsigned long stack[IRQ_STACK_SIZE /sizeof (unsigned long )]; +}; + +DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); + +void call_on_stack (unsigned long p1,void *func,unsigned long new_stack); + +#endif /* __KERNEL__ */ + +/* * Data detected about CPUs at boot time which is the same for all CPU's. * HP boxes are SMP - ie identical processors. *
arch/parisc/kernel/entry.S +41 -0
47 lines not on this page · raw message
arch/parisc/kernel/irq.c +28 -0
@@ -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 ();