@@ -332,7 +332,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
EXC_XFER_LITE(0x400, handle_page_fault)
/* External interrupt */
- EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
+ EXCEPTION_IRQ(0x500, HardwareInterrupt, __do_irq, EXC_XFER_LITE)
/* Alignment exception */
. = 0x600
@@ -11,21 +11,41 @@
* task's thread_struct.
*/
-.macro EXCEPTION_PROLOG
+.macro EXCEPTION_PROLOG is_irq=0
mtspr SPRN_SPRG_SCRATCH0,r10
mtspr SPRN_SPRG_SCRATCH1,r11
mfcr r10
- EXCEPTION_PROLOG_1
+ EXCEPTION_PROLOG_1 is_irq=\is_irq
EXCEPTION_PROLOG_2
.endm
-.macro EXCEPTION_PROLOG_1
+.macro EXCEPTION_PROLOG_1 is_irq=0
mfspr r11,SPRN_SRR1 /* check whether user or kernel */
andi. r11,r11,MSR_PR
+ .if \is_irq
+ bne 2f
+ mfspr r11, SPRN_SPRG_THREAD
+ lwz r11, TASK_STACK - THREAD(r11)
+ xor r11, r11, r1
+ cmplwi cr7, r11, THREAD_SIZE - 1
+ tophys(r11, r1) /* use tophys(r1) if not thread stack */
+ bgt cr7, 1f
+2:
+#ifdef CONFIG_SMP
+ mfspr r11, SPRN_SPRG_THREAD
+ lwz r11, TASK_CPU - THREAD(r11)
+ slwi r11, r11, 3
+ addis r11, r11, (hardirq_ctx - PAGE_OFFSET)@ha
+#else
+ lis r11, (hardirq_ctx - PAGE_OFFSET)@ha
+#endif
+ lwz r11, (hardirq_ctx - PAGE_OFFSET)@l(r11)
+ .else
tophys(r11,r1) /* use tophys(r1) if kernel */
beq 1f
mfspr r11,SPRN_SPRG_THREAD
lwz r11,TASK_STACK-THREAD(r11)
+ .endif
addi r11,r11,THREAD_SIZE
tophys(r11,r11)
1: subi r11,r11,INT_FRAME_SIZE /* alloc exc. frame */
@@ -171,6 +191,12 @@
addi r3,r1,STACK_FRAME_OVERHEAD; \
xfer(n, hdlr)
+#define EXCEPTION_IRQ(n, label, hdlr, xfer) \
+ START_EXCEPTION(n, label) \
+ EXCEPTION_PROLOG is_irq=1; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ xfer(n, hdlr)
+
#define EXC_XFER_TEMPLATE(hdlr, trap, msr, tfer, ret) \
li r10,trap; \
stw r10,_TRAP(r11); \
@@ -315,7 +315,7 @@ _ENTRY(crit_srr1)
EXC_XFER_LITE(0x400, handle_page_fault)
/* 0x0500 - External Interrupt Exception */
- EXCEPTION(0x0500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
+ EXCEPTION_IRQ(0x0500, HardwareInterrupt, __do_irq, EXC_XFER_LITE)
/* 0x0600 - Alignment Exception */
START_EXCEPTION(0x0600, Alignment)
@@ -150,7 +150,7 @@ DataAccess:
InstructionAccess:
/* External interrupt */
- EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
+ EXCEPTION_IRQ(0x500, HardwareInterrupt, __do_irq, EXC_XFER_LITE)
/* Alignment exception */
. = 0x600
Exception entries run of kernel thread stack, then do_IRQ() switches to the IRQ stack. Instead of doing a first step of the thread stack, increasing the risk of stack overflow and spending time switch stacks two times when coming from userspace, set the stack to IRQ stack immediately in the EXCEPTION entry. In the same way as ARM64, consider that when the stack pointer is not within the kernel thread stack, it means it is already on IRQ stack. Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> --- arch/powerpc/kernel/head_32.S | 2 +- arch/powerpc/kernel/head_32.h | 32 +++++++++++++++++++++++++++++--- arch/powerpc/kernel/head_40x.S | 2 +- arch/powerpc/kernel/head_8xx.S | 2 +- 4 files changed, 32 insertions(+), 6 deletions(-)