aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2013-05-07 16:25:42 -0400
committerHelge Deller <deller@gmx.de>2013-05-07 16:30:35 -0400
commit200c880420a2c02a0899120ce52d801fad705b90 (patch)
treec7f206861dbe5707fe319122bee0eabb67da7b9f /arch
parent9372450cc22d185f708e5cc3557cf991be4b7dc5 (diff)
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')
-rw-r--r--arch/parisc/Kconfig8
-rw-r--r--arch/parisc/include/asm/processor.h19
-rw-r--r--arch/parisc/kernel/entry.S41
-rw-r--r--arch/parisc/kernel/irq.c28
4 files changed, 94 insertions, 2 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index fe4afb0f152f..cad060f288cf 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -243,6 +243,14 @@ config SMP
243 243
244 If you don't know what to do here, say N. 244 If you don't know what to do here, say N.
245 245
246config IRQSTACKS
247 bool "Use separate kernel stacks when processing interrupts"
248 default n
249 help
250 If you say Y here the kernel will use separate kernel stacks
251 for handling hard and soft interrupts. This can help avoid
252 overflowing the process kernel stacks.
253
246config HOTPLUG_CPU 254config HOTPLUG_CPU
247 bool 255 bool
248 default y if SMP 256 default y if SMP
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 09b54a57a48d..242f06a5fbd8 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -20,8 +20,6 @@
20 20
21#endif /* __ASSEMBLY__ */ 21#endif /* __ASSEMBLY__ */
22 22
23#define KERNEL_STACK_SIZE (4*PAGE_SIZE)
24
25/* 23/*
26 * Default implementation of macro that returns current 24 * Default implementation of macro that returns current
27 * instruction pointer ("program counter"). 25 * instruction pointer ("program counter").
@@ -61,6 +59,23 @@
61#ifndef __ASSEMBLY__ 59#ifndef __ASSEMBLY__
62 60
63/* 61/*
62 * IRQ STACK - used for irq handler
63 */
64#ifdef __KERNEL__
65
66#define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */
67
68union irq_stack_union {
69 unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
70};
71
72DECLARE_PER_CPU(union irq_stack_union, irq_stack_union);
73
74void call_on_stack(unsigned long p1, void *func, unsigned long new_stack);
75
76#endif /* __KERNEL__ */
77
78/*
64 * Data detected about CPUs at boot time which is the same for all CPU's. 79 * Data detected about CPUs at boot time which is the same for all CPU's.
65 * HP boxes are SMP - ie identical processors. 80 * HP boxes are SMP - ie identical processors.
66 * 81 *
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 3f3326d876f7..4bb96ad9b0b1 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -2010,6 +2010,47 @@ ftrace_stub:
2010ENDPROC(return_to_handler) 2010ENDPROC(return_to_handler)
2011#endif /* CONFIG_FUNCTION_TRACER */ 2011#endif /* CONFIG_FUNCTION_TRACER */
2012 2012
2013#ifdef CONFIG_IRQSTACKS
2014/* void call_on_stack(unsigned long param1, void *func,
2015 unsigned long new_stack) */
2016ENTRY(call_on_stack)
2017 copy %sp, %r1
2018
2019 /* Regarding the HPPA calling conventions for function pointers,
2020 we assume the PIC register is not changed across call. For
2021 CONFIG_64BIT, the argument pointer is left to point at the
2022 argument region allocated for the call to call_on_stack. */
2023# ifdef CONFIG_64BIT
2024 /* Switch to new stack. We allocate two 128 byte frames. */
2025 ldo 256(%arg2), %sp
2026 /* Save previous stack pointer and return pointer in frame marker */
2027 STREG %rp, -144(%sp)
2028 /* Calls always use function descriptor */
2029 LDREG 16(%arg1), %arg1
2030 bve,l (%arg1), %rp
2031 STREG %r1, -136(%sp)
2032 LDREG -144(%sp), %rp
2033 bve (%rp)
2034 LDREG -136(%sp), %sp
2035# else
2036 /* Switch to new stack. We allocate two 64 byte frames. */
2037 ldo 128(%arg2), %sp
2038 /* Save previous stack pointer and return pointer in frame marker */
2039 STREG %r1, -68(%sp)
2040 STREG %rp, -84(%sp)
2041 /* Calls use function descriptor if PLABEL bit is set */
2042 bb,>=,n %arg1, 30, 1f
2043 depwi 0,31,2, %arg1
2044 LDREG 0(%arg1), %arg1
20451:
2046 be,l 0(%sr4,%arg1), %sr0, %r31
2047 copy %r31, %rp
2048 LDREG -84(%sp), %rp
2049 bv (%rp)
2050 LDREG -68(%sp), %sp
2051# endif /* CONFIG_64BIT */
2052ENDPROC(call_on_stack)
2053#endif /* CONFIG_IRQSTACKS */
2013 2054
2014get_register: 2055get_register:
2015 /* 2056 /*
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)
358#endif 358#endif
359} 359}
360 360
361#ifdef CONFIG_IRQSTACKS
362DEFINE_PER_CPU(union irq_stack_union, irq_stack_union);
363
364static void execute_on_irq_stack(void *func, unsigned long param1)
365{
366 unsigned long *irq_stack_start;
367 unsigned long irq_stack;
368 int cpu = smp_processor_id();
369
370 irq_stack_start = &per_cpu(irq_stack_union, cpu).stack[0];
371 irq_stack = (unsigned long) irq_stack_start;
372 irq_stack = ALIGN(irq_stack, 16); /* align for stack frame usage */
373
374 BUG_ON(*irq_stack_start); /* report bug if we were called recursive. */
375 *irq_stack_start = 1;
376
377 /* This is where we switch to the IRQ stack. */
378 call_on_stack(param1, func, irq_stack);
379
380 *irq_stack_start = 0;
381}
382#endif /* CONFIG_IRQSTACKS */
383
361/* ONLY called from entry.S:intr_extint() */ 384/* ONLY called from entry.S:intr_extint() */
362void do_cpu_irq_mask(struct pt_regs *regs) 385void do_cpu_irq_mask(struct pt_regs *regs)
363{ 386{
@@ -393,7 +416,12 @@ void do_cpu_irq_mask(struct pt_regs *regs)
393 } 416 }
394#endif 417#endif
395 stack_overflow_check(regs); 418 stack_overflow_check(regs);
419
420#ifdef CONFIG_IRQSTACKS
421 execute_on_irq_stack(&generic_handle_irq, irq);
422#else
396 generic_handle_irq(irq); 423 generic_handle_irq(irq);
424#endif /* CONFIG_IRQSTACKS */
397 425
398 out: 426 out:
399 irq_exit(); 427 irq_exit();