aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel
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/parisc/kernel
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/parisc/kernel')
-rw-r--r--arch/parisc/kernel/entry.S41
-rw-r--r--arch/parisc/kernel/irq.c28
2 files changed, 69 insertions, 0 deletions
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();