From 85218827cc4ca900867807f19345418164ffc108 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 28 Apr 2008 16:21:22 +1000 Subject: [POWERPC] Add IRQSTACKS support on ppc32 This makes it possible to use separate stacks for hard and soft IRQs on 32-bit powerpc as well as on 64-bit. The code for 32-bit is just the 32-bit analog of the 64-bit code. * Added allocation and initialization of the irq stacks. We limit the stacks to be in lowmem for ppc32. * Implemented ppc32 versions of call_do_softirq() and call_handle_irq() to switch the stack pointers * Reworked how we do stack overflow detection. We now keep around the limit of the stack in the thread_struct and compare against the limit to see if we've overflowed. We can now use this on ppc64 if desired. [ paulus@samba.org: Fixed bug on 6xx where we need to reload r9 with the thread_info pointer. ] Signed-off-by: Kumar Gala Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/irq.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/kernel/irq.c') diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 425616f92d18..2f73f705d564 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -307,6 +307,7 @@ void do_IRQ(struct pt_regs *regs) if (curtp != irqtp) { struct irq_desc *desc = irq_desc + irq; void *handler = desc->handle_irq; + unsigned long saved_sp_limit = current->thread.ksp_limit; if (handler == NULL) handler = &__do_IRQ; irqtp->task = curtp->task; @@ -319,7 +320,10 @@ void do_IRQ(struct pt_regs *regs) (irqtp->preempt_count & ~SOFTIRQ_MASK) | (curtp->preempt_count & SOFTIRQ_MASK); + current->thread.ksp_limit = (unsigned long)irqtp + + _ALIGN_UP(sizeof(struct thread_info), 16); call_handle_irq(irq, desc, irqtp, handler); + current->thread.ksp_limit = saved_sp_limit; irqtp->task = NULL; @@ -352,9 +356,7 @@ void __init init_IRQ(void) { if (ppc_md.init_IRQ) ppc_md.init_IRQ(); -#ifdef CONFIG_PPC64 irq_ctx_init(); -#endif } @@ -383,11 +385,15 @@ void irq_ctx_init(void) static inline void do_softirq_onstack(void) { struct thread_info *curtp, *irqtp; + unsigned long saved_sp_limit = current->thread.ksp_limit; curtp = current_thread_info(); irqtp = softirq_ctx[smp_processor_id()]; irqtp->task = curtp->task; + current->thread.ksp_limit = (unsigned long)irqtp + + _ALIGN_UP(sizeof(struct thread_info), 16); call_do_softirq(irqtp); + current->thread.ksp_limit = saved_sp_limit; irqtp->task = NULL; } -- cgit v1.2.3